diff --git a/components/drivers/include/drivers/usb_common.h b/components/drivers/include/drivers/usb_common.h index 866909f3a71e1d0e988595a0995d4bb69cd3deb4..08462d9244891139f5a3e7794ecd48063cc271fa 100644 --- a/components/drivers/include/drivers/usb_common.h +++ b/components/drivers/include/drivers/usb_common.h @@ -21,6 +21,7 @@ * Date Author Notes * 2012-10-01 Yi Qiu first version * 2013-04-26 aozima add DEVICEQUALIFIER support. + * 2017-11-15 ZYH fix ep0 transform error */ #ifndef __USB_COMMON_H__ @@ -241,6 +242,16 @@ typedef enum USB_STATE_SUSPENDED }udevice_state_t; +typedef enum +{ + STAGE_IDLE, + STAGE_SETUP, + STAGE_STATUS_IN, + STAGE_STATUS_OUT, + STAGE_DIN, + STAGE_DOUT +} uep0_stage_t; + #pragma pack(1) struct usb_descriptor diff --git a/components/drivers/include/drivers/usb_device.h b/components/drivers/include/drivers/usb_device.h index fbbae7edb918827bd4c6c1db823b05c52f4816c2..5e2417e90da66b12c75512209a5eaecf2132bba7 100644 --- a/components/drivers/include/drivers/usb_device.h +++ b/components/drivers/include/drivers/usb_device.h @@ -22,6 +22,7 @@ * 2012-10-01 Yi Qiu first version * 2012-12-12 heyuanjie87 change endpoint and function handler * 2013-04-26 aozima add DEVICEQUALIFIER support. + * 2017-11-15 ZYH fix ep0 transform error */ #ifndef __USB_DEVICE_H__ @@ -137,6 +138,7 @@ struct udcd struct rt_device parent; const struct udcd_ops* ops; struct uendpoint ep0; + uep0_stage_t stage; struct ep_id* ep_pool; }; typedef struct udcd* udcd_t; diff --git a/components/drivers/usb/usbdevice/core/core.c b/components/drivers/usb/usbdevice/core/core.c index 6880f931f009b8d55993ac94b101771b8b8f174c..a3caa60f99951fb71883f2ae5a1b6ffe3c88ec9a 100644 --- a/components/drivers/usb/usbdevice/core/core.c +++ b/components/drivers/usb/usbdevice/core/core.c @@ -24,6 +24,7 @@ * 2012-12-30 heyuanjie87 change inferface handler * 2013-04-26 aozima add DEVICEQUALIFIER support. * 2013-07-25 Yi Qiu update for USB CV test + * 2017-11-15 ZYH fix ep0 transform error */ #include @@ -1815,22 +1816,41 @@ rt_err_t rt_usbd_ep0_setup_handler(udcd_t dcd, struct urequest* setup) rt_err_t rt_usbd_ep0_in_handler(udcd_t dcd) { + rt_int32_t remain, mps; + RT_ASSERT(dcd != RT_NULL); - if(dcd->ep0.request.remain_size >= dcd->ep0.id->maxpacket) - { - dcd_ep_write(dcd, EP0_IN_ADDR, dcd->ep0.request.buffer, dcd->ep0.id->maxpacket); - dcd->ep0.request.remain_size -= dcd->ep0.id->maxpacket; - dcd->ep0.request.buffer += dcd->ep0.id->maxpacket; - } - else if(dcd->ep0.request.remain_size > 0) + if (dcd->stage != STAGE_DIN) + return RT_EOK; + + mps = dcd->ep0.id->maxpacket; + dcd->ep0.request.remain_size -= mps; + remain = dcd->ep0.request.remain_size; + + if (remain > 0) { - dcd_ep_write(dcd, EP0_IN_ADDR, dcd->ep0.request.buffer, dcd->ep0.request.remain_size); - dcd->ep0.request.remain_size = 0; + if (remain >= mps) + { + remain = mps; + } + + dcd->ep0.request.buffer += mps; + dcd_ep_write(dcd, EP0_IN_ADDR, dcd->ep0.request.buffer, remain); } else { - dcd_ep_write(dcd, EP0_IN_ADDR, RT_NULL, 0); + /* last packet is MPS multiple, so send ZLP packet */ + if ((remain == 0) && (dcd->ep0.request.size > 0)) + { + dcd->ep0.request.size = 0; + dcd_ep_write(dcd, EP0_IN_ADDR, RT_NULL, 0); + } + else + { + /* receive status */ + dcd->stage = STAGE_STATUS_OUT; + dcd_ep_read_prepare(dcd, EP0_OUT_ADDR, RT_NULL, 0); + } } return RT_EOK; @@ -1935,6 +1955,7 @@ rt_err_t rt_usbd_sof_handler(udcd_t dcd) rt_size_t rt_usbd_ep0_write(udevice_t device, void *buffer, rt_size_t size) { uep_t ep0; + rt_size_t sent_size = 0; RT_ASSERT(device != RT_NULL); RT_ASSERT(device->dcd != RT_NULL); @@ -1945,20 +1966,17 @@ rt_size_t rt_usbd_ep0_write(udevice_t device, void *buffer, rt_size_t size) ep0->request.size = size; ep0->request.buffer = buffer; ep0->request.remain_size = size; - - if(ep0->request.remain_size >= ep0->id->maxpacket) + if(size >= ep0->id->maxpacket) { - dcd_ep_write(device->dcd, EP0_IN_ADDR, ep0->request.buffer, ep0->id->maxpacket); - ep0->request.remain_size -= ep0->id->maxpacket; - ep0->request.buffer += ep0->id->maxpacket; + sent_size = ep0->id->maxpacket; } else { - dcd_ep_write(device->dcd, EP0_IN_ADDR, ep0->request.buffer, ep0->request.remain_size); - ep0->request.remain_size = 0; + sent_size = size; } + device->dcd->stage = STAGE_DIN; - return size; + return dcd_ep_write(device->dcd, EP0_IN_ADDR, ep0->request.buffer, sent_size); } rt_size_t rt_usbd_ep0_read(udevice_t device, void *buffer, rt_size_t size, @@ -1975,6 +1993,7 @@ rt_size_t rt_usbd_ep0_read(udevice_t device, void *buffer, rt_size_t size, ep0->request.buffer = buffer; ep0->request.remain_size = size; ep0->rx_indicate = rx_ind; + device->dcd->stage = STAGE_DOUT; dcd_ep_read_prepare(device->dcd, EP0_OUT_ADDR, buffer, size); return size;