794 lines
24 KiB
C
794 lines
24 KiB
C
#ifdef SUPPORT_MS_EXTENSIONS
|
|
#pragma bss_seg(".usb.data.bss")
|
|
#pragma data_seg(".usb.data")
|
|
#pragma code_seg(".usb.text")
|
|
#pragma const_seg(".usb.text.const")
|
|
#pragma str_literal_override(".usb.text.const")
|
|
#endif
|
|
|
|
#include "system/includes.h"
|
|
#include "app_config.h"
|
|
#include "device_drive.h"
|
|
/* #include "os/os_compat.h" */
|
|
#include "system/event.h"
|
|
#include "clock_manager/clock_manager.h"
|
|
#if TCFG_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"
|
|
#include "host_uvc.h"
|
|
#include "usb/usb_task.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;
|
|
log_debug("%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) {
|
|
log_debug("%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) {
|
|
log_debug("%s %d ", __func__, ret);
|
|
}
|
|
return 0;
|
|
}
|
|
int usb_sem_del(struct usb_host_device *host_dev)
|
|
{
|
|
usb_dev usb_id = host_device2id(host_dev);
|
|
|
|
if (host_dev == NULL || host_dev->sem == NULL) {
|
|
return 0;
|
|
}
|
|
#if USB_HUB
|
|
if (host_dev->father == NULL) {
|
|
os_sem_del(host_dev->sem, 0);
|
|
}
|
|
#else
|
|
os_sem_del(host_dev->sem, 0);
|
|
#endif
|
|
log_debug("%s %x %x ", __func__, host_dev, host_dev->sem);
|
|
free(host_dev->sem);
|
|
host_dev->sem = NULL;
|
|
usb_host_free(usb_id);
|
|
return 0;
|
|
}
|
|
|
|
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_uvc_parse(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
|
{
|
|
log_info("find uvc @ interface %d", interface_num);
|
|
#if TCFG_HOST_UVC_ENABLE
|
|
return usb_uvc_parser(host_dev, interface_num, (u8 *)pBuf);
|
|
#else
|
|
return USB_DT_INTERFACE_SIZE;
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief usb_descriptor_parser
|
|
*
|
|
* @param device
|
|
* @param pBuf
|
|
* @param total_len
|
|
*
|
|
* @return
|
|
*/
|
|
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;
|
|
u32 have_find_valid_class = 0;
|
|
while (len < total_len) {
|
|
if (interface_num > MAX_HOST_INTERFACE) {
|
|
log_error("interface_num too much");
|
|
break;
|
|
}
|
|
|
|
struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf;
|
|
if (interface->bDescriptorType == USB_DT_INTERFACE) {
|
|
|
|
log_debug("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 if (interface->bInterfaceClass == USB_CLASS_VIDEO) {
|
|
i = _usb_uvc_parse(host_dev, interface_num, pBuf);
|
|
if (i < 0) {
|
|
log_error("---%s %d---", __func__, __LINE__);
|
|
len = total_len;
|
|
} else {
|
|
interface_num += 2;
|
|
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 int usb_event_notify(const struct usb_host_device *host_dev, u32 ev)
|
|
{
|
|
const usb_dev id = host_device2id(host_dev);
|
|
u32 event;
|
|
typedef struct {
|
|
char subdev[MAX_HOST_INTERFACE][8];
|
|
} subdev_t;
|
|
static subdev_t itf_set[USB_MAX_HW_NUM];
|
|
static u32 bmUsbEvent[USB_MAX_HW_NUM];
|
|
u8 have_post_event = 0;
|
|
u8 no_send_event = 0;
|
|
if (ev == 0) {
|
|
event = DEVICE_EVENT_IN;
|
|
} else if (ev == 1) {
|
|
event = DEVICE_EVENT_CHANGE;
|
|
} else {
|
|
event = DEVICE_EVENT_OUT;
|
|
goto __usb_event_out;
|
|
}
|
|
for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) {
|
|
memset(itf_set[id].subdev[i], 0, sizeof(itf_set[id].subdev[i]));
|
|
}
|
|
|
|
for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) {
|
|
no_send_event = 0;
|
|
/* memset(itf_set[id].subdev[i], 0, sizeof(itf_set[id].subdev[i])); */
|
|
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);
|
|
}
|
|
sprintf(itf_set[id].subdev[i], "udisk%d", id);
|
|
bmUsbEvent[id] |= BIT(0);
|
|
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);
|
|
}
|
|
sprintf(itf_set[id].subdev[i], "adb%d", id);
|
|
bmUsbEvent[id] |= BIT(1);
|
|
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);
|
|
}
|
|
sprintf(itf_set[id].subdev[i], "aoa%d", id);
|
|
bmUsbEvent[id] |= BIT(2);
|
|
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);
|
|
}
|
|
sprintf(itf_set[id].subdev[i], "hid%d", id);
|
|
bmUsbEvent[id] |= BIT(3);
|
|
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);
|
|
}
|
|
sprintf(itf_set[id].subdev[i], "audio%d", id);
|
|
bmUsbEvent[id] |= BIT(4);
|
|
break;
|
|
#endif
|
|
#if TCFG_HOST_UVC_ENABLE
|
|
case USB_CLASS_VIDEO:
|
|
if (have_post_event & BIT(5)) {
|
|
no_send_event = 1;
|
|
} else {
|
|
have_post_event |= BIT(5);
|
|
}
|
|
sprintf(itf_set[id].subdev[5], "uvc%d", id);
|
|
bmUsbEvent[id] |= BIT(5);
|
|
break;
|
|
#endif
|
|
|
|
}
|
|
|
|
//cppcheck-suppress knownConditionTrueFalse
|
|
/* if (!no_send_event && itf_set[id].subdev[i][0]) { */
|
|
if (!no_send_event) {
|
|
for (u8 k = 0; k < MAX_HOST_INTERFACE; k++) {
|
|
|
|
if (itf_set[id].subdev[k][0]) {
|
|
log_info("event %x interface %x class %x %s",
|
|
event,
|
|
i,
|
|
host_dev->interface_info[i]->ctrl->interface_class,
|
|
itf_set[id].subdev[k]);
|
|
|
|
/* printf("usb_host_mount notify >>>>>>>>>>>\n"); */
|
|
/* usb_driver_event_to_user(DEVICE_EVENT_FROM_USB_HOST, event, itf_set[id].subdev[i]); */
|
|
os_taskq_post_msg(USB_TASK_NAME, 3, USBSTACK_HOST_MSG, event, itf_set[id].subdev[k]);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
__usb_event_out:
|
|
if (event == DEVICE_EVENT_OUT) {
|
|
for (int i = 0; i < 32; i++) {
|
|
if (bmUsbEvent[id] & BIT(i)) {
|
|
bmUsbEvent[id] &= ~BIT(i);
|
|
if (itf_set[id].subdev[i][0]) {
|
|
have_post_event = 1;
|
|
/* usb_driver_event_to_user(DEVICE_EVENT_FROM_USB_HOST, event, itf_set[id].subdev[i]); */
|
|
os_taskq_post_msg(USB_TASK_NAME, 3, USBSTACK_HOST_MSG, event, itf_set[id].subdev[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (have_post_event) {
|
|
return DEV_ERR_NONE;
|
|
} else {
|
|
return DEV_ERR_UNKNOW_CLASS;
|
|
}
|
|
|
|
}
|
|
|
|
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;
|
|
u32 speed = USB_SPEED_FULL;
|
|
|
|
#if defined(FUSB_MODE) && FUSB_MODE
|
|
speed = USB_SPEED_FULL;
|
|
#elif defined(FUSB_MODE) && (FUSB_MODE == 0)
|
|
speed = USB_SPEED_HIGH;
|
|
#endif
|
|
usb_host_clock_lock();
|
|
for (int i = 0; i < retry; i++) {
|
|
usb_h_sie_init(usb_id);
|
|
ret = usb_host_init(usb_id, reset_delay, mount_timeout, speed);
|
|
if (ret) {
|
|
reset_delay += 10;
|
|
continue;
|
|
}
|
|
|
|
void *const ep0_dma = usb_h_alloc_ep_buffer(usb_id, 0, 64);
|
|
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;
|
|
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);
|
|
|
|
for (int itf = 0; itf < MAX_HOST_INTERFACE; itf++) {
|
|
if (host_dev->interface_info[itf]) {
|
|
if (host_dev->interface_info[itf]->ctrl->set_power) {
|
|
host_dev->interface_info[itf]->ctrl->set_power(host_dev, 1);
|
|
}
|
|
}
|
|
}
|
|
break;//succ
|
|
}
|
|
|
|
if (ret) {
|
|
goto __exit_fail;
|
|
}
|
|
private_data->status = 1;
|
|
return DEV_ERR_NONE;
|
|
|
|
__exit_fail:
|
|
log_error("usb_probe fail");
|
|
private_data->status = 0;
|
|
usb_sie_close(usb_id);
|
|
usb_host_clock_unlock(NULL);
|
|
return ret;
|
|
}
|
|
|
|
/* --------------------------------------------------------------------------*/
|
|
/**
|
|
* @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_sem_init(host_dev);
|
|
usb_h_isr_reg(usb_id, 1, 0);
|
|
|
|
|
|
ret = _usb_host_mount(usb_id, retry, reset_delay, mount_timeout);
|
|
usb_otg_resume(usb_id); //打开usb host之后恢复otg检测
|
|
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]) {
|
|
if (host_dev->interface_info[i]->ctrl->set_power) {
|
|
host_dev->interface_info[i]->ctrl->set_power(host_dev, 0);
|
|
}
|
|
if (host_dev->interface_info[i]->ctrl->release) {
|
|
host_dev->interface_info[i]->ctrl->release(host_dev);
|
|
}
|
|
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];
|
|
|
|
#if (TCFG_UDISK_ENABLE && UDISK_READ_512_ASYNC_ENABLE)
|
|
_usb_stor_async_wait_sem(host_dev);
|
|
#endif
|
|
ret = _usb_host_unmount(usb_id);
|
|
if (ret) {
|
|
goto __exit_fail;
|
|
}
|
|
usb_sem_del(host_dev);
|
|
|
|
/* printf("usb_host_unmount notify >>>>>>>>>>>\n"); */
|
|
usb_event_notify(host_dev, 2);
|
|
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;
|
|
|
|
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) {
|
|
usb_event_notify(host_dev, 1);
|
|
}
|
|
return DEV_ERR_NONE;
|
|
|
|
__exit_fail:
|
|
return ret;
|
|
}
|
|
|
|
int usb_host_force_reset(const usb_dev usb_id)
|
|
{
|
|
//预留以后加上hub的处理
|
|
usb_h_force_reset(usb_id);
|
|
return 0;
|
|
}
|
|
|
|
static u16 clock_lock_timer;
|
|
void usb_host_clock_unlock(void *priv)
|
|
{
|
|
#ifdef CONFIG_CPU_BR27
|
|
if (clock_lock_timer) {
|
|
clock_unlock("usb_host");
|
|
sys_timeout_del(clock_lock_timer);
|
|
clock_lock_timer = 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void usb_host_clock_lock(void)
|
|
{
|
|
#ifdef CONFIG_CPU_BR27
|
|
if (clock_lock_timer) {
|
|
sys_timer_re_run(clock_lock_timer);
|
|
return;
|
|
}
|
|
clock_lock("usb_host", 320000000);
|
|
clock_lock_timer = sys_timeout_add(NULL, usb_host_clock_unlock, 3000);
|
|
#endif
|
|
}
|
|
#endif
|