diff --git a/components/drivers/include/drivers/usb_device.h b/components/drivers/include/drivers/usb_device.h index f0e0989ce..2f464def3 100644 --- a/components/drivers/include/drivers/usb_device.h +++ b/components/drivers/include/drivers/usb_device.h @@ -146,6 +146,11 @@ enum udev_msg_type USB_MSG_DATA_NOTIFY, USB_MSG_SOF, USB_MSG_RESET, + /* we don't need to add a "PLUG_IN" event because after the cable is + * plugged in(before any SETUP) the classed have nothing to do. If the host + * is ready, it will send RESET and we will have USB_MSG_RESET. So, a RESET + * should reset and run the class while plug_in is not. */ + USB_MSG_PLUG_OUT, }; typedef enum udev_msg_type udev_msg_type; diff --git a/components/drivers/usb/usbdevice/core/core.c b/components/drivers/usb/usbdevice/core/core.c index 45264033a..48fc69895 100644 --- a/components/drivers/usb/usbdevice/core/core.c +++ b/components/drivers/usb/usbdevice/core/core.c @@ -666,6 +666,60 @@ rt_err_t _sof_notify(udevice_t device) return RT_EOK; } +/** + * This function will stop all class. + * + * @param device the usb device object. + * + * @return RT_EOK. + */ +rt_err_t _stop_notify(udevice_t device) +{ + struct rt_list_node *i; + uclass_t cls; + + RT_ASSERT(device != RT_NULL); + + /* to notity every class that sof event comes */ + for (i = device->curr_cfg->cls_list.next; + i != &device->curr_cfg->cls_list; + i = i->next) + { + cls = (uclass_t)rt_list_entry(i, struct uclass, list); + if(cls->ops->stop != RT_NULL) + cls->ops->stop(device, cls); + } + + return RT_EOK; +} + +/** + * This function will run all class. + * + * @param device the usb device object. + * + * @return RT_EOK. + */ +rt_err_t _run_notify(udevice_t device) +{ + struct rt_list_node *i; + uclass_t cls; + + RT_ASSERT(device != RT_NULL); + + /* to notity every class that sof event comes */ + for (i = device->curr_cfg->cls_list.next; + i != &device->curr_cfg->cls_list; + i = i->next) + { + cls = (uclass_t)rt_list_entry(i, struct uclass, list); + if(cls->ops->run != RT_NULL) + cls->ops->run(device, cls); + } + + return RT_EOK; +} + /** * This function will reset all class. * @@ -680,17 +734,8 @@ rt_err_t _reset_notify(udevice_t device) RT_ASSERT(device != RT_NULL); - /* to notity every class that sof event comes */ - for (i=device->curr_cfg->cls_list.next; - i!=&device->curr_cfg->cls_list; i=i->next) - { - cls = (uclass_t)rt_list_entry(i, struct uclass, list); - if(cls->ops->stop != RT_NULL) - cls->ops->stop(device, cls); - - if(cls->ops->run != RT_NULL) - cls->ops->run(device, cls); - } + _stop_notify(); + _run_notify(); return RT_EOK; } @@ -1402,6 +1447,10 @@ static void rt_usbd_thread_entry(void* parameter) _sof_notify(device); break; case USB_MSG_DATA_NOTIFY: + /* some buggy drivers will have USB_MSG_DATA_NOTIFY before the core + * got configured. */ + if (device->state != USB_STATE_CONFIGURED) + break; ep = rt_usbd_find_endpoint(device, &cls, msg.content.ep_msg.ep_addr); if(ep != RT_NULL) ep->handler(device, cls, msg.content.ep_msg.size); @@ -1415,6 +1464,9 @@ static void rt_usbd_thread_entry(void* parameter) if (device->state == USB_STATE_ADDRESS) _reset_notify(device); break; + case USB_MSG_PLUG_OUT: + _stop_notify(device); + break; default: rt_kprintf("unknown msg type\n"); break;