742 lines
22 KiB
C
742 lines
22 KiB
C
#include "includes.h"
|
|
#include "app_config.h"
|
|
#include "device_drive.h"
|
|
/* #include "os/os_compat.h" */
|
|
#if USB_HOST_ENABLE
|
|
#include "usb_config.h"
|
|
#include "usb/host/usb_host.h"
|
|
#include "usb/usb_phy.h"
|
|
#include "usb_ctrl_transfer.h"
|
|
#include "usb_storage.h"
|
|
#include "adb.h"
|
|
#include "aoa.h"
|
|
#include "hid.h"
|
|
#include "audio.h"
|
|
|
|
#if TCFG_USB_APPLE_DOCK_EN
|
|
#include "apple_dock/iAP.h"
|
|
#include "apple_mfi.h"
|
|
#endif
|
|
|
|
#define LOG_TAG_CONST USB
|
|
#define LOG_TAG "[mount]"
|
|
#define LOG_ERROR_ENABLE
|
|
#define LOG_DEBUG_ENABLE
|
|
#define LOG_INFO_ENABLE
|
|
/* #define LOG_DUMP_ENABLE */
|
|
#define LOG_CLI_ENABLE
|
|
#include "debug.h"
|
|
|
|
|
|
static struct usb_host_device host_devices[USB_MAX_HW_NUM];// SEC(.usb_h_bss);
|
|
|
|
#define device_to_usbdev(device) ((struct usb_host_device *)((device)->private_data))
|
|
|
|
|
|
int host_dev_status(const struct usb_host_device *host_dev)
|
|
{
|
|
return ((host_dev)->private_data.status);
|
|
}
|
|
|
|
u32 host_device2id(const struct usb_host_device *host_dev)
|
|
{
|
|
#if USB_MAX_HW_NUM > 1
|
|
return ((host_dev)->private_data.usb_id);
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
const struct usb_host_device *host_id2device(const usb_dev id)
|
|
{
|
|
#if USB_MAX_HW_NUM > 1
|
|
return &host_devices[id];
|
|
#else
|
|
return &host_devices[0];
|
|
#endif
|
|
}
|
|
int usb_sem_init(struct usb_host_device *host_dev)
|
|
{
|
|
usb_dev usb_id = host_device2id(host_dev);
|
|
|
|
usb_host_config(usb_id);
|
|
|
|
OS_SEM *sem = zalloc(sizeof(OS_SEM));
|
|
ASSERT(sem, "usb alloc sem error");
|
|
host_dev->sem = sem;
|
|
g_printf("%s %x %x ", __func__, host_dev, sem);
|
|
os_sem_create(host_dev->sem, 0);
|
|
return 0;
|
|
}
|
|
int usb_sem_pend(struct usb_host_device *host_dev, u32 timeout)
|
|
{
|
|
if (host_dev->sem == NULL) {
|
|
return 1;
|
|
}
|
|
int ret = os_sem_pend(host_dev->sem, timeout);
|
|
if (ret) {
|
|
r_printf("%s %d ", __func__, ret);
|
|
}
|
|
return ret;
|
|
}
|
|
int usb_sem_post(struct usb_host_device *host_dev)
|
|
{
|
|
if (host_dev->sem == NULL) {
|
|
return 1;
|
|
}
|
|
int ret = os_sem_post(host_dev->sem);
|
|
if (ret) {
|
|
r_printf("%s %d ", __func__, ret);
|
|
}
|
|
return 0;
|
|
}
|
|
int usb_sem_del(struct usb_host_device *host_dev)
|
|
{
|
|
usb_dev usb_id = host_device2id(host_dev);
|
|
|
|
r_printf("1");
|
|
if (host_dev->sem == NULL) {
|
|
return 0;
|
|
}
|
|
r_printf("2");
|
|
r_printf("3");
|
|
#if USB_HUB
|
|
if (host_dev && host_ep->sem && host_dev->father == NULL) {
|
|
os_sem_del(host_dev->sem);
|
|
}
|
|
#else
|
|
if (host_dev && host_dev->sem) {
|
|
os_sem_del(host_dev->sem, 0);
|
|
}
|
|
#endif
|
|
r_printf("4");
|
|
g_printf("%s %x %x ", __func__, host_dev, host_dev->sem);
|
|
free(host_dev->sem);
|
|
r_printf("5");
|
|
host_dev->sem = NULL;
|
|
r_printf("6");
|
|
usb_host_free(usb_id);
|
|
r_printf("7");
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief usb_descriptor_parser
|
|
*
|
|
* @param device
|
|
* @param pBuf
|
|
* @param total_len
|
|
*
|
|
* @return
|
|
*/
|
|
static int _usb_msd_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
|
{
|
|
log_info("find udisk @ interface %d", interface_num);
|
|
#if TCFG_UDISK_ENABLE
|
|
return usb_msd_parser(host_dev, interface_num, pBuf);
|
|
#else
|
|
return USB_DT_INTERFACE_SIZE;
|
|
#endif
|
|
}
|
|
static int _usb_apple_mfi_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
|
{
|
|
log_info("find udisk @ interface %d", interface_num);
|
|
#if TCFG_USB_APPLE_DOCK_EN
|
|
return usb_apple_mfi_parser(host_dev, interface_num, pBuf);
|
|
#else
|
|
return USB_DT_INTERFACE_SIZE;
|
|
#endif
|
|
}
|
|
static int _usb_adb_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
|
{
|
|
log_info("find adb @ interface %d", interface_num);
|
|
#if TCFG_ADB_ENABLE
|
|
return usb_adb_parser(host_dev, interface_num, pBuf);
|
|
#else
|
|
return USB_DT_INTERFACE_SIZE;
|
|
#endif
|
|
}
|
|
static int _usb_aoa_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
|
{
|
|
log_info("find aoa @ interface %d", interface_num);
|
|
#if TCFG_AOA_ENABLE
|
|
return usb_aoa_parser(host_dev, interface_num, pBuf);
|
|
#else
|
|
return USB_DT_INTERFACE_SIZE;
|
|
#endif
|
|
|
|
}
|
|
static int _usb_hid_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
|
{
|
|
log_info("find hid @ interface %d", interface_num);
|
|
#if TCFG_HID_HOST_ENABLE
|
|
return usb_hid_parser(host_dev, interface_num, pBuf);
|
|
#else
|
|
return USB_DT_INTERFACE_SIZE;
|
|
#endif
|
|
}
|
|
static int _usb_audio_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
|
{
|
|
log_info("find audio @ interface %d", interface_num);
|
|
#if TCFG_HOST_AUDIO_ENABLE
|
|
return usb_audio_parser(host_dev, interface_num, pBuf);
|
|
#else
|
|
return USB_DT_INTERFACE_SIZE;
|
|
#endif
|
|
}
|
|
static int _usb_adb_interface_ptp_mtp_parse(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
|
{
|
|
log_info("find adbmtp @ interface %d", interface_num);
|
|
#if TCFG_ADB_ENABLE
|
|
return usb_adb_interface_ptp_mtp_parse(host_dev, interface_num, pBuf);
|
|
#else
|
|
return USB_DT_INTERFACE_SIZE;
|
|
#endif
|
|
}
|
|
static int usb_descriptor_parser(struct usb_host_device *host_dev, const u8 *pBuf, u32 total_len, struct usb_device_descriptor *device_desc)
|
|
{
|
|
int len = 0;
|
|
u8 interface_num = 0;
|
|
struct usb_private_data *private_data = &host_dev->private_data;
|
|
|
|
struct usb_config_descriptor *cfg_desc = (struct usb_config_descriptor *)pBuf;
|
|
|
|
if (cfg_desc->bDescriptorType != USB_DT_CONFIG ||
|
|
cfg_desc->bLength < USB_DT_CONFIG_SIZE) {
|
|
log_error("invalid descriptor for config bDescriptorType = %d bLength= %d",
|
|
cfg_desc->bDescriptorType, cfg_desc->bLength);
|
|
return -USB_DT_CONFIG;
|
|
}
|
|
|
|
log_info("idVendor %x idProduct %x", device_desc->idVendor, device_desc->idProduct);
|
|
|
|
len += USB_DT_CONFIG_SIZE;
|
|
pBuf += USB_DT_CONFIG_SIZE;
|
|
int i = 0;
|
|
u32 have_find_valid_class = 0;
|
|
while (len < total_len) {
|
|
if (interface_num > 4) {
|
|
log_error("interface_num too much");
|
|
break;
|
|
}
|
|
|
|
struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf;
|
|
if (interface->bDescriptorType == USB_DT_INTERFACE) {
|
|
|
|
printf("inf class %x subclass %x ep %d",
|
|
interface->bInterfaceClass, interface->bInterfaceSubClass, interface->bNumEndpoints);
|
|
|
|
if (interface->bInterfaceClass == USB_CLASS_MASS_STORAGE) {
|
|
i = _usb_msd_parser(host_dev, interface_num, pBuf);
|
|
if (i < 0) {
|
|
log_error("---%s %d---", __func__, __LINE__);
|
|
len = total_len;
|
|
} else {
|
|
interface_num++;
|
|
len += i;
|
|
pBuf += i;
|
|
have_find_valid_class = true;
|
|
}
|
|
} else if ((device_desc->idVendor == 0x05AC) &&
|
|
((device_desc->idProduct & 0xff00) == 0x1200)) {
|
|
i = _usb_apple_mfi_parser(host_dev, interface_num, pBuf);
|
|
if (i < 0) {
|
|
log_error("---%s %d---", __func__, __LINE__);
|
|
len = total_len;
|
|
} else {
|
|
interface_num++;
|
|
len += i;
|
|
pBuf += i;
|
|
have_find_valid_class = true;
|
|
}
|
|
} else if (interface->bInterfaceClass == USB_CLASS_AUDIO) {
|
|
i = _usb_audio_parser(host_dev, interface_num, pBuf);
|
|
if (i < 0) {
|
|
log_error("---%s %d---", __func__, __LINE__);
|
|
len = total_len;
|
|
} else {
|
|
interface_num++;
|
|
len += i;
|
|
pBuf += i;
|
|
have_find_valid_class = true;
|
|
}
|
|
} else if ((interface->bInterfaceClass == 0xff) &&
|
|
(interface->bInterfaceSubClass == USB_CLASS_ADB)) {
|
|
i = _usb_adb_parser(host_dev, interface_num, pBuf);
|
|
if (i < 0) {
|
|
log_error("---%s %d---", __func__, __LINE__);
|
|
len = total_len;
|
|
} else {
|
|
interface_num++;
|
|
len += i;
|
|
pBuf += i;
|
|
have_find_valid_class = true;
|
|
}
|
|
} else if ((device_desc->idVendor == 0x18d1) &&
|
|
((device_desc->idProduct & 0x2d00) == 0x2d00)) {
|
|
i = _usb_aoa_parser(host_dev, interface_num, pBuf);
|
|
if (i < 0) {
|
|
log_error("---%s %d---", __func__, __LINE__);
|
|
len = total_len;
|
|
} else {
|
|
interface_num++;
|
|
len += i;
|
|
pBuf += i;
|
|
have_find_valid_class = true;
|
|
}
|
|
} else if (interface->bInterfaceClass == USB_CLASS_HID) {
|
|
i = _usb_hid_parser(host_dev, interface_num, pBuf);
|
|
if (i < 0) {
|
|
log_error("---%s %d---", __func__, __LINE__);
|
|
len = total_len;
|
|
} else {
|
|
interface_num++;
|
|
len += i;
|
|
pBuf += i;
|
|
have_find_valid_class = true;
|
|
}
|
|
} else if ((interface->bNumEndpoints == 3) &&
|
|
(interface->bInterfaceClass == 0xff || interface->bInterfaceClass == 0x06)) {
|
|
i = _usb_adb_interface_ptp_mtp_parse(host_dev, interface_num, pBuf);
|
|
if (i < 0) {
|
|
log_error("---%s %d---", __func__, __LINE__);
|
|
len = total_len;
|
|
} else {
|
|
interface_num++;
|
|
len += i;
|
|
pBuf += i;
|
|
}
|
|
have_find_valid_class = true;
|
|
} else if ((interface->bInterfaceClass == 0xff) &&
|
|
(interface->bInterfaceSubClass == 0xff)) {
|
|
i = _usb_aoa_parser(host_dev, interface_num, pBuf);
|
|
if (i < 0) {
|
|
log_error("---%s %d---", __func__, __LINE__);
|
|
len = total_len;
|
|
} else {
|
|
interface_num++;
|
|
len += i;
|
|
pBuf += i;
|
|
}
|
|
have_find_valid_class = true;
|
|
|
|
} else {
|
|
log_info("find unsupport [class %x subClass %x] @ interface %d",
|
|
interface->bInterfaceClass,
|
|
interface->bInterfaceSubClass,
|
|
interface_num);
|
|
|
|
len += USB_DT_INTERFACE_SIZE;
|
|
pBuf += USB_DT_INTERFACE_SIZE;
|
|
}
|
|
} else {
|
|
/* log_error("unknown section %d %d", len, pBuf[0]); */
|
|
if (pBuf[0]) {
|
|
len += pBuf[0];
|
|
pBuf += pBuf[0];
|
|
} else {
|
|
len = total_len;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
log_debug("len %d total_len %d", len, total_len);
|
|
return !have_find_valid_class;
|
|
}
|
|
|
|
|
|
/* --------------------------------------------------------------------------*/
|
|
/**
|
|
* @brief usb_host_suspend
|
|
*
|
|
* @param usb
|
|
*
|
|
* @return
|
|
*/
|
|
/* --------------------------------------------------------------------------*/
|
|
void usb_host_suspend(const usb_dev usb_id)
|
|
{
|
|
usb_h_entry_suspend(usb_id);
|
|
}
|
|
|
|
void usb_host_resume(const usb_dev usb_id)
|
|
{
|
|
usb_h_resume(usb_id);
|
|
}
|
|
|
|
static u32 _usb_host_mount(const usb_dev usb_id, u32 retry, u32 reset_delay, u32 mount_timeout)
|
|
{
|
|
u32 ret = DEV_ERR_NONE;
|
|
struct usb_host_device *host_dev = &host_devices[usb_id];
|
|
struct usb_private_data *private_data = &host_dev->private_data;
|
|
|
|
|
|
for (int i = 0; i < retry; i++) {
|
|
usb_h_sie_init(usb_id);
|
|
ret = usb_host_init(usb_id, reset_delay, mount_timeout);
|
|
if (ret) {
|
|
reset_delay += 10;
|
|
continue;
|
|
}
|
|
|
|
void *const ep0_dma = usb_h_get_ep_buffer(usb_id, 0);
|
|
usb_set_dma_taddr(usb_id, 0, ep0_dma);
|
|
|
|
usb_sie_enable(usb_id);//enable sie intr
|
|
usb_mdelay(reset_delay);
|
|
|
|
/**********get device descriptor*********/
|
|
struct usb_device_descriptor device_desc;
|
|
private_data->usb_id = usb_id;
|
|
private_data->status = 0;
|
|
private_data->devnum = 0;
|
|
private_data->ep0_max_packet_size = 8;
|
|
ret = usb_get_device_descriptor(host_dev, &device_desc);
|
|
|
|
/**********set address*********/
|
|
usb_mdelay(20);
|
|
u8 devnum = rand32() % 16 + 1;
|
|
ret = set_address(host_dev, devnum);
|
|
check_usb_mount(ret);
|
|
private_data->devnum = devnum ;
|
|
|
|
/**********get device descriptor*********/
|
|
usb_mdelay(20);
|
|
ret = usb_get_device_descriptor(host_dev, &device_desc);
|
|
check_usb_mount(ret);
|
|
private_data->ep0_max_packet_size = device_desc.bMaxPacketSize0;
|
|
|
|
/**********get config descriptor*********/
|
|
struct usb_config_descriptor cfg_desc;
|
|
ret = get_config_descriptor(host_dev, &cfg_desc, USB_DT_CONFIG_SIZE);
|
|
check_usb_mount(ret);
|
|
|
|
#if USB_H_MALLOC_ENABLE
|
|
u8 *desc_buf = zalloc(cfg_desc.wTotalLength + 16);
|
|
ASSERT(desc_buf, "desc_buf");
|
|
#else
|
|
u8 desc_buf[128] = {0};
|
|
cfg_desc.wTotalLength = min(sizeof(desc_buf), cfg_desc.wTotalLength);
|
|
#endif
|
|
|
|
ret = get_config_descriptor(host_dev, desc_buf, cfg_desc.wTotalLength);
|
|
check_usb_mount(ret);
|
|
|
|
/**********set configuration*********/
|
|
ret = set_configuration(host_dev);
|
|
/* printf_buf(desc_buf, cfg_desc.wTotalLength); */
|
|
ret |= usb_descriptor_parser(host_dev, desc_buf, cfg_desc.wTotalLength, &device_desc);
|
|
#if USB_H_MALLOC_ENABLE
|
|
log_info("free:desc_buf= %x\n", desc_buf);
|
|
free(desc_buf);
|
|
#endif
|
|
check_usb_mount(ret);
|
|
|
|
break;//succ
|
|
}
|
|
|
|
if (ret) {
|
|
goto __exit_fail;
|
|
}
|
|
private_data->status = 1;
|
|
return DEV_ERR_NONE;
|
|
|
|
__exit_fail:
|
|
printf("usb_probe fail");
|
|
private_data->status = 0;
|
|
usb_sie_close(usb_id);
|
|
return ret;
|
|
}
|
|
static int usb_event_notify(const struct usb_host_device *host_dev, u32 ev)
|
|
{
|
|
const usb_dev id = host_device2id(host_dev);
|
|
struct sys_event event;
|
|
if (ev == 0) {
|
|
event.u.dev.event = DEVICE_EVENT_IN;
|
|
} else {
|
|
event.u.dev.event = DEVICE_EVENT_CHANGE;
|
|
}
|
|
u8 have_post_event = 0;
|
|
u8 no_send_event;
|
|
for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) {
|
|
no_send_event = 0;
|
|
event.u.dev.value = 0;
|
|
if (host_dev->interface_info[i]) {
|
|
switch (host_dev->interface_info[i]->ctrl->interface_class) {
|
|
#if TCFG_UDISK_ENABLE
|
|
case USB_CLASS_MASS_STORAGE:
|
|
if (have_post_event & BIT(0)) {
|
|
no_send_event = 1;
|
|
} else {
|
|
have_post_event |= BIT(0);
|
|
}
|
|
if (id == 0) {
|
|
event.u.dev.value = (int)"udisk0";
|
|
} else {
|
|
event.u.dev.value = (int)"udisk1";
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
#if TCFG_ADB_ENABLE
|
|
case USB_CLASS_ADB:
|
|
if (have_post_event & BIT(1)) {
|
|
no_send_event = 1;
|
|
} else {
|
|
have_post_event |= BIT(1);
|
|
}
|
|
if (id == 0) {
|
|
event.u.dev.value = (int)"adb0";
|
|
} else {
|
|
event.u.dev.value = (int)"adb1";
|
|
}
|
|
break;
|
|
#endif
|
|
#if TCFG_AOA_ENABLE
|
|
case USB_CLASS_AOA:
|
|
if (have_post_event & BIT(2)) {
|
|
no_send_event = 1;
|
|
} else {
|
|
have_post_event |= BIT(2);
|
|
}
|
|
if (id == 0) {
|
|
event.u.dev.value = (int)"aoa0";
|
|
} else {
|
|
event.u.dev.value = (int)"aoa1";
|
|
}
|
|
break;
|
|
#endif
|
|
#if TCFG_HID_HOST_ENABLE
|
|
case USB_CLASS_HID:
|
|
if (have_post_event & BIT(3)) {
|
|
no_send_event = 1;
|
|
} else {
|
|
have_post_event |= BIT(3);
|
|
}
|
|
if (id == 0) {
|
|
event.u.dev.value = (int)"hid0";
|
|
} else {
|
|
event.u.dev.value = (int)"hid1";
|
|
}
|
|
break;
|
|
#endif
|
|
#if TCFG_HOST_AUDIO_ENABLE
|
|
case USB_CLASS_AUDIO:
|
|
if (have_post_event & BIT(4)) {
|
|
no_send_event = 1;
|
|
} else {
|
|
have_post_event |= BIT(4);
|
|
}
|
|
if (id == 0) {
|
|
event.u.dev.value = (int)"audio0";
|
|
} else {
|
|
event.u.dev.value = (int)"audio1";
|
|
}
|
|
break;
|
|
#endif
|
|
}
|
|
|
|
if (!no_send_event && event.u.dev.value) {
|
|
log_info("event %x interface %x class %x %s",
|
|
event.u.dev.event, i,
|
|
host_dev->interface_info[i]->ctrl->interface_class,
|
|
(const char *)event.u.dev.value);
|
|
|
|
/* printf("usb_host_mount notify >>>>>>>>>>>\n"); */
|
|
event.arg = (void *)DEVICE_EVENT_FROM_USB_HOST;
|
|
event.type = SYS_DEVICE_EVENT;
|
|
sys_event_notify(&event);
|
|
}
|
|
}
|
|
}
|
|
if (have_post_event) {
|
|
return DEV_ERR_NONE;
|
|
} else {
|
|
return DEV_ERR_UNKNOW_CLASS;
|
|
}
|
|
|
|
}
|
|
|
|
const char *usb_host_valid_class_to_dev(const usb_dev id, u32 usbclass)
|
|
{
|
|
#if USB_MAX_HW_NUM > 1
|
|
const usb_dev usb_id = id;
|
|
#else
|
|
const usb_dev usb_id = 0;
|
|
#endif
|
|
struct usb_host_device *host_dev = &host_devices[usb_id];
|
|
u32 itf_class;
|
|
|
|
for (int i = 0; i < MAX_HOST_INTERFACE; i++) {
|
|
if (host_dev->interface_info[i] &&
|
|
host_dev->interface_info[i]->ctrl) {
|
|
itf_class = host_dev->interface_info[i]->ctrl->interface_class;
|
|
if (itf_class == usbclass) {
|
|
switch (itf_class) {
|
|
case USB_CLASS_MASS_STORAGE:
|
|
if (usb_id == 0) {
|
|
return "udisk0";
|
|
} else if (usb_id == 1) {
|
|
return "udisk1";
|
|
}
|
|
break;
|
|
case USB_CLASS_ADB:
|
|
if (usb_id == 0) {
|
|
return "adb0";
|
|
} else if (usb_id == 1) {
|
|
return "adb1";
|
|
}
|
|
break;
|
|
case USB_CLASS_AOA:
|
|
if (usb_id == 0) {
|
|
return "aoa0";
|
|
} else if (usb_id == 1) {
|
|
return "aoa1";
|
|
}
|
|
break;
|
|
case USB_CLASS_HID:
|
|
if (usb_id == 0) {
|
|
return "hid0";
|
|
} else if (usb_id == 1) {
|
|
return "hid1";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/* --------------------------------------------------------------------------*/
|
|
/**
|
|
* @brief usb_host_mount
|
|
*
|
|
* @param usb
|
|
*
|
|
* @return
|
|
*/
|
|
/* --------------------------------------------------------------------------*/
|
|
u32 usb_host_mount(const usb_dev id, u32 retry, u32 reset_delay, u32 mount_timeout)
|
|
{
|
|
#if USB_MAX_HW_NUM > 1
|
|
const usb_dev usb_id = id;
|
|
#else
|
|
const usb_dev usb_id = 0;
|
|
#endif
|
|
|
|
u32 ret;
|
|
struct usb_host_device *host_dev = &host_devices[usb_id];
|
|
memset(host_dev, 0, sizeof(*host_dev));
|
|
|
|
host_dev->private_data.usb_id = id;
|
|
usb_otg_resume(usb_id); //打开usb host之后恢复otg检测
|
|
|
|
usb_sem_init(host_dev);
|
|
usb_h_isr_reg(usb_id, 1, 0);
|
|
|
|
|
|
ret = _usb_host_mount(usb_id, retry, reset_delay, mount_timeout);
|
|
if (ret) {
|
|
goto __exit_fail;
|
|
}
|
|
return usb_event_notify(host_dev, 0);
|
|
|
|
__exit_fail:
|
|
usb_sie_disable(usb_id);
|
|
usb_sem_del(host_dev);
|
|
return ret;
|
|
}
|
|
|
|
static u32 _usb_host_unmount(const usb_dev usb_id)
|
|
{
|
|
struct usb_host_device *host_dev = &host_devices[usb_id];
|
|
|
|
struct usb_private_data *private_data = &host_dev->private_data;
|
|
private_data->status = 0;
|
|
|
|
usb_sem_post(host_dev);//拔掉设备时,让读写线程快速释放
|
|
|
|
for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) {
|
|
if (host_dev->interface_info[i]) {
|
|
host_dev->interface_info[i]->ctrl->set_power(host_dev, -1);
|
|
host_dev->interface_info[i] = NULL;
|
|
}
|
|
}
|
|
|
|
usb_sie_close(usb_id);
|
|
return DEV_ERR_NONE;
|
|
}
|
|
|
|
/* --------------------------------------------------------------------------*/
|
|
/**
|
|
* @brief usb_host_unmount
|
|
*
|
|
* @param usb
|
|
*
|
|
* @return
|
|
*/
|
|
/* --------------------------------------------------------------------------*/
|
|
/* u32 usb_host_unmount(const usb_dev usb_id, char *device_name) */
|
|
u32 usb_host_unmount(const usb_dev id)
|
|
{
|
|
#if USB_MAX_HW_NUM > 1
|
|
const usb_dev usb_id = id;
|
|
#else
|
|
const usb_dev usb_id = 0;
|
|
#endif
|
|
u32 ret;
|
|
struct usb_host_device *host_dev = &host_devices[usb_id];
|
|
struct sys_event event;
|
|
|
|
ret = _usb_host_unmount(usb_id);
|
|
if (ret) {
|
|
goto __exit_fail;
|
|
}
|
|
usb_sem_del(host_dev);
|
|
|
|
/* printf("usb_host_unmount notify >>>>>>>>>>>\n"); */
|
|
event.arg = (void *)DEVICE_EVENT_FROM_USB_HOST;
|
|
event.type = SYS_DEVICE_EVENT;
|
|
event.u.dev.event = DEVICE_EVENT_OUT;
|
|
sys_event_notify(&event);
|
|
return DEV_ERR_NONE;
|
|
|
|
__exit_fail:
|
|
return ret;
|
|
}
|
|
|
|
u32 usb_host_remount(const usb_dev id, u32 retry, u32 delay, u32 ot, u8 notify)
|
|
{
|
|
#if USB_MAX_HW_NUM > 1
|
|
const usb_dev usb_id = id;
|
|
#else
|
|
const usb_dev usb_id = 0;
|
|
#endif
|
|
u32 ret;
|
|
struct sys_event event;
|
|
|
|
ret = _usb_host_unmount(usb_id);
|
|
if (ret) {
|
|
goto __exit_fail;
|
|
}
|
|
|
|
struct usb_host_device *host_dev = &host_devices[usb_id];
|
|
os_sem_set(host_dev->sem, 0);
|
|
|
|
ret = _usb_host_mount(usb_id, retry, delay, ot);
|
|
if (ret) {
|
|
goto __exit_fail;
|
|
}
|
|
|
|
if (notify) {
|
|
struct usb_host_device *host_dev = &host_devices[usb_id];
|
|
usb_event_notify(host_dev, 1);
|
|
}
|
|
return DEV_ERR_NONE;
|
|
|
|
__exit_fail:
|
|
return ret;
|
|
}
|
|
#endif
|