summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
authoruestczyh222 <[email protected]>2017-11-15 20:46:18 +0800
committeruestczyh222 <[email protected]>2017-11-15 20:54:54 +0800
commita3808362aca372512cddb11abccf5a865ed2362f (patch)
treec03324f133892f06876ba4c26149d6091749e086 /components
parent66ddbbfef9b86e54e71d9f2abffe62fe4beeae08 (diff)
[Components][Drivers][USB]fix usb device core
Diffstat (limited to 'components')
-rw-r--r--components/drivers/include/drivers/usb_common.h11
-rw-r--r--components/drivers/include/drivers/usb_device.h2
-rw-r--r--components/drivers/usb/usbdevice/core/core.c55
3 files changed, 50 insertions, 18 deletions
diff --git a/components/drivers/include/drivers/usb_common.h b/components/drivers/include/drivers/usb_common.h
index 866909f3a7..08462d9244 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 fbbae7edb9..5e2417e90d 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 6880f931f0..a3caa60f99 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 <rtthread.h>
@@ -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;