summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshaolin <[email protected]>2014-02-16 17:42:35 +0800
committershaolin <[email protected]>2014-02-16 17:42:35 +0800
commit8fd0a7f9c61dde28d90ec4c3661e9e0e8327f7fc (patch)
treeb9b8491531d8354850c598d826010491b63e86c5
parentdb02f56283d17125917254e470997c63492b6862 (diff)
Update USB Device Stack to support more device controllers;
Pass USB CV test verification; Code cleanup;
-rw-r--r--components/drivers/include/drivers/usb_common.h63
-rw-r--r--components/drivers/include/drivers/usb_device.h311
-rw-r--r--components/drivers/usb/usbdevice/SConscript3
-rw-r--r--components/drivers/usb/usbdevice/class/cdc_vcom.c557
-rw-r--r--components/drivers/usb/usbdevice/class/mstorage.c1031
-rw-r--r--components/drivers/usb/usbdevice/class/mstorage.h7
-rw-r--r--components/drivers/usb/usbdevice/core/core.c1142
-rw-r--r--components/drivers/usb/usbdevice/core/usbdevice.c62
8 files changed, 2157 insertions, 1019 deletions
diff --git a/components/drivers/include/drivers/usb_common.h b/components/drivers/include/drivers/usb_common.h
index 979deb4732..cd6f0432f3 100644
--- a/components/drivers/include/drivers/usb_common.h
+++ b/components/drivers/include/drivers/usb_common.h
@@ -20,6 +20,7 @@
* Change Logs:
* Date Author Notes
* 2012-10-01 Yi Qiu first version
+ * 2013-04-26 aozima add DEVICEQUALIFIER support.
*/
#ifndef __USB_COMMON_H__
@@ -148,13 +149,22 @@ extern "C" {
#define USB_EPNO_MASK 0x7f
#define USB_DIR_OUT 0x00
#define USB_DIR_IN 0x80
+#define USB_DIR_INOUT 0x40
#define USB_DIR_MASK 0x80
+#define ID_UNASSIGNED 0
+#define ID_ASSIGNED 1
+
#define RH_GET_PORT_STATUS 0
#define RH_SET_PORT_STATUS 1
#define RH_CLEAR_PORT_FEATURE 2
#define RH_SET_PORT_FEATURE 3
+#define USB_BUS_POWERED 0
+#define USB_SELF_POWERED 1
+#define USB_REMOTE_WAKEUP 1
+#define USB_EP_HALT 0
+
/*
* Port feature numbers
*/
@@ -205,6 +215,7 @@ extern "C" {
#define USB_EP_ATTR(attr) (attr & USB_EP_ATTR_TYPE_MASK)
#define USB_EP_DESC_NUM(addr) (addr & USB_EP_DESC_NUM_MASK)
+#define USB_EP_DIR(addr) ((addr & USB_DIR_MASK)>>7)
#define uswap_32(x) \
((((x) & 0xff000000) >> 24) | \
@@ -239,7 +250,7 @@ struct usb_descriptor
};
typedef struct usb_descriptor* udesc_t;
-struct udevice_descriptor
+struct udevice_descriptor
{
rt_uint8_t bLength;
rt_uint8_t type;
@@ -258,7 +269,7 @@ struct udevice_descriptor
};
typedef struct udevice_descriptor* udev_desc_t;
-struct uconfig_descriptor
+struct uconfig_descriptor
{
rt_uint8_t bLength;
rt_uint8_t type;
@@ -272,7 +283,7 @@ struct uconfig_descriptor
};
typedef struct uconfig_descriptor* ucfg_desc_t;
-struct uinterface_descriptor
+struct uinterface_descriptor
{
rt_uint8_t bLength;
rt_uint8_t type;
@@ -287,7 +298,7 @@ struct uinterface_descriptor
typedef struct uinterface_descriptor* uintf_desc_t;
/* Interface Association Descriptor (IAD) */
-struct uiad_descriptor
+struct uiad_descriptor
{
rt_uint8_t bLength;
rt_uint8_t bDescriptorType;
@@ -300,7 +311,7 @@ struct uiad_descriptor
};
typedef struct uiad_descriptor* uiad_desc_t;
-struct uendpoint_descriptor
+struct uendpoint_descriptor
{
rt_uint8_t bLength;
rt_uint8_t type;
@@ -311,7 +322,7 @@ struct uendpoint_descriptor
};
typedef struct uendpoint_descriptor* uep_desc_t;
-struct ustring_descriptor
+struct ustring_descriptor
{
rt_uint8_t bLength;
rt_uint8_t type;
@@ -319,19 +330,34 @@ struct ustring_descriptor
};
typedef struct ustring_descriptor* ustr_desc_t;
-struct uhub_descriptor
+struct uhub_descriptor
{
rt_uint8_t length;
rt_uint8_t type;
rt_uint8_t num_ports;
- rt_uint16_t characteristics;
+ rt_uint16_t characteristics;
rt_uint8_t pwron_to_good; /* power on to power good */
- rt_uint8_t current;
+ rt_uint8_t current;
rt_uint8_t removable[8];
rt_uint8_t pwr_ctl[8];
};
typedef struct uhub_descriptor* uhub_desc_t;
+/* USB_DESC_TYPE_DEVICEQUALIFIER: Device Qualifier descriptor */
+struct usb_qualifier_descriptor
+{
+ rt_uint8_t bLength;
+ rt_uint8_t bDescriptorType;
+
+ rt_uint16_t bcdUSB; // TODO: big-endian.
+ rt_uint8_t bDeviceClass;
+ rt_uint8_t bDeviceSubClass;
+ rt_uint8_t bDeviceProtocol;
+ rt_uint8_t bMaxPacketSize0;
+ rt_uint8_t bNumConfigurations;
+ rt_uint8_t bRESERVED;
+} __attribute__ ((packed));
+
struct uhid_descriptor
{
rt_uint8_t bLength;
@@ -352,15 +378,17 @@ struct ureqest
rt_uint8_t request_type;
rt_uint8_t request;
rt_uint16_t value;
- rt_uint16_t index;
+ rt_uint16_t index;
rt_uint16_t length;
};
typedef struct ureqest* ureq_t;
+#ifndef MIN
#define MIN(a, b) (a < b ? a : b)
#define MAX(a, b) (a > b ? a : b)
+#endif
-/*
+/*
* the define related to mass storage
*/
#define USBREQ_GET_MAX_LUN 0xfe
@@ -368,6 +396,11 @@ typedef struct ureqest* ureq_t;
#define SIZEOF_CSW 0x0d
#define SIZEOF_CBW 0x1f
+#define SIZEOF_INQUIRY_CMD 0x24
+#define SIZEOF_MODE_SENSE_6 0x4
+#define SIZEOF_READ_CAPACITIES 0xc
+#define SIZEOF_READ_CAPACITY 0x8
+#define SIZEOF_REQUEST_SENSE 0x12
#define CBWFLAGS_DIR_M 0x80
#define CBWFLAGS_DIR_IN 0x80
@@ -376,7 +409,7 @@ typedef struct ureqest* ureq_t;
#define SCSI_TEST_UNIT_READY 0x00
#define SCSI_REQUEST_SENSE 0x03
#define SCSI_INQUIRY_CMD 0x12
-#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1e
+#define SCSI_ALLOW_REMOVAL 0x1e
#define SCSI_MODE_SENSE_6 0x1a
#define SCSI_START_STOP 0x1b
#define SCSI_READ_CAPACITIES 0x23
@@ -389,7 +422,7 @@ typedef struct ureqest* ureq_t;
#define CSW_SIGNATURE 0x53425355
#define CBW_TAG_VALUE 0x12345678
-struct ustorage_cbw
+struct ustorage_cbw
{
rt_uint32_t signature;
rt_uint32_t tag;
@@ -401,11 +434,11 @@ struct ustorage_cbw
};
typedef struct ustorage_cbw* ustorage_cbw_t;
-struct ustorage_csw
+struct ustorage_csw
{
rt_uint32_t signature;
rt_uint32_t tag;
- rt_uint32_t data_reside;
+ rt_int32_t data_reside;
rt_uint8_t status;
};
typedef struct ustorage_csw* ustorage_csw_t;
diff --git a/components/drivers/include/drivers/usb_device.h b/components/drivers/include/drivers/usb_device.h
index db03ee36ef..722251c82a 100644
--- a/components/drivers/include/drivers/usb_device.h
+++ b/components/drivers/include/drivers/usb_device.h
@@ -20,7 +20,8 @@
* Change Logs:
* Date Author Notes
* 2012-10-01 Yi Qiu first version
- * 2012-12-12 heyuanjie87 change endpoint and class handler
+ * 2012-12-12 heyuanjie87 change endpoint and function handler
+ * 2013-04-26 aozima add DEVICEQUALIFIER support.
*/
#ifndef __USB_DEVICE_H__
@@ -31,59 +32,115 @@
/* Vendor ID */
#ifdef USB_VENDOR_ID
-#define _VENDOR_ID USB_VENDOR_ID
+#define _VENDOR_ID USB_VENDOR_ID
#else
-#define _VENDOR_ID 0x0EFF
+#define _VENDOR_ID 0x0EFF
#endif
/* Product ID */
#ifdef USB_PRODUCT_ID
-#define _PRODUCT_ID USB_PRODUCT_ID
+#define _PRODUCT_ID USB_PRODUCT_ID
#else
-#define _PRODUCT_ID 0x0001
+#define _PRODUCT_ID 0x0001
#endif
-#define USB_BCD_DEVICE 0x0200 /* USB Specification Release Number in Binary-Coded Decimal */
-#define USB_BCD_VERSION 0x0200 /* USB 2.0 */
+#define USB_BCD_DEVICE 0x0200 /* USB Specification Release Number in Binary-Coded Decimal */
+#define USB_BCD_VERSION 0x0200 /* USB 2.0 */
+#define EP0_IN_ADDR 0x80
+#define EP0_OUT_ADDR 0x00
+#define EP_HANDLER(ep, func, size) RT_ASSERT(ep != RT_NULL); ep->handler(func, size)
+#define EP_ADDRESS(ep) ep->ep_desc->bEndpointAddress
+#define EP_MAXPACKET(ep) ep->ep_desc->wMaxPacketSize
+#define FUNC_ENABLE(func) do{ \
+ if(func->ops->enable != RT_NULL && \
+ func->enabled == RT_FALSE) \
+ { \
+ if(func->ops->enable(func) == RT_EOK) \
+ func->enabled = RT_TRUE; \
+ } \
+ }while(0)
+#define FUNC_DISABLE(func) do{ \
+ if(func->ops->disable != RT_NULL && \
+ func->enabled == RT_TRUE) \
+ { \
+ func->enabled = RT_FALSE; \
+ func->ops->disable(func); \
+ } \
+ }while(0)
-struct uclass;
+struct ufunction;
struct udevice;
struct uendpoint;
+typedef enum
+{
+ /* request to read full count */
+ UIO_REQUEST_READ_FULL,
+ /* request to read any count */
+ UIO_REQUEST_READ_BEST,
+ /* request to write full count */
+ UIO_REQUEST_WRITE,
+}UIO_REQUEST_TYPE;
+
struct udcd_ops
{
- rt_err_t (*set_address)(rt_uint8_t value);
- rt_err_t (*clear_feature)(rt_uint16_t value, rt_uint16_t index);
- rt_err_t (*set_feature)(rt_uint16_t value, rt_uint16_t index);
- rt_err_t (*ep_alloc)(struct uendpoint* ep);
- rt_err_t (*ep_free)(struct uendpoint* ep);
- rt_err_t (*ep_stall)(struct uendpoint* ep);
- rt_err_t (*ep_run)(struct uendpoint* ep);
- rt_err_t (*ep_stop)(struct uendpoint* ep);
- rt_err_t (*ep_read)(struct uendpoint* ep, void *buffer, rt_size_t size);
- rt_size_t (*ep_write)(struct uendpoint* ep, void *buffer, rt_size_t size);
- rt_err_t (*send_status)(void);
+ rt_err_t (*set_address)(rt_uint8_t address);
+ rt_err_t (*set_config)(rt_uint8_t address);
+ rt_err_t (*ep_set_stall)(rt_uint8_t address);
+ rt_err_t (*ep_clear_stall)(rt_uint8_t address);
+ rt_err_t (*ep_enable)(struct uendpoint* ep);
+ rt_err_t (*ep_disable)(struct uendpoint* ep);
+ rt_size_t (*ep_read_prepare)(rt_uint8_t address, void *buffer, rt_size_t size);
+ rt_size_t (*ep_read)(rt_uint8_t address, void *buffer);
+ rt_size_t (*ep_write)(rt_uint8_t address, void *buffer, rt_size_t size);
+ rt_err_t (*ep0_send_status)(void);
+ rt_err_t (*suspend)(void);
+ rt_err_t (*wakeup)(void);
};
-struct udcd
+struct ep_id
{
- struct rt_device parent;
- struct udcd_ops* ops;
- struct rt_completion completion;
+ rt_uint8_t addr;
+ rt_uint8_t type;
+ rt_uint8_t dir;
+ rt_uint8_t maxpacket;
+ rt_uint8_t status;
};
-typedef struct udcd* udcd_t;
-typedef rt_err_t (*udep_handler_t)(struct udevice* device, struct uclass* cls, rt_size_t size);
+typedef rt_err_t (*udep_handler_t)(struct ufunction* func, rt_size_t size);
-struct uendpoint
+struct uio_request
{
rt_list_t list;
+ UIO_REQUEST_TYPE req_type;
rt_uint8_t* buffer;
+ rt_size_t size;
+ rt_size_t remain_size;
+};
+typedef struct uio_request* uio_request_t;
+
+struct uendpoint
+{
+ rt_list_t list;
uep_desc_t ep_desc;
+ rt_list_t request_list;
+ struct uio_request request;
+ rt_uint8_t* buffer;
+ rt_bool_t stalled;
+ struct ep_id* id;
udep_handler_t handler;
- rt_bool_t is_stall;
+ rt_err_t (*rx_indicate)(struct udevice* dev, rt_size_t size);
};
typedef struct uendpoint* uep_t;
+struct udcd
+{
+ struct rt_device parent;
+ const struct udcd_ops* ops;
+ struct uendpoint ep0;
+ struct ep_id* ep_pool;
+};
+typedef struct udcd* udcd_t;
+
struct ualtsetting
{
rt_list_t list;
@@ -94,7 +151,7 @@ struct ualtsetting
};
typedef struct ualtsetting* ualtsetting_t;
-typedef rt_err_t (*uintf_handler_t)(struct udevice* device, struct uclass* cls, ureq_t setup);
+typedef rt_err_t (*uintf_handler_t)(struct ufunction* func, ureq_t setup);
struct uinterface
{
@@ -106,32 +163,32 @@ struct uinterface
};
typedef struct uinterface* uintf_t;
-struct uclass_ops
+struct ufunction_ops
{
- rt_err_t (*run)(struct udevice* device, struct uclass* cls);
- rt_err_t (*stop)(struct udevice* device, struct uclass* cls);
- rt_err_t (*sof_handler)(struct udevice* device, struct uclass* cls);
+ rt_err_t (*enable)(struct ufunction* func);
+ rt_err_t (*disable)(struct ufunction* func);
+ rt_err_t (*sof_handler)(struct ufunction* func);
};
-typedef struct uclass_ops* uclass_ops_t;
+typedef struct ufunction_ops* ufunction_ops_t;
-struct uclass
+struct ufunction
{
rt_list_t list;
- uclass_ops_t ops;
- void* eps;
+ ufunction_ops_t ops;
struct udevice* device;
udev_desc_t dev_desc;
void* user_data;
+ rt_bool_t enabled;
rt_list_t intf_list;
};
-typedef struct uclass* uclass_t;
+typedef struct ufunction* ufunction_t;
struct uconfig
{
rt_list_t list;
struct uconfig_descriptor cfg_desc;
- rt_list_t cls_list;
+ rt_list_t func_list;
};
typedef struct uconfig* uconfig_t;
@@ -139,6 +196,8 @@ struct udevice
{
rt_list_t list;
struct udevice_descriptor dev_desc;
+
+ struct usb_qualifier_descriptor * dev_qualifier;
const char** str;
udevice_state_t state;
@@ -154,8 +213,11 @@ enum udev_msg_type
{
USB_MSG_SETUP_NOTIFY,
USB_MSG_DATA_NOTIFY,
+ USB_MSG_EP0_OUT,
+ USB_MSG_EP_CLEAR_FEATURE,
USB_MSG_SOF,
USB_MSG_RESET,
+ USB_MSG_PLUG_IN,
/* 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
@@ -164,153 +226,184 @@ enum udev_msg_type
};
typedef enum udev_msg_type udev_msg_type;
+struct ep_msg
+{
+ rt_size_t size;
+ rt_uint8_t ep_addr;
+};
+
struct udev_msg
{
udev_msg_type type;
udcd_t dcd;
union
{
- struct
- {
- rt_size_t size;
- rt_uint8_t ep_addr;
- } ep_msg;
- struct
- {
- rt_uint32_t* packet;
- } setup_msg;
+ struct ep_msg ep_msg;
+ struct ureqest setup;
} content;
};
typedef struct udev_msg* udev_msg_t;
-udevice_t rt_usbd_device_create(void);
-uconfig_t rt_usbd_config_create(void);
-uclass_t rt_usbd_class_create(udevice_t device,
- udev_desc_t dev_desc,
- uclass_ops_t ops);
-uintf_t rt_usbd_interface_create(udevice_t device, uintf_handler_t handler);
-uep_t rt_usbd_endpoint_create(uep_desc_t ep_desc, udep_handler_t handler);
-ualtsetting_t rt_usbd_altsetting_create(rt_size_t desc_size);
+udevice_t rt_usbd_device_new(void);
+uconfig_t rt_usbd_config_new(void);
+ufunction_t rt_usbd_function_new(udevice_t device, udev_desc_t dev_desc,
+ ufunction_ops_t ops);
+uintf_t rt_usbd_interface_new(udevice_t device, uintf_handler_t handler);
+uep_t rt_usbd_endpoint_new(uep_desc_t ep_desc, udep_handler_t handler);
+ualtsetting_t rt_usbd_altsetting_new(rt_size_t desc_size);
rt_err_t rt_usbd_core_init(void);
-rt_err_t rt_usb_device_init(const char *udc_name);
-rt_err_t rt_usbd_post_event(struct udev_msg *msg, rt_size_t size);
-rt_err_t rt_usbd_free_device(udevice_t device);
+rt_err_t rt_usb_device_init(void);
+rt_err_t rt_usbd_event_signal(struct udev_msg* msg);
rt_err_t rt_usbd_device_set_controller(udevice_t device, udcd_t dcd);
rt_err_t rt_usbd_device_set_descriptor(udevice_t device, udev_desc_t dev_desc);
rt_err_t rt_usbd_device_set_string(udevice_t device, const char** ustring);
+rt_err_t rt_usbd_device_set_qualifier(udevice_t device, struct usb_qualifier_descriptor* qualifier);
rt_err_t rt_usbd_device_add_config(udevice_t device, uconfig_t cfg);
-rt_err_t rt_usbd_config_add_class(uconfig_t cfg, uclass_t cls);
-rt_err_t rt_usbd_class_add_interface(uclass_t cls, uintf_t intf);
+rt_err_t rt_usbd_config_add_function(uconfig_t cfg, ufunction_t func);
+rt_err_t rt_usbd_function_add_interface(ufunction_t func, uintf_t intf);
rt_err_t rt_usbd_interface_add_altsetting(uintf_t intf, ualtsetting_t setting);
rt_err_t rt_usbd_altsetting_add_endpoint(ualtsetting_t setting, uep_t ep);
-rt_err_t rt_usbd_altsetting_config_descriptor(ualtsetting_t setting,
- const void *desc,
- rt_off_t intf_pos);
+rt_err_t rt_usbd_altsetting_config_descriptor(ualtsetting_t setting, const void* desc, rt_off_t intf_pos);
rt_err_t rt_usbd_set_config(udevice_t device, rt_uint8_t value);
rt_err_t rt_usbd_set_altsetting(uintf_t intf, rt_uint8_t value);
udevice_t rt_usbd_find_device(udcd_t dcd);
uconfig_t rt_usbd_find_config(udevice_t device, rt_uint8_t value);
-uintf_t rt_usbd_find_interface(udevice_t device,
- rt_uint8_t value,
- uclass_t *pcls);
-uep_t rt_usbd_find_endpoint(udevice_t device,
- uclass_t *pcls,
- rt_uint8_t ep_addr);
+uintf_t rt_usbd_find_interface(udevice_t device, rt_uint8_t value, ufunction_t *pfunc);
+uep_t rt_usbd_find_endpoint(udevice_t device, ufunction_t* pfunc, rt_uint8_t ep_addr);
+rt_size_t rt_usbd_io_request(udevice_t device, uep_t ep, uio_request_t req);
+rt_size_t rt_usbd_ep0_write(udevice_t device, void *buffer, rt_size_t size);
+rt_size_t rt_usbd_ep0_read(udevice_t device, void *buffer, rt_size_t size,
+ rt_err_t (*rx_ind)(udevice_t device, rt_size_t size));
-uclass_t rt_usbd_class_mstorage_create(udevice_t device);
-uclass_t rt_usbd_class_cdc_create(udevice_t device);
-uclass_t rt_usbd_class_rndis_create(udevice_t device);
-uclass_t rt_usbd_class_dap_create(udevice_t device);
+ufunction_t rt_usbd_function_mstorage_create(udevice_t device);
+ufunction_t rt_usbd_function_cdc_create(udevice_t device);
+ufunction_t rt_usbd_function_rndis_create(udevice_t device);
+ufunction_t rt_usbd_function_dap_create(udevice_t device);
#ifdef RT_USB_DEVICE_COMPOSITE
-rt_err_t rt_usbd_class_set_iad(uclass_t cls, uiad_desc_t iad_desc);
+rt_err_t rt_usbd_function_set_iad(ufunction_t func, uiad_desc_t iad_desc);
#endif
-rt_inline rt_err_t dcd_set_address(udcd_t dcd, rt_uint8_t value)
-{
- RT_ASSERT(dcd != RT_NULL);
-
- return dcd->ops->set_address(value);
-}
+rt_err_t rt_usbd_set_feature(udevice_t device, rt_uint16_t value, rt_uint16_t index);
+rt_err_t rt_usbd_clear_feature(udevice_t device, rt_uint16_t value, rt_uint16_t index);
+rt_err_t rt_usbd_ep_set_stall(udevice_t device, uep_t ep);
+rt_err_t rt_usbd_ep_clear_stall(udevice_t device, uep_t ep);
+rt_err_t rt_usbd_ep0_set_stall(udevice_t device);
+rt_err_t rt_usbd_ep0_clear_stall(udevice_t device);
+rt_err_t rt_usbd_ep0_setup_handler(udcd_t dcd, struct ureqest* setup);
+rt_err_t rt_usbd_ep0_in_handler(udcd_t dcd);
+rt_err_t rt_usbd_ep0_out_handler(udcd_t dcd, rt_size_t size);
+rt_err_t rt_usbd_ep_in_handler(udcd_t dcd, rt_uint8_t address);
+rt_err_t rt_usbd_ep_out_handler(udcd_t dcd, rt_uint8_t address, rt_size_t size);
+rt_err_t rt_usbd_reset_handler(udcd_t dcd);
+rt_err_t rt_usbd_connect_handler(udcd_t dcd);
+rt_err_t rt_usbd_disconnect_handler(udcd_t dcd);
+rt_err_t rt_usbd_sof_handler(udcd_t dcd);
-rt_inline rt_err_t dcd_clear_feature(udcd_t dcd,
- rt_uint16_t value,
- rt_uint16_t index)
+rt_inline rt_err_t dcd_set_address(udcd_t dcd, rt_uint8_t address)
{
RT_ASSERT(dcd != RT_NULL);
+ RT_ASSERT(dcd->ops != RT_NULL);
+ RT_ASSERT(dcd->ops->set_address != RT_NULL);
- return dcd->ops->clear_feature(value, index);
+ return dcd->ops->set_address(address);
}
-rt_inline rt_err_t dcd_set_feature(udcd_t dcd,
- rt_uint8_t value,
- rt_uint16_t index)
+rt_inline rt_err_t dcd_set_config(udcd_t dcd, rt_uint8_t address)
{
RT_ASSERT(dcd != RT_NULL);
+ RT_ASSERT(dcd->ops != RT_NULL);
+ RT_ASSERT(dcd->ops->set_config != RT_NULL);
- return dcd->ops->set_feature(value, index);
+ return dcd->ops->set_config(address);
}
-rt_inline rt_err_t dcd_ep_stall(udcd_t dcd, uep_t ep)
+rt_inline rt_err_t dcd_ep_enable(udcd_t dcd, uep_t ep)
{
RT_ASSERT(dcd != RT_NULL);
+ RT_ASSERT(dcd->ops != RT_NULL);
+ RT_ASSERT(dcd->ops->ep_enable != RT_NULL);
- return dcd->ops->ep_stall(ep);
+ return dcd->ops->ep_enable(ep);
}
-rt_inline rt_uint8_t dcd_ep_alloc(udcd_t dcd, uep_t ep)
+rt_inline rt_err_t dcd_ep_disable(udcd_t dcd, uep_t ep)
{
RT_ASSERT(dcd != RT_NULL);
+ RT_ASSERT(dcd->ops != RT_NULL);
+ RT_ASSERT(dcd->ops->ep_disable != RT_NULL);
- return dcd->ops->ep_alloc(ep);
+ return dcd->ops->ep_disable(ep);
}
-rt_inline rt_err_t dcd_ep_free(udcd_t dcd, uep_t ep)
+rt_inline rt_size_t dcd_ep_read_prepare(udcd_t dcd, rt_uint8_t address, void *buffer,
+ rt_size_t size)
{
RT_ASSERT(dcd != RT_NULL);
+ RT_ASSERT(dcd->ops != RT_NULL);
- return dcd->ops->ep_free(ep);
+ if(dcd->ops->ep_read_prepare != RT_NULL)
+ {
+ return dcd->ops->ep_read_prepare(address, buffer, size);
+ }
+ else
+ {
+ return 0;
+ }
}
-rt_inline rt_err_t dcd_ep_run(udcd_t dcd, uep_t ep)
+rt_inline rt_size_t dcd_ep_read(udcd_t dcd, rt_uint8_t address, void *buffer)
{
RT_ASSERT(dcd != RT_NULL);
+ RT_ASSERT(dcd->ops != RT_NULL);
- return dcd->ops->ep_run(ep);
+ if(dcd->ops->ep_read != RT_NULL)
+ {
+ return dcd->ops->ep_read(address, buffer);
+ }
+ else
+ {
+ return 0;
+ }
}
-rt_inline rt_err_t dcd_ep_stop(udcd_t dcd, uep_t ep)
+rt_inline rt_size_t dcd_ep_write(udcd_t dcd, rt_uint8_t address, void *buffer,
+ rt_size_t size)
{
RT_ASSERT(dcd != RT_NULL);
+ RT_ASSERT(dcd->ops != RT_NULL);
+ RT_ASSERT(dcd->ops->ep_write != RT_NULL);
- return dcd->ops->ep_stop(ep);
+ return dcd->ops->ep_write(address, buffer, size);
}
-rt_inline rt_err_t dcd_ep_read(udcd_t dcd, uep_t ep, void *buffer,
- rt_size_t size)
+rt_inline rt_err_t dcd_ep0_send_status(udcd_t dcd)
{
RT_ASSERT(dcd != RT_NULL);
+ RT_ASSERT(dcd->ops != RT_NULL);
+ RT_ASSERT(dcd->ops->ep0_send_status != RT_NULL);
- return dcd->ops->ep_read(ep, buffer, size);
+ return dcd->ops->ep0_send_status();
}
-rt_inline rt_size_t dcd_ep_write(udcd_t dcd,
- uep_t ep,
- void *buffer,
- rt_size_t size)
-{
+rt_inline rt_err_t dcd_ep_set_stall(udcd_t dcd, rt_uint8_t address)
+{
RT_ASSERT(dcd != RT_NULL);
+ RT_ASSERT(dcd->ops != RT_NULL);
+ RT_ASSERT(dcd->ops->ep_set_stall != RT_NULL);
- return dcd->ops->ep_write(ep, buffer, size);
+ return dcd->ops->ep_set_stall(address);
}
-rt_inline rt_err_t dcd_send_status(udcd_t dcd)
+rt_inline rt_err_t dcd_ep_clear_stall(udcd_t dcd, rt_uint8_t address)
{
RT_ASSERT(dcd != RT_NULL);
+ RT_ASSERT(dcd->ops != RT_NULL);
+ RT_ASSERT(dcd->ops->ep_clear_stall != RT_NULL);
- return dcd->ops->send_status();
+ return dcd->ops->ep_clear_stall(address);
}
#endif
diff --git a/components/drivers/usb/usbdevice/SConscript b/components/drivers/usb/usbdevice/SConscript
index d46ec3db59..1ee9467410 100644
--- a/components/drivers/usb/usbdevice/SConscript
+++ b/components/drivers/usb/usbdevice/SConscript
@@ -13,9 +13,6 @@ if GetDepend('RT_USB_DEVICE_CDC'):
if GetDepend('RT_USB_DEVICE_MSTORAGE'):
src += Glob('class/mstorage.c')
-if GetDepend('RT_USB_DEVICE_RNDIS'):
- src += Glob('class/rndis.c')
-
CPPPATH = [cwd]
group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_USB_DEVICE'], CPPPATH = CPPPATH)
diff --git a/components/drivers/usb/usbdevice/class/cdc_vcom.c b/components/drivers/usb/usbdevice/class/cdc_vcom.c
index 5f284b0294..33f9f7abef 100644
--- a/components/drivers/usb/usbdevice/class/cdc_vcom.c
+++ b/components/drivers/usb/usbdevice/class/cdc_vcom.c
@@ -20,34 +20,56 @@
* Change Logs:
* Date Author Notes
* 2012-10-02 Yi Qiu first version
- * 2012-12-12 heyuanjie87 change endpoints and class handler
+ * 2012-12-12 heyuanjie87 change endpoints and function handler
+ * 2013-06-25 heyuanjie87 remove SOF mechinism
+ * 2013-07-20 Yi Qiu do more test
*/
#include <rtthread.h>
+#include <rtservice.h>
#include <rtdevice.h>
#include <rthw.h>
#include "cdc.h"
#ifdef RT_USB_DEVICE_CDC
+#define TX_TIMEOUT 100
#define CDC_RX_BUFSIZE 2048
-#define CDC_TX_BUFSIZE 2048
-static rt_uint8_t rx_rbp[CDC_RX_BUFSIZE];
-static rt_uint8_t tx_rbp[CDC_TX_BUFSIZE];
-static struct rt_ringbuffer rx_ringbuffer;
-static struct rt_ringbuffer tx_ringbuffer;
-static struct serial_ringbuffer vcom_int_rx;
+#define CDC_MAX_PACKET_SIZE 64
+#define VCOM_DEVICE "vcom"
-static struct rt_serial_device vcom_serial;
-
-#define CDC_MaxPacketSize 64
-ALIGN(RT_ALIGN_SIZE)
-static rt_uint8_t rx_buf[CDC_RX_BUFSIZE];
ALIGN(RT_ALIGN_SIZE)
-static rt_uint8_t tx_buf[CDC_TX_BUFSIZE];
+static rt_uint8_t vcom_thread_stack[512];
+static struct rt_thread vcom_thread;
+#define VCOM_MQ_MSG_SZ 16
+#define VCOM_MQ_MAX_MSG 4
+/* internal of the message queue: every message is associated with a pointer,
+ * so in order to recveive VCOM_MQ_MAX_MSG messages, we have to allocate more
+ * than VCOM_MQ_MSG_SZ*VCOM_MQ_MAX_MSG memery. */
+static rt_uint8_t vcom_tx_thread_mq_pool[(VCOM_MQ_MSG_SZ+sizeof(void*))*VCOM_MQ_MAX_MSG];
+static struct rt_messagequeue vcom_tx_thread_mq;
+static struct ucdc_line_coding line_coding;
-volatile static rt_bool_t vcom_connected = RT_FALSE;
-volatile static rt_bool_t vcom_in_sending = RT_FALSE;
+struct vcom
+{
+ struct rt_serial_device serial;
+ uep_t ep_out;
+ uep_t ep_in;
+ uep_t ep_cmd;
+ rt_bool_t connected;
+ rt_bool_t in_sending;
+ struct rt_completion wait;
+ rt_uint8_t rx_rbp[CDC_RX_BUFSIZE];
+ struct rt_ringbuffer rx_ringbuffer;
+ struct serial_ringbuffer vcom_int_rx;
+};
+
+struct vcom_tx_msg
+{
+ struct rt_serial_device * serial;
+ const char *buf;
+ rt_size_t size;
+};
static struct udevice_descriptor dev_desc =
{
@@ -57,7 +79,7 @@ static struct udevice_descriptor dev_desc =
USB_CLASS_CDC, //bDeviceClass;
0x00, //bDeviceSubClass;
0x00, //bDeviceProtocol;
- CDC_MaxPacketSize, //bMaxPacketSize0;
+ CDC_MAX_PACKET_SIZE, //bMaxPacketSize0;
_VENDOR_ID, //idVendor;
_PRODUCT_ID, //idProduct;
USB_BCD_DEVICE, //bcdDevice;
@@ -67,6 +89,18 @@ static struct udevice_descriptor dev_desc =
USB_DYNAMIC, //bNumConfigurations;
};
+static struct usb_qualifier_descriptor dev_qualifier =
+{
+ sizeof(dev_qualifier),
+ USB_DESC_TYPE_DEVICEQUALIFIER,
+ 0x0200,
+ USB_CLASS_CDC,
+ 0x00,
+ 64,
+ 0x01,
+ 0,
+};
+
/* communcation interface descriptor */
const static struct ucdc_comm_descriptor _comm_desc =
{
@@ -85,19 +119,19 @@ const static struct ucdc_comm_descriptor _comm_desc =
USB_DESC_LENGTH_INTERFACE,
USB_DESC_TYPE_INTERFACE,
USB_DYNAMIC,
- 0x00,
+ 0x00,
0x01,
USB_CDC_CLASS_COMM,
USB_CDC_SUBCLASS_ACM,
USB_CDC_PROTOCOL_V25TER,
0x00,
- /* Header Functional Descriptor */
- 0x05,
+ /* Header Functional Descriptor */
+ 0x05,
USB_CDC_CS_INTERFACE,
USB_CDC_SCS_HEADER,
0x0110,
- /* Call Management Functional Descriptor */
- 0x05,
+ /* Call Management Functional Descriptor */
+ 0x05,
USB_CDC_CS_INTERFACE,
USB_CDC_SCS_CALL_MGMT,
0x00,
@@ -107,13 +141,13 @@ const static struct ucdc_comm_descriptor _comm_desc =
USB_CDC_CS_INTERFACE,
USB_CDC_SCS_ACM,
0x02,
- /* Union Functional Descriptor */
+ /* Union Functional Descriptor */
0x05,
USB_CDC_CS_INTERFACE,
USB_CDC_SCS_UNION,
USB_DYNAMIC,
USB_DYNAMIC,
- /* Endpoint Descriptor */
+ /* Endpoint Descriptor */
USB_DESC_LENGTH_ENDPOINT,
USB_DESC_TYPE_ENDPOINT,
USB_DYNAMIC | USB_DIR_IN,
@@ -130,23 +164,23 @@ const static struct ucdc_data_descriptor _data_desc =
USB_DESC_TYPE_INTERFACE,
USB_DYNAMIC,
0x00,
- 0x02,
+ 0x02,
USB_CDC_CLASS_DATA,
- 0x00,
- 0x00,
- 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
/* endpoint, bulk out */
- USB_DESC_LENGTH_ENDPOINT,
+ USB_DESC_LENGTH_ENDPOINT,
USB_DESC_TYPE_ENDPOINT,
USB_DYNAMIC | USB_DIR_OUT,
- USB_EP_ATTR_BULK,
+ USB_EP_ATTR_BULK,
USB_CDC_BUFSIZE,
- 0x00,
+ 0x00,
/* endpoint, bulk in */
USB_DESC_LENGTH_ENDPOINT,
USB_DESC_TYPE_ENDPOINT,
USB_DYNAMIC | USB_DIR_IN,
- USB_EP_ATTR_BULK,
+ USB_EP_ATTR_BULK,
USB_CDC_BUFSIZE,
0x00,
};
@@ -156,18 +190,24 @@ const static char* _ustring[] =
"Language",
"RT-Thread Team.",
"RTT Virtual Serial",
- "1.1.0",
+ "32021919830108",
"Configuration",
"Interface",
};
+static void rt_usb_vcom_init(struct ufunction *func);
-static void _vcom_reset_state(void)
+static void _vcom_reset_state(ufunction_t func)
{
- int lvl = rt_hw_interrupt_disable();
- tx_ringbuffer.read_mirror = tx_ringbuffer.read_index = 0;
- tx_ringbuffer.write_mirror = tx_ringbuffer.write_index = 0;
- vcom_connected = RT_FALSE;
- vcom_in_sending = RT_FALSE;
+ struct vcom* data;
+ int lvl;
+
+ RT_ASSERT(func != RT_NULL)
+
+ data = (struct vcom*)func->user_data;
+
+ lvl = rt_hw_interrupt_disable();
+ data->connected = RT_FALSE;
+ data->in_sending = RT_FALSE;
/*rt_kprintf("reset USB serial\n", cnt);*/
rt_hw_interrupt_enable(lvl);
}
@@ -175,95 +215,73 @@ static void _vcom_reset_state(void)
/**
* This function will handle cdc bulk in endpoint request.
*
- * @param device the usb device object.
+ * @param func the usb function object.
* @param size request size.
*
* @return RT_EOK.
*/
-static rt_err_t _ep_in_handler(udevice_t device, uclass_t cls, rt_size_t size)
+static rt_err_t _ep_in_handler(ufunction_t func, rt_size_t size)
{
- rt_uint32_t level;
- rt_uint32_t remain;
- cdc_eps_t eps;
-
- eps = (cdc_eps_t)cls->eps;
- level = rt_hw_interrupt_disable();
- remain = rt_ringbuffer_data_len(&tx_ringbuffer);
- if (remain != 0)
- {
- /* although vcom_in_sending is set in SOF handler in the very
- * beginning, we have to guarantee the state is right when start
- * sending. There is at least one extreme case where we have finished the
- * last IN transaction but the vcom_in_sending is RT_FALSE.
- *
- * Ok, what the extreme case is: pour data into vcom in loop. Open
- * terminal on the PC, you will see the data. Then close it. So the
- * data will be sent to the PC in the back. When the buffer of the PC
- * driver is full. It will not send IN packet to the board and you will
- * have no chance to clear vcom_in_sending in this function. The data
- * will fill into the ringbuffer until it is full, and we will reset
- * the state machine and clear vcom_in_sending. When you open the
- * terminal on the PC again. The IN packet will appear on the line and
- * we will, eventually, reach here with vcom_in_sending is clear.
- */
- vcom_in_sending = RT_TRUE;
- rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, remain);
- rt_hw_interrupt_enable(level);
+ struct vcom *data;
- /* send data to host */
- dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, remain);
+ RT_ASSERT(func != RT_NULL);
- return RT_EOK;
- }
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_in_handler %d\n", size));
- if (size != 0 &&
- (size % CDC_MaxPacketSize) == 0)
+ data = (struct vcom*)func->user_data;
+ if ((size != 0) && (size % CDC_MAX_PACKET_SIZE == 0))
{
/* don't have data right now. Send a zero-length-packet to
* terminate the transaction.
*
* FIXME: actually, this might not be the right place to send zlp.
* Only the rt_device_write could know how much data is sending. */
- vcom_in_sending = RT_TRUE;
- rt_hw_interrupt_enable(level);
- dcd_ep_write(device->dcd, eps->ep_in, RT_NULL, 0);
- return RT_EOK;
- }
- else
- {
- vcom_in_sending = RT_FALSE;
- rt_hw_interrupt_enable(level);
+ data->in_sending = RT_TRUE;
+
+ data->ep_in->request.buffer = RT_NULL;
+ data->ep_in->request.size = 0;
+ data->ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
+
return RT_EOK;
}
+
+ rt_completion_done(&data->wait);
+
+ return RT_EOK;
}
/**
* This function will handle cdc bulk out endpoint request.
*
- * @param device the usb device object.
+ * @param func the usb function object.
* @param size request size.
*
* @return RT_EOK.
*/
-static rt_err_t _ep_out_handler(udevice_t device, uclass_t cls, rt_size_t size)
+static rt_err_t _ep_out_handler(ufunction_t func, rt_size_t size)
{
rt_uint32_t level;
- cdc_eps_t eps;
+ struct vcom *data;
- RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(func != RT_NULL);
- eps = (cdc_eps_t)cls->eps;
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_out_handler %d\n", size));
+
+ data = (struct vcom*)func->user_data;
/* receive data from USB VCOM */
level = rt_hw_interrupt_disable();
- rt_ringbuffer_put(&rx_ringbuffer, eps->ep_out->buffer, size);
+ rt_ringbuffer_put(&data->rx_ringbuffer, data->ep_out->buffer, size);
rt_hw_interrupt_enable(level);
/* notify receive data */
- rt_hw_serial_isr(&vcom_serial);
+ rt_hw_serial_isr(&data->serial);
- dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer,
- eps->ep_out->ep_desc->wMaxPacketSize);
+ data->ep_out->request.buffer = data->ep_out->buffer;
+ data->ep_out->request.size = EP_MAXPACKET(data->ep_out);
+ data->ep_out->request.req_type = UIO_REQUEST_READ_BEST;
+ rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
return RT_EOK;
}
@@ -276,9 +294,9 @@ static rt_err_t _ep_out_handler(udevice_t device, uclass_t cls, rt_size_t size)
*
* @return RT_EOK.
*/
-static rt_err_t _ep_cmd_handler(udevice_t device, uclass_t cls, rt_size_t size)
+static rt_err_t _ep_cmd_handler(ufunction_t func, rt_size_t size)
{
- RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(func != RT_NULL);
RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_cmd_handler\n"));
@@ -301,14 +319,25 @@ static rt_err_t _cdc_get_line_coding(udevice_t device, ureq_t setup)
RT_ASSERT(device != RT_NULL);
RT_ASSERT(setup != RT_NULL);
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_cdc_get_line_coding\n"));
+
data.dwDTERate = 115200;
data.bCharFormat = 0;
data.bDataBits = 8;
data.bParityType = 0;
size = setup->length > 7 ? 7 : setup->length;
- dcd_ep_write(device->dcd, 0, (void*)&data, size);
+ rt_usbd_ep0_write(device, (void*)&data, size);
+
+ return RT_EOK;
+}
+
+static rt_err_t _cdc_set_line_coding_callback(udevice_t device, rt_size_t size)
+{
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_cdc_set_line_coding_callback\n"));
+ dcd_ep0_send_status(device->dcd);
+
return RT_EOK;
}
@@ -322,21 +351,13 @@ static rt_err_t _cdc_get_line_coding(udevice_t device, ureq_t setup)
*/
static rt_err_t _cdc_set_line_coding(udevice_t device, ureq_t setup)
{
- struct ucdc_line_coding data;
- rt_err_t ret;
-
RT_ASSERT(device != RT_NULL);
RT_ASSERT(setup != RT_NULL);
- rt_completion_init(&device->dcd->completion);
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_cdc_set_line_coding\n"));
- dcd_ep_read(device->dcd, 0, (void*)&data, setup->length);
-
- ret = rt_completion_wait(&device->dcd->completion, 100);
- if(ret != RT_EOK)
- {
- rt_kprintf("_cdc_set_line_coding timeout\n");
- }
+ rt_usbd_ep0_read(device, (void*)&line_coding, sizeof(struct ucdc_line_coding),
+ _cdc_set_line_coding_callback);
return RT_EOK;
}
@@ -349,11 +370,16 @@ static rt_err_t _cdc_set_line_coding(udevice_t device, ureq_t setup)
*
* @return RT_EOK on successful.
*/
-static rt_err_t _interface_handler(udevice_t device, uclass_t cls, ureq_t setup)
+static rt_err_t _interface_handler(ufunction_t func, ureq_t setup)
{
- RT_ASSERT(device != RT_NULL);
+ struct vcom *data;
+
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
RT_ASSERT(setup != RT_NULL);
+ data = (struct vcom*)func->user_data;
+
switch(setup->request)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
@@ -367,14 +393,14 @@ static rt_err_t _interface_handler(udevice_t device, uclass_t cls, ureq_t setup)
case CDC_CLEAR_COMM_FEATURE:
break;
case CDC_SET_LINE_CODING:
- _cdc_set_line_coding(device, setup);
- vcom_connected = RT_TRUE;
+ _cdc_set_line_coding(func->device, setup);
+ data->connected = RT_TRUE;
break;
case CDC_GET_LINE_CODING:
- _cdc_get_line_coding(device, setup);
+ _cdc_get_line_coding(func->device, setup);
break;
case CDC_SET_CONTROL_LINE_STATE:
- dcd_send_status(device->dcd);
+ dcd_ep0_send_status(func->device->dcd);
break;
case CDC_SEND_BREAK:
break;
@@ -387,92 +413,66 @@ static rt_err_t _interface_handler(udevice_t device, uclass_t cls, ureq_t setup)
}
/**
- * This function will run cdc class, it will be called on handle set configuration request.
+ * This function will run cdc function, it will be called on handle set configuration request.
*
- * @param device the usb device object.
+ * @param func the usb function object.
*
* @return RT_EOK on successful.
*/
-static rt_err_t _class_run(udevice_t device, uclass_t cls)
+static rt_err_t _function_enable(ufunction_t func)
{
- cdc_eps_t eps;
- RT_ASSERT(device != RT_NULL);
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("cdc class run\n"));
- eps = (cdc_eps_t)cls->eps;
+ struct vcom *data;
- eps->ep_in->buffer = tx_buf;
- eps->ep_out->buffer = rx_buf;
+ RT_ASSERT(func != RT_NULL);
- _vcom_reset_state();
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("cdc function enable\n"));
- dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer,
- eps->ep_out->ep_desc->wMaxPacketSize);
+ _vcom_reset_state(func);
+
+ data = (struct vcom*)func->user_data;
+ data->ep_out->buffer = rt_malloc(CDC_RX_BUFSIZE);
+ data->ep_out->request.buffer = data->ep_out->buffer;
+ data->ep_out->request.size = EP_MAXPACKET(data->ep_out);
+
+ data->ep_out->request.req_type = UIO_REQUEST_READ_BEST;
+ rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
+
return RT_EOK;
}
/**
- * This function will stop cdc class, it will be called on handle set configuration request.
+ * This function will stop cdc function, it will be called on handle set configuration request.
*
- * @param device the usb device object.
+ * @param func the usb function object.
*
* @return RT_EOK on successful.
*/
-static rt_err_t _class_stop(udevice_t device, uclass_t cls)
+static rt_err_t _function_disable(ufunction_t func)
{
- RT_ASSERT(device != RT_NULL);
+ struct vcom *data;
- RT_DEBUG_LOG(RT_DEBUG_USB, ("cdc class stop\n"));
+ RT_ASSERT(func != RT_NULL);
- _vcom_reset_state();
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("cdc function disable\n"));
- return RT_EOK;
-}
+ _vcom_reset_state(func);
-/**
- * This function will handle system sof event.
- *
- * @param device the usb device object.
- *
- * @return RT_EOK on successful.
- */
-static rt_err_t _class_sof_handler(udevice_t device, uclass_t cls)
-{
- rt_uint32_t level;
- rt_size_t size;
- cdc_eps_t eps;
-
- if (vcom_connected != RT_TRUE)
- return -RT_ERROR;
-
- if (vcom_in_sending)
+ data = (struct vcom*)func->user_data;
+ if(data->ep_out->buffer != RT_NULL)
{
- return RT_EOK;
+ rt_free(data->ep_out->buffer);
+ data->ep_out->buffer = RT_NULL;
}
- eps = (cdc_eps_t)cls->eps;
-
- size = rt_ringbuffer_data_len(&tx_ringbuffer);
- if (size == 0)
- return -RT_EFULL;
-
- level = rt_hw_interrupt_disable();
- rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, size);
- rt_hw_interrupt_enable(level);
-
- /* send data to host */
- vcom_in_sending = RT_TRUE;
- dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, size);
-
return RT_EOK;
}
-static struct uclass_ops ops =
+static struct ufunction_ops ops =
{
- _class_run,
- _class_stop,
- _class_sof_handler,
+ _function_enable,
+ _function_disable,
+ RT_NULL,
};
/**
@@ -483,7 +483,8 @@ static struct uclass_ops ops =
*
* @return RT_EOK on successful.
*/
-static rt_err_t _cdc_descriptor_config(ucdc_comm_desc_t comm, rt_uint8_t cintf_nr, ucdc_data_desc_t data, rt_uint8_t dintf_nr)
+static rt_err_t _cdc_descriptor_config(ucdc_comm_desc_t comm,
+ rt_uint8_t cintf_nr, ucdc_data_desc_t data, rt_uint8_t dintf_nr)
{
comm->call_mgmt_desc.data_interface = dintf_nr;
comm->union_desc.master_interface = cintf_nr;
@@ -496,16 +497,16 @@ static rt_err_t _cdc_descriptor_config(ucdc_comm_desc_t comm, rt_uint8_t cintf_n
}
/**
- * This function will create a cdc class instance.
+ * This function will create a cdc function instance.
*
* @param device the usb device object.
*
* @return RT_EOK on successful.
*/
-uclass_t rt_usbd_class_cdc_create(udevice_t device)
+ufunction_t rt_usbd_function_cdc_create(udevice_t device)
{
- uclass_t cdc;
- cdc_eps_t eps;
+ ufunction_t func;
+ struct vcom* data;
uintf_t intf_comm, intf_data;
ualtsetting_t comm_setting, data_setting;
ucdc_data_desc_t data_desc;
@@ -516,19 +517,26 @@ uclass_t rt_usbd_class_cdc_create(udevice_t device)
/* set usb device string description */
rt_usbd_device_set_string(device, _ustring);
- /* create a cdc class */
- cdc = rt_usbd_class_create(device, &dev_desc, &ops);
- /* create a cdc class endpoints collection */
- eps = rt_malloc(sizeof(struct cdc_eps));
- cdc->eps = (void*)eps;
+
+ /* create a cdc function */
+ func = rt_usbd_function_new(device, &dev_desc, &ops);
+ rt_usbd_device_set_qualifier(device, &dev_qualifier);
+
+ /* allocate memory for cdc vcom data */
+ data = (struct vcom*)rt_malloc(sizeof(struct vcom));
+ rt_memset(data, 0, sizeof(struct vcom));
+ func->user_data = (void*)data;
+
+ /* initilize vcom */
+ rt_usb_vcom_init(func);
/* create a cdc communication interface and a cdc data interface */
- intf_comm = rt_usbd_interface_create(device, _interface_handler);
- intf_data = rt_usbd_interface_create(device, _interface_handler);
+ intf_comm = rt_usbd_interface_new(device, _interface_handler);
+ intf_data = rt_usbd_interface_new(device, _interface_handler);
/* create a communication alternate setting and a data alternate setting */
- comm_setting = rt_usbd_altsetting_create(sizeof(struct ucdc_comm_descriptor));
- data_setting = rt_usbd_altsetting_create(sizeof(struct ucdc_data_descriptor));
+ comm_setting = rt_usbd_altsetting_new(sizeof(struct ucdc_comm_descriptor));
+ data_setting = rt_usbd_altsetting_new(sizeof(struct ucdc_data_descriptor));
/* config desc in alternate setting */
rt_usbd_altsetting_config_descriptor(comm_setting, &_comm_desc,
@@ -537,39 +545,39 @@ uclass_t rt_usbd_class_cdc_create(udevice_t device)
/* configure the cdc interface descriptor */
_cdc_descriptor_config(comm_setting->desc, intf_comm->intf_num, data_setting->desc, intf_data->intf_num);
- /* create a bulk in and a bulk endpoint */
- data_desc = (ucdc_data_desc_t)data_setting->desc;
- eps->ep_out = rt_usbd_endpoint_create(&data_desc->ep_out_desc, _ep_out_handler);
- eps->ep_in = rt_usbd_endpoint_create(&data_desc->ep_in_desc, _ep_in_handler);
-
- /* add the bulk out and bulk in endpoints to the data alternate setting */
- rt_usbd_altsetting_add_endpoint(data_setting, eps->ep_in);
- rt_usbd_altsetting_add_endpoint(data_setting, eps->ep_out);
-
- /* add the data alternate setting to the data interface
- then set default setting of the interface */
- rt_usbd_interface_add_altsetting(intf_data, data_setting);
- rt_usbd_set_altsetting(intf_data, 0);
-
- /* add the cdc data interface to cdc class */
- rt_usbd_class_add_interface(cdc, intf_data);
-
/* create a command endpoint */
comm_desc = (ucdc_comm_desc_t)comm_setting->desc;
- eps->ep_cmd = rt_usbd_endpoint_create(&comm_desc->ep_desc, _ep_cmd_handler);
+ data->ep_cmd = rt_usbd_endpoint_new(&comm_desc->ep_desc, _ep_cmd_handler);
/* add the command endpoint to the cdc communication interface */
- rt_usbd_altsetting_add_endpoint(comm_setting, eps->ep_cmd);
+ rt_usbd_altsetting_add_endpoint(comm_setting, data->ep_cmd);
/* add the communication alternate setting to the communication interface,
then set default setting of the interface */
rt_usbd_interface_add_altsetting(intf_comm, comm_setting);
rt_usbd_set_altsetting(intf_comm, 0);
- /* add the communication interface to the cdc class */
- rt_usbd_class_add_interface(cdc, intf_comm);
+ /* add the communication interface to the cdc function */
+ rt_usbd_function_add_interface(func, intf_comm);
- return cdc;
+ /* create a bulk in and a bulk endpoint */
+ data_desc = (ucdc_data_desc_t)data_setting->desc;
+ data->ep_out = rt_usbd_endpoint_new(&data_desc->ep_out_desc, _ep_out_handler);
+ data->ep_in = rt_usbd_endpoint_new(&data_desc->ep_in_desc, _ep_in_handler);
+
+ /* add the bulk out and bulk in endpoints to the data alternate setting */
+ rt_usbd_altsetting_add_endpoint(data_setting, data->ep_in);
+ rt_usbd_altsetting_add_endpoint(data_setting, data->ep_out);
+
+ /* add the data alternate setting to the data interface
+ then set default setting of the interface */
+ rt_usbd_interface_add_altsetting(intf_data, data_setting);
+ rt_usbd_set_altsetting(intf_data, 0);
+
+ /* add the cdc data interface to cdc function */
+ rt_usbd_function_add_interface(func, intf_data);
+
+ return func;
}
/**
@@ -597,80 +605,106 @@ static rt_err_t _vcom_control(struct rt_serial_device *serial,
return RT_EOK;
}
-static int _vcom_putc(struct rt_serial_device *serial, char c)
+static int _vcom_getc(struct rt_serial_device *serial)
{
+ int result;
+ rt_uint8_t ch;
rt_uint32_t level;
- int cnt;
-
- if (vcom_connected != RT_TRUE)
- {
- return 0;
- }
+ struct ufunction *func;
+ struct vcom *data;
+
+ func = (struct ufunction*)serial->parent.user_data;
+ data = (struct vcom*)func->user_data;
- /* if the buffer is full, there is a chance that the host would pull some
- * data out soon. But we cannot rely on that and if we wait to long, just
- * return. */
- for (cnt = 500;
- rt_ringbuffer_space_len(&tx_ringbuffer) == 0 && cnt;
- cnt--)
- {
- /*rt_kprintf("wait for %d\n", cnt);*/
- if (vcom_connected != RT_TRUE)
- return 0;
- }
- if (cnt == 0)
- {
- /* OK, we believe that the connection is lost. So don't send any more
- * data and act as the USB cable is not plugged in. Reset the VCOM
- * state machine */
- _vcom_reset_state();
- return 0;
- }
+ result = -1;
level = rt_hw_interrupt_disable();
- if (rt_ringbuffer_space_len(&tx_ringbuffer))
+
+ if(rt_ringbuffer_getchar(&data->rx_ringbuffer, &ch) != 0)
{
- rt_ringbuffer_putchar(&tx_ringbuffer, c);
+ result = ch;
}
+
rt_hw_interrupt_enable(level);
- return 1;
+ return result;
}
-static int _vcom_getc(struct rt_serial_device *serial)
+static rt_size_t _vcom_tx(struct rt_serial_device *serial,
+ const char *buf, rt_size_t size)
{
- int result;
- rt_uint8_t ch;
- rt_uint32_t level;
+ struct vcom_tx_msg msg;
- result = -1;
+ RT_ASSERT(serial != RT_NULL);
+ RT_ASSERT(buf != RT_NULL);
- level = rt_hw_interrupt_disable();
- if (rt_ringbuffer_data_len(&rx_ringbuffer))
+ msg.buf = buf;
+ msg.serial = serial;
+ msg.size = size;
+
+ if (rt_mq_send(&vcom_tx_thread_mq, (void*)&msg,
+ sizeof(struct vcom_tx_msg)) != RT_EOK)
{
- rt_ringbuffer_getchar(&rx_ringbuffer, &ch);
- result = ch;
+ rt_kprintf("vcom send msg fail\n");
+ return 0;
}
- rt_hw_interrupt_enable(level);
-
- return result;
+
+ return size;
}
static const struct rt_uart_ops usb_vcom_ops =
{
_vcom_configure,
_vcom_control,
- _vcom_putc,
+ RT_NULL,
_vcom_getc,
+ RT_NULL,
+ //_vcom_tx,
};
-void rt_usb_vcom_init(void)
+/* Vcom Tx Thread */
+static void vcom_tx_thread_entry(void* parameter)
{
- struct serial_configure config;
+ struct vcom_tx_msg msg;
+
+ while (1)
+ {
+ if (rt_mq_recv(&vcom_tx_thread_mq, (void*)&msg,
+ sizeof(struct vcom_tx_msg), RT_WAITING_FOREVER) == RT_EOK)
+ {
+ struct ufunction *func;
+ struct vcom *data;
+
+ func = (struct ufunction*)msg.serial->parent.user_data;
+ data = (struct vcom*)func->user_data;
+ if (!data->connected)
+ {
+ continue;
+ }
+
+ rt_completion_init(&data->wait);
+ data->ep_in->request.buffer = (void*)msg.buf;
+ data->ep_in->request.size = msg.size;
+ data->ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
+
+ if (rt_completion_wait(&data->wait, TX_TIMEOUT) != RT_EOK)
+ {
+ rt_kprintf("vcom tx timeout\n");
+ }
+ }
+ }
+}
+
+static void rt_usb_vcom_init(struct ufunction *func)
+{
+ rt_err_t result = RT_EOK;
+ struct serial_configure config;
+ struct vcom *data = (struct vcom*)func->user_data;
+
/* initialize ring buffer */
- rt_ringbuffer_init(&rx_ringbuffer, rx_rbp, CDC_RX_BUFSIZE);
- rt_ringbuffer_init(&tx_ringbuffer, tx_rbp, CDC_TX_BUFSIZE);
+ rt_ringbuffer_init(&data->rx_ringbuffer, data->rx_rbp, CDC_RX_BUFSIZE);
config.baud_rate = BAUD_RATE_115200;
config.bit_order = BIT_ORDER_LSB;
@@ -679,14 +713,25 @@ void rt_usb_vcom_init(void)
config.stop_bits = STOP_BITS_1;
config.invert = NRZ_NORMAL;
- vcom_serial.ops = &usb_vcom_ops;
- vcom_serial.int_rx = &vcom_int_rx;
- vcom_serial.config = config;
+ data->serial.ops = &usb_vcom_ops;
+ data->serial.int_rx = &data->vcom_int_rx;
+ data->serial.config = config;
/* register vcom device */
- rt_hw_serial_register(&vcom_serial, "vcom",
- RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
- RT_NULL);
+ rt_hw_serial_register(&data->serial, VCOM_DEVICE,
+ RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX,
+ func);
+
+ /* create an vcom message queue */
+ rt_mq_init(&vcom_tx_thread_mq, "vcomq", vcom_tx_thread_mq_pool, VCOM_MQ_MSG_SZ,
+ sizeof(vcom_tx_thread_mq_pool), RT_IPC_FLAG_FIFO);
+
+ /* init usb device thread */
+ rt_thread_init(&vcom_thread, "vcom", vcom_tx_thread_entry, RT_NULL,
+ vcom_thread_stack, 512, 8, 20);
+ result = rt_thread_startup(&vcom_thread);
+ RT_ASSERT(result == RT_EOK);
}
#endif
+
diff --git a/components/drivers/usb/usbdevice/class/mstorage.c b/components/drivers/usb/usbdevice/class/mstorage.c
index b0351f63e5..4ee45189f8 100644
--- a/components/drivers/usb/usbdevice/class/mstorage.c
+++ b/components/drivers/usb/usbdevice/class/mstorage.c
@@ -21,7 +21,8 @@
* Date Author Notes
* 2012-10-01 Yi Qiu first version
* 2012-11-25 Heyuanjie87 reduce the memory consumption
- * 2012-12-09 Heyuanjie87 change class and endpoint handler
+ * 2012-12-09 Heyuanjie87 change function and endpoint handler
+ * 2013-07-25 Yi Qiu update for USB CV test
*/
#include <rtthread.h>
@@ -31,19 +32,55 @@
#ifdef RT_USB_DEVICE_MSTORAGE
-#define STATUS_CBW 0x00
-#define STATUS_CSW 0x01
-#define STATUS_RECEIVE 0x02
-#define STATUS_SEND 0x03
+enum STAT
+{
+ STAT_CBW,
+ STAT_CMD,
+ STAT_CSW,
+ STAT_RECEIVE,
+ STAT_SEND,
+};
+
+typedef enum
+{
+ FIXED,
+ COUNT,
+ BLOCK_COUNT,
+}CB_SIZE_TYPE;
-static int status = STATUS_CBW;
-ALIGN(RT_ALIGN_SIZE)
-static struct ustorage_csw csw;
-static rt_device_t disk;
-static rt_uint32_t _block;
-static rt_uint32_t _count, _size;
-static struct rt_device_blk_geometry geometry;
-static rt_uint32_t _removed = 0;
+typedef enum
+{
+ DIR_IN,
+ DIR_OUT,
+ DIR_NONE,
+}CB_DIR;
+
+typedef rt_size_t (*cbw_handler)(ufunction_t func, ustorage_cbw_t cbw);
+
+struct scsi_cmd
+{
+ rt_uint16_t cmd;
+ cbw_handler handler;
+ rt_size_t cmd_len;
+ CB_SIZE_TYPE type;
+ rt_size_t data_size;
+ CB_DIR dir;
+};
+
+struct mstorage
+{
+ struct ustorage_csw csw_response;
+ uep_t ep_in;
+ uep_t ep_out;
+ int status;
+ rt_uint32_t cb_data_size;
+ rt_device_t disk;
+ rt_uint32_t block;
+ rt_int32_t count;
+ rt_int32_t size;
+ struct scsi_cmd* processing;
+ struct rt_device_blk_geometry geometry;
+};
static struct udevice_descriptor dev_desc =
{
@@ -63,6 +100,18 @@ static struct udevice_descriptor dev_desc =
USB_DYNAMIC, //bNumConfigurations;
};
+static struct usb_qualifier_descriptor dev_qualifier =
+{
+ sizeof(dev_qualifier),
+ USB_DESC_TYPE_DEVICEQUALIFIER,
+ 0x0200,
+ USB_CLASS_MASS_STORAGE,
+ 0x00,
+ 64,
+ 0x01,
+ 0,
+};
+
const static struct umass_descriptor _mass_desc =
{
USB_DESC_LENGTH_INTERFACE, //bLength;
@@ -95,270 +144,489 @@ const static char* _ustring[] =
"Language",
"RT-Thread Team.",
"RTT Mass Storage",
- "1.1.0",
+ "320219198301",
"Configuration",
"Interface",
};
+static rt_size_t _test_unit_ready(ufunction_t func, ustorage_cbw_t cbw);
+static rt_size_t _request_sense(ufunction_t func, ustorage_cbw_t cbw);
+static rt_size_t _inquiry_cmd(ufunction_t func, ustorage_cbw_t cbw);
+static rt_size_t _allow_removal(ufunction_t func, ustorage_cbw_t cbw);
+static rt_size_t _start_stop(ufunction_t func, ustorage_cbw_t cbw);
+static rt_size_t _mode_sense_6(ufunction_t func, ustorage_cbw_t cbw);
+static rt_size_t _read_capacities(ufunction_t func, ustorage_cbw_t cbw);
+static rt_size_t _read_capacity(ufunction_t func, ustorage_cbw_t cbw);
+static rt_size_t _read_10(ufunction_t func, ustorage_cbw_t cbw);
+static rt_size_t _write_10(ufunction_t func, ustorage_cbw_t cbw);
+static rt_size_t _verify_10(ufunction_t func, ustorage_cbw_t cbw);
+
+static struct scsi_cmd cmd_data[] =
+{
+ {SCSI_TEST_UNIT_READY, _test_unit_ready, 6, FIXED, 0, DIR_NONE},
+ {SCSI_REQUEST_SENSE, _request_sense, 6, COUNT, 0, DIR_IN},
+ {SCSI_INQUIRY_CMD, _inquiry_cmd, 6, COUNT, 0, DIR_IN},
+ {SCSI_ALLOW_REMOVAL, _allow_removal, 6, FIXED, 0, DIR_NONE},
+ {SCSI_MODE_SENSE_6, _mode_sense_6, 6, COUNT, 0, DIR_IN},
+ {SCSI_START_STOP, _start_stop, 6, FIXED, 0, DIR_NONE},
+ {SCSI_READ_CAPACITIES, _read_capacities, 10, COUNT, 0, DIR_NONE},
+ {SCSI_READ_CAPACITY, _read_capacity, 10, FIXED, 8, DIR_IN},
+ {SCSI_READ_10, _read_10, 10, BLOCK_COUNT, 0, DIR_IN},
+ {SCSI_WRITE_10, _write_10, 10, BLOCK_COUNT, 0, DIR_OUT},
+ {SCSI_VERIFY_10, _verify_10, 10, FIXED, 0, DIR_NONE},
+};
+
+static void _send_status(ufunction_t func)
+{
+ struct mstorage *data;
+
+ RT_ASSERT(func != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_send_status\n"));
+
+ data = (struct mstorage*)func->user_data;
+ data->ep_in->request.buffer = (rt_uint8_t*)&data->csw_response;
+ data->ep_in->request.size = SIZEOF_CSW;
+ data->ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
+ data->status = STAT_CSW;
+}
+
+static rt_size_t _test_unit_ready(ufunction_t func, ustorage_cbw_t cbw)
+{
+ struct mstorage *data;
+
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_test_unit_ready\n"));
+
+ data = (struct mstorage*)func->user_data;
+ data->csw_response.status = 0;
+
+ return 0;
+}
+
+static rt_size_t _allow_removal(ufunction_t func, ustorage_cbw_t cbw)
+{
+ struct mstorage *data;
+
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_allow_removal\n"));
+
+ data = (struct mstorage*)func->user_data;
+ data->csw_response.status = 0;
+
+ return 0;
+}
+
/**
- * This function will allocate an usb device instance from system.
+ * This function will handle inquiry command request.
*
- * @param parent the hub instance to which the new allocated device attached.
- * @param port the hub port.
+ * @param func the usb function object.
+ * @param cbw the command block wrapper.
*
- * @return the allocate instance on successful, or RT_NULL on failure.
+ * @return RT_EOK on successful.
*/
-static rt_err_t _inquiry_cmd(udevice_t device, uep_t ep_in)
+
+static rt_size_t _inquiry_cmd(ufunction_t func, ustorage_cbw_t cbw)
{
- rt_uint8_t data[36];
+ struct mstorage *data;
+ rt_uint8_t *buf;
- *(rt_uint32_t*)&data[0] = 0x0 | (0x80 << 8);
- *(rt_uint32_t*)&data[4] = 31;
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
+ RT_ASSERT(cbw != RT_NULL);
- rt_memset(&data[8], 0x20, 28);
- rt_memcpy(&data[8], "RTT", 3);
- rt_memcpy(&data[16], "USB Disk", 8);
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_inquiry_cmd\n"));
- dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 36);
+ data = (struct mstorage*)func->user_data;
+ buf = data->ep_in->buffer;
- return RT_EOK;
+ *(rt_uint32_t*)&buf[0] = 0x0 | (0x80 << 8);
+ *(rt_uint32_t*)&buf[4] = 31;
+
+ rt_memset(&buf[8], 0x20, 28);
+ rt_memcpy(&buf[8], "RTT", 3);
+ rt_memcpy(&buf[16], "USB Disk", 8);
+
+ data->cb_data_size = MIN(data->cb_data_size, SIZEOF_INQUIRY_CMD);
+ data->ep_in->request.buffer = buf;
+ data->ep_in->request.size = data->cb_data_size;
+ data->ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
+ data->status = STAT_CMD;
+
+ return data->cb_data_size;
}
/**
* This function will handle sense request.
*
- * @param device the usb device object.
+ * @param func the usb function object.
+ * @param cbw the command block wrapper.
*
* @return RT_EOK on successful.
*/
-static rt_err_t _request_sense(udevice_t device, uep_t ep_in)
+static rt_size_t _request_sense(ufunction_t func, ustorage_cbw_t cbw)
{
- struct request_sense_data data;
+ struct mstorage *data;
+ struct request_sense_data *buf;
- data.ErrorCode = 0x70;
- data.Valid = 0;
- data.SenseKey = 2; //TODO
- data.Information[0] = 0;
- data.Information[1] = 0;
- data.Information[2] = 0;
- data.Information[3] = 0;
- data.AdditionalSenseLength = 0x0a;
- data.AdditionalSenseCode = 0x3a; //TODO
- data.AdditionalSenseCodeQualifier =0;
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
+ RT_ASSERT(cbw != RT_NULL);
- dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, sizeof(struct request_sense_data));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_request_sense\n"));
+
+ data = (struct mstorage*)func->user_data;
+ buf = (struct request_sense_data *)data->ep_in->buffer;
- return RT_EOK;
+ buf->ErrorCode = 0x70;
+ buf->Valid = 0;
+ buf->SenseKey = 2;
+ buf->Information[0] = 0;
+ buf->Information[1] = 0;
+ buf->Information[2] = 0;
+ buf->Information[3] = 0;
+ buf->AdditionalSenseLength = 0x0a;
+ buf->AdditionalSenseCode = 0x3a;
+ buf->AdditionalSenseCodeQualifier = 0;
+
+ data->cb_data_size = MIN(data->cb_data_size, SIZEOF_REQUEST_SENSE);
+ data->ep_in->request.buffer = (rt_uint8_t*)data->ep_in->buffer;
+ data->ep_in->request.size = data->cb_data_size;
+ data->ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
+ data->status = STAT_CMD;
+
+ return data->cb_data_size;
}
/**
* This function will handle mode_sense_6 request.
*
- * @param device the usb device object.
+ * @param func the usb function object.
+ * @param cbw the command block wrapper.
*
* @return RT_EOK on successful.
*/
-static rt_err_t _mode_sense_6(udevice_t device, uep_t ep_in)
+static rt_size_t _mode_sense_6(ufunction_t func, ustorage_cbw_t cbw)
{
- rt_uint8_t data[4];
+ struct mstorage *data;
+ rt_uint8_t *buf;
- data[0]=3;
- data[1]=0;
- data[2]=0;
- data[3]=0;
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
+ RT_ASSERT(cbw != RT_NULL);
- dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 4);
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_mode_sense_6\n"));
- return RT_EOK;
+ data = (struct mstorage*)func->user_data;
+ buf = data->ep_in->buffer;
+ buf[0] = 3;
+ buf[1] = 0;
+ buf[2] = 0;
+ buf[3] = 0;
+
+ data->cb_data_size = MIN(data->cb_data_size, SIZEOF_MODE_SENSE_6);
+ data->ep_in->request.buffer = buf;
+ data->ep_in->request.size = data->cb_data_size;
+ data->ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
+ data->status = STAT_CMD;
+
+ return data->cb_data_size;
}
/**
* This function will handle read_capacities request.
*
- * @param device the usb device object.
+ * @param func the usb function object.
+ * @param cbw the command block wrapper.
*
* @return RT_EOK on successful.
*/
-static rt_err_t _read_capacities(udevice_t device, uep_t ep_in)
+static rt_size_t _read_capacities(ufunction_t func, ustorage_cbw_t cbw)
{
- rt_uint8_t data[12];
+ struct mstorage *data;
+ rt_uint8_t *buf;
rt_uint32_t sector_count, sector_size;
- RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
+ RT_ASSERT(cbw != RT_NULL);
- sector_count = geometry.sector_count;
- sector_size = geometry.bytes_per_sector;
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_read_capacities\n"));
- *(rt_uint32_t*)&data[0] = 0x08000000;
- data[4] = sector_count >> 24;
- data[5] = 0xff & (sector_count >> 16);
- data[6] = 0xff & (sector_count >> 8);
- data[7] = 0xff & (sector_count);
- data[8] = 0x02;
- data[9] = 0xff & (sector_size >> 16);
- data[10] = 0xff & (sector_size >> 8);
- data[11] = 0xff & sector_size;
+ data = (struct mstorage*)func->user_data;
+ buf = data->ep_in->buffer;
+ sector_count = data->geometry.sector_count;
+ sector_size = data->geometry.bytes_per_sector;
- dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 12);
+ *(rt_uint32_t*)&buf[0] = 0x08000000;
+ buf[4] = sector_count >> 24;
+ buf[5] = 0xff & (sector_count >> 16);
+ buf[6] = 0xff & (sector_count >> 8);
+ buf[7] = 0xff & (sector_count);
+ buf[8] = 0x02;
+ buf[9] = 0xff & (sector_size >> 16);
+ buf[10] = 0xff & (sector_size >> 8);
+ buf[11] = 0xff & sector_size;
- return RT_EOK;
+ data->cb_data_size = MIN(data->cb_data_size, SIZEOF_READ_CAPACITIES);
+ data->ep_in->request.buffer = buf;
+ data->ep_in->request.size = data->cb_data_size;
+ data->ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
+ data->status = STAT_CMD;
+
+ return data->cb_data_size;
}
/**
* This function will handle read_capacity request.
*
- * @param device the usb device object.
+ * @param func the usb function object.
+ * @param cbw the command block wapper.
*
* @return RT_EOK on successful.
*/
-static rt_err_t _read_capacity(udevice_t device, uep_t ep_in)
+static rt_size_t _read_capacity(ufunction_t func, ustorage_cbw_t cbw)
{
- rt_uint8_t data[8];
+ struct mstorage *data;
+
+ rt_uint8_t *buf;
rt_uint32_t sector_count, sector_size;
- RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
+ RT_ASSERT(cbw != RT_NULL);
- sector_count = geometry.sector_count;
- sector_size = geometry.bytes_per_sector;
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_read_capacity\n"));
- data[0] = sector_count >> 24;
- data[1] = 0xff & (sector_count >> 16);
- data[2] = 0xff & (sector_count >> 8);
- data[3] = 0xff & (sector_count);
- data[4] = 0x0;
- data[5] = 0xff & (sector_size >> 16);
- data[6] = 0xff & (sector_size >> 8);
- data[7] = 0xff & sector_size;
+ data = (struct mstorage*)func->user_data;
+ buf = data->ep_in->buffer;
+ sector_count = data->geometry.sector_count;
+ sector_size = data->geometry.bytes_per_sector;
- dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 8);
+ buf[0] = sector_count >> 24;
+ buf[1] = 0xff & (sector_count >> 16);
+ buf[2] = 0xff & (sector_count >> 8);
+ buf[3] = 0xff & (sector_count);
+ buf[4] = 0x0;
+ buf[5] = 0xff & (sector_size >> 16);
+ buf[6] = 0xff & (sector_size >> 8);
+ buf[7] = 0xff & sector_size;
- return RT_EOK;
+ data->cb_data_size = MIN(data->cb_data_size, SIZEOF_READ_CAPACITY);
+ data->ep_in->request.buffer = buf;
+ data->ep_in->request.size = data->cb_data_size;
+ data->ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
+ data->status = STAT_CMD;
+
+ return data->cb_data_size;
}
/**
* This function will handle read_10 request.
*
- * @param device the usb device object.
+ * @param func the usb function object.
* @param cbw the command block wrapper.
*
* @return RT_EOK on successful.
*/
-static rt_err_t _read_10(udevice_t device, ustorage_cbw_t cbw, uep_t ep_in)
+static rt_size_t _read_10(ufunction_t func, ustorage_cbw_t cbw)
{
- RT_ASSERT(device != RT_NULL);
+ struct mstorage *data;
+ rt_size_t size;
+
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
RT_ASSERT(cbw != RT_NULL);
- _block = cbw->cb[2]<<24 | cbw->cb[3]<<16 | cbw->cb[4]<<8 |
- cbw->cb[5]<<0 ;
-
- _count = cbw->cb[7]<<8 | cbw->cb[8]<<0 ;
+ data = (struct mstorage*)func->user_data;
+ data->block = cbw->cb[2]<<24 | cbw->cb[3]<<16 | cbw->cb[4]<<8 |
+ cbw->cb[5]<<0;
+ data->count = cbw->cb[7]<<8 | cbw->cb[8]<<0;
- RT_ASSERT(_count < geometry.sector_count);
+ RT_ASSERT(data->count < data->geometry.sector_count);
- rt_device_read(disk, _block, ep_in->buffer, 1);
- dcd_ep_write(device->dcd, ep_in, ep_in->buffer, geometry.bytes_per_sector);
- _count --;
- if (_count)
- {
- _block ++;
- status = STATUS_SEND;
- }
- else
+ data->csw_response.data_reside = data->cb_data_size;
+ size = rt_device_read(data->disk, data->block, data->ep_in->buffer, 1);
+ if(size == 0)
{
- status = STATUS_CSW;
+ rt_kprintf("read data error\n");
}
- return RT_EOK;
+ data->ep_in->request.buffer = data->ep_in->buffer;
+ data->ep_in->request.size = data->geometry.bytes_per_sector;
+ data->ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
+ data->status = STAT_SEND;
+
+ return data->geometry.bytes_per_sector;
}
/**
* This function will handle write_10 request.
*
- * @param device the usb device object.
+ * @param func the usb function object.
* @param cbw the command block wrapper.
*
* @return RT_EOK on successful.
*/
-static rt_err_t _write_10(udevice_t device, ustorage_cbw_t cbw, uep_t ep_out)
+static rt_size_t _write_10(ufunction_t func, ustorage_cbw_t cbw)
{
- RT_ASSERT(device != RT_NULL);
+ struct mstorage *data;
+
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
RT_ASSERT(cbw != RT_NULL);
- _block = cbw->cb[2]<<24 | cbw->cb[3]<<16 | cbw->cb[4]<<8 |
- cbw->cb[5]<<0 ;
- _count = cbw->cb[7]<<8 | cbw->cb[8]<<0;
- csw.data_reside = cbw->xfer_len;
- _size = _count * geometry.bytes_per_sector;
+ data = (struct mstorage*)func->user_data;
- RT_DEBUG_LOG(RT_DEBUG_USB, ("_write_10 count 0x%x 0x%x\n",
- _count, geometry.sector_count));
+ data->block = cbw->cb[2]<<24 | cbw->cb[3]<<16 | cbw->cb[4]<<8 |
+ cbw->cb[5]<<0;
+ data->count = cbw->cb[7]<<8 | cbw->cb[8];
+ data->csw_response.data_reside = cbw->xfer_len;
+ data->size = data->count * data->geometry.bytes_per_sector;
- dcd_ep_read(device->dcd, ep_out, ep_out->buffer, geometry.bytes_per_sector);
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_write_10 count 0x%x block 0x%x 0x%x\n",
+ data->count, data->block, data->geometry.sector_count));
- return RT_EOK;
+ data->csw_response.data_reside = data->cb_data_size;
+
+ data->ep_out->request.buffer = data->ep_out->buffer;
+ data->ep_out->request.size = data->geometry.bytes_per_sector;
+ data->ep_out->request.req_type = UIO_REQUEST_READ_FULL;
+ rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
+ data->status = STAT_RECEIVE;
+
+ return data->geometry.bytes_per_sector;
}
/**
* This function will handle verify_10 request.
*
- * @param device the usb device object.
+ * @param func the usb function object.
*
* @return RT_EOK on successful.
*/
-static rt_err_t _verify_10(udevice_t device)
+static rt_size_t _verify_10(ufunction_t func, ustorage_cbw_t cbw)
{
- return RT_EOK;
-}
+ struct mstorage *data;
-static void _send_status(udevice_t device, mass_eps_t eps, ustorage_csw_t csw)
-{
- dcd_ep_write(device->dcd, eps->ep_in, (rt_uint8_t*)csw, SIZEOF_CSW);
- dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer, SIZEOF_CBW);
- status = STATUS_CBW;
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_verify_10\n"));
+
+ data = (struct mstorage*)func->user_data;
+ data->csw_response.status = 0;
+
+ return 0;
}
-static void _start_stop(ustorage_cbw_t cbw)
+static rt_size_t _start_stop(ufunction_t func,
+ ustorage_cbw_t cbw)
{
- //TODO
- _removed = 1;
+ struct mstorage *data;
+
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_start_stop\n"));
+
+ data = (struct mstorage*)func->user_data;
+ data->csw_response.status = 0;
+
+ return 0;
}
-/**
- * This function will handle mass storage bulk in endpoint request.
- *
- * @param device the usb device object.
- * @param size request size.
- *
- * @return RT_EOK.
- */
-static rt_err_t _ep_in_handler(udevice_t device, uclass_t cls, rt_size_t size)
+static rt_err_t _ep_in_handler(ufunction_t func, rt_size_t size)
{
- mass_eps_t eps;
- RT_ASSERT(device != RT_NULL);
+ struct mstorage *data;
+
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
- eps = cls->eps;
- if (status == STATUS_CSW)
- {
- _send_status(device, eps, &csw);
- }
- else if (status == STATUS_SEND)
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_in_handler\n"));
+
+ data = (struct mstorage*)func->user_data;
+
+ switch(data->status)
{
- rt_device_read(disk, _block, eps->ep_in->buffer, 1);
- dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer,
- geometry.bytes_per_sector);
- _count --;
- if (_count)
+ case STAT_CSW:
+ if(data->ep_in->request.size != SIZEOF_CSW)
{
- _block ++;
- status = STATUS_SEND;
+ rt_kprintf("Size of csw command error\n");
+ rt_usbd_ep_set_stall(func->device, data->ep_in);
}
else
{
- status = STATUS_CSW;
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("return to cbw status\n"));
+ data->ep_out->request.buffer = data->ep_out->buffer;
+ data->ep_out->request.size = SIZEOF_CBW;
+ data->ep_out->request.req_type = UIO_REQUEST_READ_FULL;
+ rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
+ data->status = STAT_CBW;
}
- }
+ break;
+ case STAT_CMD:
+ if(data->csw_response.data_reside == 0xFF)
+ {
+ data->csw_response.data_reside = 0;
+ }
+ else
+ {
+ data->csw_response.data_reside -= data->ep_in->request.size;
+ if(data->csw_response.data_reside != 0)
+ {
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("data_reside %d, request %d\n",
+ data->csw_response.data_reside, data->ep_in->request.size));
+ if(data->processing->dir == DIR_OUT)
+ {
+ rt_usbd_ep_set_stall(func->device, data->ep_out);
+ }
+ else
+ {
+ rt_usbd_ep_set_stall(func->device, data->ep_in);
+ }
+ data->csw_response.data_reside = 0;
+ }
+ }
+ _send_status(func);
+ break;
+ case STAT_SEND:
+ data->csw_response.data_reside -= data->ep_in->request.size;
+ data->count--;
+ data->block++;
+ if(data->count > 0 && data->csw_response.data_reside > 0)
+ {
+ if(rt_device_read(data->disk, data->block, data->ep_in->buffer, 1) == 0)
+ {
+ rt_kprintf("disk read error\n");
+ rt_usbd_ep_set_stall(func->device, data->ep_in);
+ return -RT_ERROR;
+ }
- return RT_EOK;
+ data->ep_in->request.buffer = data->ep_in->buffer;
+ data->ep_in->request.size = data->geometry.bytes_per_sector;
+ data->ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
+ }
+ else
+ {
+ _send_status(func);
+ }
+ break;
+ }
+
+ return RT_EOK;
}
#ifdef MASS_CBW_DUMP
@@ -376,134 +644,283 @@ static void cbw_dump(struct ustorage_cbw* cbw)
}
#endif
-/**
- * This function will handle mass storage bulk out endpoint request.
- *
- * @param device the usb device object.
- * @param size request size.
- *
- * @return RT_EOK.
- */
-static rt_err_t _ep_out_handler(udevice_t device, uclass_t cls, rt_size_t size)
+static struct scsi_cmd* _find_cbw_command(rt_uint16_t cmd)
{
- mass_eps_t eps;
- RT_ASSERT(device != RT_NULL);
+ int i;
- eps = (mass_eps_t)cls->eps;
- if(status == STATUS_CBW)
+ for(i=0; i<sizeof(cmd_data)/sizeof(struct scsi_cmd); i++)
{
- struct ustorage_cbw* cbw;
+ if(cmd_data[i].cmd == cmd)
+ return &cmd_data[i];
+ }
- /* dump cbw information */
- cbw = (struct ustorage_cbw*)eps->ep_out->buffer;
+ return RT_NULL;
+}
- if(cbw->signature == CBW_SIGNATURE)
- {
- csw.signature = CSW_SIGNATURE;
- csw.tag = cbw->tag;
- csw.data_reside = 0;
- csw.status = 0;
- }
- else
- return -RT_ERROR;
+static void _cb_len_calc(ufunction_t func, struct scsi_cmd* cmd,
+ ustorage_cbw_t cbw)
+{
+ struct mstorage *data;
- switch(cbw->cb[0])
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(cmd != RT_NULL);
+ RT_ASSERT(cbw != RT_NULL);
+
+ data = (struct mstorage*)func->user_data;
+ if(cmd->cmd_len == 6)
+ {
+ switch(cmd->type)
{
- case SCSI_TEST_UNIT_READY:
- csw.status = _removed;
- _send_status(device, eps, &csw);
- break;
- case SCSI_REQUEST_SENSE:
- _request_sense(device, eps->ep_in);
- status = STATUS_CSW;
+ case COUNT:
+ data->cb_data_size = cbw->cb[4];
break;
- case SCSI_INQUIRY_CMD:
- _inquiry_cmd(device, eps->ep_in);
- status = STATUS_CSW;
+ case BLOCK_COUNT:
+ data->cb_data_size = cbw->cb[4] * data->geometry.bytes_per_sector;
break;
- case SCSI_MODE_SENSE_6:
- _mode_sense_6(device, eps->ep_in);
- status = STATUS_CSW;
+ case FIXED:
+ data->cb_data_size = cmd->data_size;
break;
- case SCSI_ALLOW_MEDIUM_REMOVAL:
- _send_status(device, eps, &csw);
+ default:
break;
- case SCSI_READ_CAPACITIES:
- _read_capacities(device, eps->ep_in);
- status = STATUS_CSW;
- break;
- case SCSI_READ_CAPACITY:
- _read_capacity(device, eps->ep_in);
- status = STATUS_CSW;
- break;
- case SCSI_READ_10:
- _read_10(device, cbw, eps->ep_in);
+ }
+ }
+ else if(cmd->cmd_len == 10)
+ {
+ switch(cmd->type)
+ {
+ case COUNT:
+ data->cb_data_size = cbw->cb[7]<<8 | cbw->cb[8];
break;
- case SCSI_WRITE_10:
- _write_10(device, cbw, eps->ep_out);
- status = STATUS_RECEIVE;
+ case BLOCK_COUNT:
+ data->cb_data_size = (cbw->cb[7]<<8 | cbw->cb[8]) *
+ data->geometry.bytes_per_sector;
break;
- case SCSI_VERIFY_10:
- _verify_10(device);
+ case FIXED:
+ data->cb_data_size = cmd->data_size;
break;
- case SCSI_START_STOP:
- _start_stop(cbw);
- _send_status(device, eps, &csw);
+ default:
break;
}
}
- else if(status == STATUS_RECEIVE)
+ else
{
- RT_DEBUG_LOG(RT_DEBUG_USB, ("write size 0x%x block 0x%x oount 0x%x\n",
- size, _block, _size));
+ rt_kprintf("cmd_len error %d\n", cmd->cmd_len);
+ }
+}
- _size -= size;
- csw.data_reside -= size;
+static rt_bool_t _cbw_verify(ufunction_t func, struct scsi_cmd* cmd,
+ ustorage_cbw_t cbw)
+{
+ struct mstorage *data;
+
+ RT_ASSERT(cmd != RT_NULL);
+ RT_ASSERT(cbw != RT_NULL);
+ RT_ASSERT(func != RT_NULL);
- rt_device_write(disk, _block, eps->ep_in->buffer, 1);
- _block ++;
- if(_size == 0)
+ data = (struct mstorage*)func->user_data;
+ if(cmd->cmd_len != cbw->cb_len)
+ {
+ rt_kprintf("cb_len error\n");
+ cmd->cmd_len = cbw->cb_len;
+ }
+
+ if(cbw->xfer_len > 0 && data->cb_data_size == 0)
+ {
+ rt_kprintf("xfer_len > 0 && data_size == 0\n");
+ return RT_FALSE;
+ }
+
+ if(cbw->xfer_len == 0 && data->cb_data_size > 0)
+ {
+ rt_kprintf("xfer_len == 0 && data_size > 0");
+ return RT_FALSE;
+ }
+
+ if((cbw->dflags & USB_DIR_IN) && cmd->dir == DIR_OUT ||
+ !(cbw->dflags & USB_DIR_IN) && cmd->dir == DIR_IN)
+ {
+ rt_kprintf("dir error\n");
+ return RT_FALSE;
+ }
+
+ if(cbw->xfer_len > data->cb_data_size)
+ {
+ rt_kprintf("xfer_len > data_size\n");
+ return RT_FALSE;
+ }
+
+ if(cbw->xfer_len < data->cb_data_size)
+ {
+ rt_kprintf("xfer_len < data_size\n");
+ data->cb_data_size = cbw->xfer_len;
+ data->csw_response.status = 1;
+ }
+
+ return RT_TRUE;
+}
+
+static rt_size_t _cbw_handler(ufunction_t func, struct scsi_cmd* cmd,
+ ustorage_cbw_t cbw)
+{
+ struct mstorage *data;
+
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(cbw != RT_NULL);
+ RT_ASSERT(cmd->handler != RT_NULL);
+
+ data = (struct mstorage*)func->user_data;
+ data->processing = cmd;
+ return cmd->handler(func, cbw);
+}
+
+/**
+ * This function will handle mass storage bulk out endpoint request.
+ *
+ * @param func the usb function object.
+ * @param size request size.
+ *
+ * @return RT_EOK.
+ */
+static rt_err_t _ep_out_handler(ufunction_t func, rt_size_t size)
+{
+ struct mstorage *data;
+ struct scsi_cmd* cmd;
+ rt_size_t len;
+ struct ustorage_cbw* cbw;
+
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_out_handler %d\n", size));
+
+ data = (struct mstorage*)func->user_data;
+ cbw = (struct ustorage_cbw*)data->ep_out->buffer;
+ if(data->status == STAT_CBW)
+ {
+ /* dump cbw information */
+ if(cbw->signature != CBW_SIGNATURE || size != SIZEOF_CBW)
+ {
+ goto exit;
+ }
+
+ data->csw_response.signature = CSW_SIGNATURE;
+ data->csw_response.tag = cbw->tag;
+ data->csw_response.data_reside = cbw->xfer_len;
+ data->csw_response.status = 0;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("ep_out reside %d\n", data->csw_response.data_reside));
+
+ cmd = _find_cbw_command(cbw->cb[0]);
+ if(cmd == RT_NULL)
{
- _send_status(device, eps, &csw);
+ rt_kprintf("can't find cbw command\n");
+ goto exit;
+ }
+
+ _cb_len_calc(func, cmd, cbw);
+ if(!_cbw_verify(func, cmd, cbw))
+ {
+ goto exit;
+ }
+
+ len = _cbw_handler(func, cmd, cbw);
+ if(len == 0)
+ {
+ _send_status(func);
+ }
+
+ return RT_EOK;
+ }
+ else if(data->status == STAT_RECEIVE)
+ {
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("\nwrite size %d block 0x%x oount 0x%x\n",
+ size, data->block, data->size));
+
+ data->size -= size;
+ data->csw_response.data_reside -= size;
+
+ rt_device_write(data->disk, data->block, data->ep_out->buffer, 1);
+
+ if(data->csw_response.data_reside != 0)
+ {
+ data->ep_out->request.buffer = data->ep_out->buffer;
+ data->ep_out->request.size = data->geometry.bytes_per_sector;
+ data->ep_out->request.req_type = UIO_REQUEST_READ_FULL;
+ rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
+ data->block ++;
}
else
{
- dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer,
- geometry.bytes_per_sector);
+ _send_status(func);
}
+
+ return RT_EOK;
}
- else
+
+exit:
+ if(data->csw_response.data_reside)
{
- rt_kprintf("none cbw status\n");
+ if(cbw->dflags & USB_DIR_IN)
+ {
+ rt_usbd_ep_set_stall(func->device, data->ep_in);
+ }
+ else
+ {
+ rt_usbd_ep_set_stall(func->device, data->ep_in);
+ rt_usbd_ep_set_stall(func->device, data->ep_out);
+ }
}
-
- return RT_EOK;
+ data->csw_response.status = 1;
+ _send_status(func);
+
+ return -RT_ERROR;
}
-
/**
* This function will handle mass storage interface request.
*
- * @param device the usb device object.
+ * @param func the usb function object.
* @param setup the setup request.
*
* @return RT_EOK on successful.
*/
-static rt_err_t _interface_handler(udevice_t device, uclass_t cls, ureq_t setup)
+static rt_err_t _interface_handler(ufunction_t func, ureq_t setup)
{
rt_uint8_t lun = 0;
-
- RT_ASSERT(device != RT_NULL);
+
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
RT_ASSERT(setup != RT_NULL);
- RT_DEBUG_LOG(RT_DEBUG_USB, ("_interface_handler\n"));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("mstorage_interface_handler\n"));
switch(setup->request)
{
- case USBREQ_GET_MAX_LUN:
- dcd_ep_write(device->dcd, 0, &lun, 1);
+ case USBREQ_GET_MAX_LUN:
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("USBREQ_GET_MAX_LUN\n"));
+
+ if(setup->value || setup->length != 1)
+ {
+ rt_usbd_ep0_set_stall(func->device);
+ }
+ else
+ {
+ rt_usbd_ep0_write(func->device, &lun, 1);
+ }
break;
case USBREQ_MASS_STORAGE_RESET:
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("USBREQ_MASS_STORAGE_RESET\n"));
+
+ if(setup->value || setup->length != 0)
+ {
+ rt_usbd_ep0_set_stall(func->device);
+ }
+ else
+ {
+ rt_usbd_ep0_write(func->device, RT_NULL, 0);
+ }
break;
default:
rt_kprintf("unknown interface request\n");
@@ -514,81 +931,114 @@ static rt_err_t _interface_handler(udevice_t device, uclass_t cls, ureq_t setup)
}
/**
- * This function will run mass storage class, it will be called on handle set configuration request.
+ * This function will run mass storage function, it will be called on handle set configuration request.
*
- * @param device the usb device object.
+ * @param func the usb function object.
*
* @return RT_EOK on successful.
*/
-static rt_err_t _class_run(udevice_t device, uclass_t cls)
+static rt_err_t _function_enable(ufunction_t func)
{
- mass_eps_t eps;
- rt_uint8_t *buffer;
- RT_ASSERT(device != RT_NULL);
+ struct mstorage *data;
+ RT_ASSERT(func != RT_NULL);
- RT_DEBUG_LOG(RT_DEBUG_USB, ("mass storage run\n"));
- eps = (mass_eps_t)cls->eps;
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("Mass storage function enabled\n"));
+ data = (struct mstorage*)func->user_data;
- disk = rt_device_find(RT_USB_MSTORAGE_DISK_NAME);
- if(disk == RT_NULL)
+ data->disk = rt_device_find(RT_USB_MSTORAGE_DISK_NAME);
+ if(data->disk == RT_NULL)
{
- rt_kprintf("no disk named %s\n", RT_USB_MSTORAGE_DISK_NAME);
+ rt_kprintf("no data->disk named %s\n", RT_USB_MSTORAGE_DISK_NAME);
return -RT_ERROR;
}
- if(rt_device_control(disk, RT_DEVICE_CTRL_BLK_GETGEOME, (void*)&geometry) != RT_EOK)
- return -RT_ERROR;
- buffer = (rt_uint8_t*)rt_malloc(geometry.bytes_per_sector);
- if(buffer == RT_NULL)
+ if(rt_device_open(data->disk, RT_DEVICE_OFLAG_RDWR) != RT_EOK)
+ {
+ rt_kprintf("disk open error\n");
+ return -RT_ERROR;
+ }
+
+ if(rt_device_control(data->disk, RT_DEVICE_CTRL_BLK_GETGEOME,
+ (void*)&data->geometry) != RT_EOK)
+ {
+ rt_kprintf("get disk info error\n");
+ return -RT_ERROR;
+ }
+
+ data->ep_in->buffer = (rt_uint8_t*)rt_malloc(data->geometry.bytes_per_sector);
+ if(data->ep_in->buffer == RT_NULL)
+ {
+ rt_kprintf("no memory\n");
return -RT_ENOMEM;
- eps->ep_out->buffer = buffer;
- eps->ep_in->buffer = buffer;
-
- dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer, SIZEOF_CBW);
-
+ }
+ data->ep_out->buffer = (rt_uint8_t*)rt_malloc(data->geometry.bytes_per_sector);
+ if(data->ep_out->buffer == RT_NULL)
+ {
+ rt_free(data->ep_in->buffer);
+ rt_kprintf("no memory\n");
+ return -RT_ENOMEM;
+ }
+
+ /* prepare to read CBW request */
+ data->ep_out->request.buffer = data->ep_out->buffer;
+ data->ep_out->request.size = SIZEOF_CBW;
+ data->ep_out->request.req_type = UIO_REQUEST_READ_FULL;
+ rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
+
return RT_EOK;
}
/**
- * This function will stop mass storage class, it will be called on handle set configuration request.
+ * This function will stop mass storage function, it will be called on handle set configuration request.
*
* @param device the usb device object.
*
* @return RT_EOK on successful.
*/
-static rt_err_t _class_stop(udevice_t device, uclass_t cls)
+static rt_err_t _function_disable(ufunction_t func)
{
- mass_eps_t eps;
- RT_ASSERT(device != RT_NULL);
+ struct mstorage *data;
+ RT_ASSERT(func != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("Mass storage function disabled\n"));
- RT_DEBUG_LOG(RT_DEBUG_USB, ("mass storage stop\n"));
- eps = (mass_eps_t)cls->eps;
- rt_free(eps->ep_in->buffer);
- eps->ep_out->buffer = RT_NULL;
- eps->ep_in->buffer = RT_NULL;
+ data = (struct mstorage*)func->user_data;
+ if(data->ep_in->buffer != RT_NULL)
+ {
+ rt_free(data->ep_in->buffer);
+ data->ep_in->buffer = RT_NULL;
+ }
+
+ if(data->ep_out->buffer != RT_NULL)
+ {
+ rt_free(data->ep_out->buffer);
+ data->ep_out->buffer = RT_NULL;
+ }
+ data->status = STAT_CBW;
+
return RT_EOK;
}
-static struct uclass_ops ops =
+static struct ufunction_ops ops =
{
- _class_run,
- _class_stop,
+ _function_enable,
+ _function_disable,
RT_NULL,
};
/**
- * This function will create a mass storage class instance.
+ * This function will create a mass storage function instance.
*
* @param device the usb device object.
*
* @return RT_EOK on successful.
*/
-uclass_t rt_usbd_class_mstorage_create(udevice_t device)
+ufunction_t rt_usbd_function_mstorage_create(udevice_t device)
{
uintf_t intf;
- mass_eps_t eps;
- uclass_t mstorage;
+ struct mstorage *data;
+ ufunction_t func;
ualtsetting_t setting;
umass_desc_t mass_desc;
@@ -597,37 +1047,42 @@ uclass_t rt_usbd_class_mstorage_create(udevice_t device)
/* set usb device string description */
rt_usbd_device_set_string(device, _ustring);
- /* create a mass storage class */
- mstorage = rt_usbd_class_create(device, &dev_desc, &ops);
- /* create a mass storage endpoints collection */
- eps = (mass_eps_t)rt_malloc(sizeof(struct mass_eps));
- mstorage->eps = (void*)eps;
+
+ /* create a mass storage function */
+ func = rt_usbd_function_new(device, &dev_desc, &ops);
+ device->dev_qualifier = &dev_qualifier;
+
+ /* allocate memory for mass storage function data */
+ data = (struct mstorage*)rt_malloc(sizeof(struct mstorage));
+ rt_memset(data, 0, sizeof(struct mstorage));
+ func->user_data = (void*)data;
- /* create an interface */
- intf = rt_usbd_interface_create(device, _interface_handler);
+ /* create an interface object */
+ intf = rt_usbd_interface_new(device, _interface_handler);
- /* create an alternate setting */
- setting = rt_usbd_altsetting_create(sizeof(struct umass_descriptor));
+ /* create an alternate setting object */
+ setting = rt_usbd_altsetting_new(sizeof(struct umass_descriptor));
+
/* config desc in alternate setting */
rt_usbd_altsetting_config_descriptor(setting, &_mass_desc, 0);
/* create a bulk out and a bulk in endpoint */
mass_desc = (umass_desc_t)setting->desc;
- eps->ep_in = rt_usbd_endpoint_create(&mass_desc->ep_in_desc, _ep_in_handler);
- eps->ep_out = rt_usbd_endpoint_create(&mass_desc->ep_out_desc, _ep_out_handler);
+ data->ep_in = rt_usbd_endpoint_new(&mass_desc->ep_in_desc, _ep_in_handler);
+ data->ep_out = rt_usbd_endpoint_new(&mass_desc->ep_out_desc, _ep_out_handler);
/* add the bulk out and bulk in endpoint to the alternate setting */
- rt_usbd_altsetting_add_endpoint(setting, eps->ep_out);
- rt_usbd_altsetting_add_endpoint(setting, eps->ep_in);
+ rt_usbd_altsetting_add_endpoint(setting, data->ep_out);
+ rt_usbd_altsetting_add_endpoint(setting, data->ep_in);
/* add the alternate setting to the interface, then set default setting */
rt_usbd_interface_add_altsetting(intf, setting);
rt_usbd_set_altsetting(intf, 0);
- /* add the interface to the mass storage class */
- rt_usbd_class_add_interface(mstorage, intf);
+ /* add the interface to the mass storage function */
+ rt_usbd_function_add_interface(func, intf);
- return mstorage;
+ return func;
}
#endif
diff --git a/components/drivers/usb/usbdevice/class/mstorage.h b/components/drivers/usb/usbdevice/class/mstorage.h
index 4d53222a00..0f448a07d5 100644
--- a/components/drivers/usb/usbdevice/class/mstorage.h
+++ b/components/drivers/usb/usbdevice/class/mstorage.h
@@ -59,13 +59,6 @@ struct request_sense_data
rt_uint8_t Reserved4[4];
}request_sense_data_t;
-struct mass_eps
-{
- uep_t ep_in;
- uep_t ep_out;
-};
-typedef struct mass_eps* mass_eps_t;
-
#pragma pack()
#endif
diff --git a/components/drivers/usb/usbdevice/core/core.c b/components/drivers/usb/usbdevice/core/core.c
index f29ee26c2e..14deb316aa 100644
--- a/components/drivers/usb/usbdevice/core/core.c
+++ b/components/drivers/usb/usbdevice/core/core.c
@@ -20,8 +20,10 @@
* Change Logs:
* Date Author Notes
* 2012-10-01 Yi Qiu first version
- * 2012-12-12 heyuanjie87 change endpoint and class handler
+ * 2012-12-12 heyuanjie87 change endpoint and function handler
* 2012-12-30 heyuanjie87 change inferface handler
+ * 2013-04-26 aozima add DEVICEQUALIFIER support.
+ * 2013-07-25 Yi Qiu update for USB CV test
*/
#include <rtthread.h>
@@ -29,6 +31,11 @@
static rt_list_t device_list;
+static rt_size_t rt_usbd_ep_write(udevice_t device, uep_t ep, void *buffer, rt_size_t size);
+static rt_size_t rt_usbd_ep_read_prepare(udevice_t device, uep_t ep, void *buffer, rt_size_t size);
+static rt_err_t rt_usbd_ep_assign(udevice_t device, uep_t ep);
+static rt_err_t rt_usbd_ep_unassign(udevice_t device, uep_t ep);
+
/**
* This function will handle get_device_descriptor request.
*
@@ -37,7 +44,7 @@ static rt_list_t device_list;
*
* @return RT_EOK on successful.
*/
-static rt_err_t _get_device_descriptor(struct udevice *device, ureq_t setup)
+static rt_err_t _get_device_descriptor(struct udevice* device, ureq_t setup)
{
rt_size_t size;
@@ -52,7 +59,8 @@ static rt_err_t _get_device_descriptor(struct udevice *device, ureq_t setup)
USB_DESC_LENGTH_DEVICE : setup->length;
/* send device descriptor to endpoint 0 */
- dcd_ep_write(device->dcd, 0, (rt_uint8_t *)&device->dev_desc, size);
+ rt_usbd_ep0_write(device, (rt_uint8_t*)&device->dev_desc,
+ size);
return RT_EOK;
}
@@ -65,7 +73,7 @@ static rt_err_t _get_device_descriptor(struct udevice *device, ureq_t setup)
*
* @return RT_EOK on successful.
*/
-static rt_err_t _get_config_descriptor(struct udevice *device, ureq_t setup)
+static rt_err_t _get_config_descriptor(struct udevice* device, ureq_t setup)
{
rt_size_t size;
ucfg_desc_t cfg_desc;
@@ -81,7 +89,7 @@ static rt_err_t _get_config_descriptor(struct udevice *device, ureq_t setup)
cfg_desc->wTotalLength : setup->length;
/* send configuration descriptor to endpoint 0 */
- dcd_ep_write(device->dcd, 0, (rt_uint8_t *)cfg_desc, size);
+ rt_usbd_ep0_write(device, (rt_uint8_t*)cfg_desc, size);
return RT_EOK;
}
@@ -94,7 +102,7 @@ static rt_err_t _get_config_descriptor(struct udevice *device, ureq_t setup)
*
* @return RT_EOK on successful, -RT_ERROR on invalid request.
*/
-static rt_err_t _get_string_descriptor(struct udevice *device, ureq_t setup)
+static rt_err_t _get_string_descriptor(struct udevice* device, ureq_t setup)
{
struct ustring_descriptor str_desc;
rt_uint8_t index, i;
@@ -109,14 +117,13 @@ static rt_err_t _get_string_descriptor(struct udevice *device, ureq_t setup)
str_desc.type = USB_DESC_TYPE_STRING;
index = setup->value & 0xFF;
- if (index > USB_STRING_INTERFACE_INDEX)
+ if(index > USB_STRING_INTERFACE_INDEX)
{
rt_kprintf("unknown string index\n");
- dcd_ep_stall(device->dcd, 0);
-
+ rt_usbd_ep0_set_stall(device);
return -RT_ERROR;
}
- if (index == 0)
+ if(index == 0)
{
str_desc.bLength = 4;
str_desc.String[0] = 0x09;
@@ -127,7 +134,7 @@ static rt_err_t _get_string_descriptor(struct udevice *device, ureq_t setup)
len = rt_strlen(device->str[index]);
str_desc.bLength = len*2 + 2;
- for (i=0; i<len; i++)
+ for(i=0; i<len; i++)
{
str_desc.String[i*2] = device->str[index][i];
str_desc.String[i*2 + 1] = 0;
@@ -140,7 +147,29 @@ static rt_err_t _get_string_descriptor(struct udevice *device, ureq_t setup)
len = setup->length;
/* send string descriptor to endpoint 0 */
- dcd_ep_write(device->dcd, 0, (rt_uint8_t *)&str_desc, len);
+ rt_usbd_ep0_write(device, (rt_uint8_t*)&str_desc, len);
+
+ return RT_EOK;
+}
+
+static rt_err_t _get_qualifier_descriptor(struct udevice* device, ureq_t setup)
+{
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_qualifier_descriptor\n"));
+
+ /* parameter check */
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(setup != RT_NULL);
+
+ if(device->dev_qualifier)
+ {
+ /* send device qualifier descriptor to endpoint 0 */
+ rt_usbd_ep0_write(device, (rt_uint8_t*)device->dev_qualifier,
+ sizeof(struct usb_qualifier_descriptor));
+ }
+ else
+ {
+ rt_usbd_ep0_set_stall(device);
+ }
return RT_EOK;
}
@@ -153,15 +182,15 @@ static rt_err_t _get_string_descriptor(struct udevice *device, ureq_t setup)
*
* @return RT_EOK on successful.
*/
-static rt_err_t _get_descriptor(struct udevice *device, ureq_t setup)
+static rt_err_t _get_descriptor(struct udevice* device, ureq_t setup)
{
/* parameter check */
RT_ASSERT(device != RT_NULL);
RT_ASSERT(setup != RT_NULL);
- if (setup->request_type == USB_REQ_TYPE_DIR_IN)
+ if(setup->request_type == USB_REQ_TYPE_DIR_IN)
{
- switch (setup->value >> 8)
+ switch(setup->value >> 8)
{
case USB_DESC_TYPE_DEVICE:
_get_device_descriptor(device, setup);
@@ -173,18 +202,18 @@ static rt_err_t _get_descriptor(struct udevice *device, ureq_t setup)
_get_string_descriptor(device, setup);
break;
case USB_DESC_TYPE_DEVICEQUALIFIER:
- dcd_ep_stall(device->dcd, 0);
+ _get_qualifier_descriptor(device, setup);
break;
default:
rt_kprintf("unsupported descriptor request\n");
- dcd_ep_stall(device->dcd, 0);
+ rt_usbd_ep0_set_stall(device);
break;
}
}
else
{
rt_kprintf("request direction error\n");
- dcd_ep_stall(device->dcd, 0);
+ rt_usbd_ep0_set_stall(device);
}
return RT_EOK;
@@ -198,7 +227,7 @@ static rt_err_t _get_descriptor(struct udevice *device, ureq_t setup)
*
* @return RT_EOK on successful.
*/
-static rt_err_t _get_interface(struct udevice *device, ureq_t setup)
+static rt_err_t _get_interface(struct udevice* device, ureq_t setup)
{
rt_uint8_t value;
uintf_t intf;
@@ -211,8 +240,7 @@ static rt_err_t _get_interface(struct udevice *device, ureq_t setup)
if (device->state != USB_STATE_CONFIGURED)
{
- dcd_ep_stall(device->dcd, 0);
-
+ rt_usbd_ep0_set_stall(device);
return -RT_ERROR;
}
@@ -221,7 +249,7 @@ static rt_err_t _get_interface(struct udevice *device, ureq_t setup)
value = intf->curr_setting->intf_desc->bAlternateSetting;
/* send the interface alternate setting to endpoint 0*/
- dcd_ep_write(device->dcd, 0, &value, 1);
+ rt_usbd_ep0_write(device, &value, 1);
return RT_EOK;
}
@@ -234,11 +262,11 @@ static rt_err_t _get_interface(struct udevice *device, ureq_t setup)
*
* @return RT_EOK on successful.
*/
-static rt_err_t _set_interface(struct udevice *device, ureq_t setup)
+static rt_err_t _set_interface(struct udevice* device, ureq_t setup)
{
uintf_t intf;
uep_t ep;
- struct rt_list_node *i;
+ struct rt_list_node* i;
ualtsetting_t setting;
/* parameter check */
@@ -249,11 +277,10 @@ static rt_err_t _set_interface(struct udevice *device, ureq_t setup)
if (device->state != USB_STATE_CONFIGURED)
{
- dcd_ep_stall(device->dcd, 0);
-
+ rt_usbd_ep0_set_stall(device);
return -RT_ERROR;
}
-
+
/* find the specified interface */
intf = rt_usbd_find_interface(device, setup->index & 0xFF, RT_NULL);
@@ -262,13 +289,13 @@ static rt_err_t _set_interface(struct udevice *device, ureq_t setup)
setting = intf->curr_setting;
/* start all endpoints of the interface alternate setting */
- for (i=setting->ep_list.next; i != &setting->ep_list; i=i->next)
+ for(i=setting->ep_list.next; i != &setting->ep_list; i=i->next)
{
ep = (uep_t)rt_list_entry(i, struct uendpoint, list);
- dcd_ep_stop(device->dcd, ep);
- dcd_ep_run(device->dcd, ep);
+ dcd_ep_disable(device->dcd, ep);
+ dcd_ep_enable(device->dcd, ep);
}
- dcd_send_status(device->dcd);
+ dcd_ep0_send_status(device->dcd);
return RT_EOK;
}
@@ -281,7 +308,7 @@ static rt_err_t _set_interface(struct udevice *device, ureq_t setup)
*
* @return RT_EOK on successful.
*/
-static rt_err_t _get_config(struct udevice *device, ureq_t setup)
+static rt_err_t _get_config(struct udevice* device, ureq_t setup)
{
rt_uint8_t value;
@@ -291,7 +318,7 @@ static rt_err_t _get_config(struct udevice *device, ureq_t setup)
RT_ASSERT(device->curr_cfg != RT_NULL);
RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_config\n"));
-
+
if (device->state == USB_STATE_CONFIGURED)
{
/* get current configuration */
@@ -302,7 +329,7 @@ static rt_err_t _get_config(struct udevice *device, ureq_t setup)
value = 0;
}
/* write the current configuration to endpoint 0 */
- dcd_ep_write(device->dcd, 0, &value, 1);
+ rt_usbd_ep0_write(device, &value, 1);
return RT_EOK;
}
@@ -315,7 +342,7 @@ static rt_err_t _get_config(struct udevice *device, ureq_t setup)
*
* @return RT_EOK on successful.
*/
-static rt_err_t _set_config(struct udevice *device, ureq_t setup)
+static rt_err_t _set_config(struct udevice* device, ureq_t setup)
{
struct rt_list_node *i, *j, *k;
uconfig_t cfg;
@@ -331,8 +358,7 @@ static rt_err_t _set_config(struct udevice *device, ureq_t setup)
if (setup->value > device->dev_desc.bNumConfigurations)
{
- dcd_ep_stall(device->dcd, 0);
-
+ rt_usbd_ep0_set_stall(device);
return -RT_ERROR;
}
@@ -348,33 +374,32 @@ static rt_err_t _set_config(struct udevice *device, ureq_t setup)
rt_usbd_set_config(device, setup->value);
cfg = device->curr_cfg;
- for (i=cfg->cls_list.next; i!=&cfg->cls_list; i=i->next)
+ for (i=cfg->func_list.next; i!=&cfg->func_list; i=i->next)
{
- /* run all classes and their endpoints in the configuration */
- uclass_t cls = (uclass_t)rt_list_entry(i, struct uclass, list);
- for (j=cls->intf_list.next; j!=&cls->intf_list; j=j->next)
+ /* run all functiones and their endpoints in the configuration */
+ ufunction_t func = (ufunction_t)rt_list_entry(i, struct ufunction, list);
+ for(j=func->intf_list.next; j!=&func->intf_list; j=j->next)
{
intf = (uintf_t)rt_list_entry(j, struct uinterface, list);
setting = intf->curr_setting;
- for (k=setting->ep_list.next; k != &setting->ep_list; k=k->next)
+ for(k=setting->ep_list.next; k != &setting->ep_list; k=k->next)
{
ep = (uep_t)rt_list_entry(k, struct uendpoint, list);
- /* first stop then start endpoint */
- dcd_ep_stop(device->dcd, ep);
- dcd_ep_run(device->dcd, ep);
+ /* first disable then enable an endpoint */
+ dcd_ep_disable(device->dcd, ep);
+ dcd_ep_enable(device->dcd, ep);
}
}
- /* after running all endpoints, then run class */
- if (cls->ops->run != RT_NULL)
- cls->ops->run(device, cls);
+ /* after enabled endpoints, then enable function */
+ FUNC_ENABLE(func);
}
device->state = USB_STATE_CONFIGURED;
_exit:
/* issue status stage */
- dcd_send_status(device->dcd);
+ dcd_ep0_send_status(device->dcd);
return RT_EOK;
}
@@ -387,38 +412,38 @@ _exit:
*
* @return RT_EOK on successful.
*/
-static rt_err_t _set_address(struct udevice *device, ureq_t setup)
+static rt_err_t _set_address(struct udevice* device, ureq_t setup)
{
/* parameter check */
RT_ASSERT(device != RT_NULL);
RT_ASSERT(setup != RT_NULL);
- RT_DEBUG_LOG(RT_DEBUG_USB, ("_set_address\n"));
+ /* issue status stage */
+ dcd_ep0_send_status(device->dcd);
/* set address in device control driver */
dcd_set_address(device->dcd, setup->value);
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_set_address\n"));
+
device->state = USB_STATE_ADDRESS;
- /* issue status stage */
- dcd_send_status(device->dcd);
-
return RT_EOK;
}
/**
- * This function will handle standard request to
- * interface that defined in class-specifics
+ * This function will handle standard request to
+ * interface that defined in function-specifics
*
* @param device the usb device object.
* @param setup the setup request.
*
- * @return RT_EOK on successful.
+ * @return RT_EOK on successful.
*/
-static rt_err_t _request_interface(struct udevice *device, ureq_t setup)
+static rt_err_t _request_interface(struct udevice* device, ureq_t setup)
{
uintf_t intf;
- uclass_t cls;
+ ufunction_t func;
rt_err_t ret;
/* parameter check */
@@ -427,16 +452,16 @@ static rt_err_t _request_interface(struct udevice *device, ureq_t setup)
RT_DEBUG_LOG(RT_DEBUG_USB, ("_request_interface\n"));
- intf = rt_usbd_find_interface(device, setup->index & 0xFF, &cls);
+ intf = rt_usbd_find_interface(device, setup->index & 0xFF, &func);
if (intf != RT_NULL)
{
- ret = intf->handler(device, cls, setup);
+ ret = intf->handler(func, setup);
}
else
{
ret = -RT_ERROR;
}
-
+
return ret;
}
@@ -448,7 +473,7 @@ static rt_err_t _request_interface(struct udevice *device, ureq_t setup)
*
* @return RT_EOK on successful.
*/
-static rt_err_t _standard_request(struct udevice *device, ureq_t setup)
+static rt_err_t _standard_request(struct udevice* device, ureq_t setup)
{
udcd_t dcd;
rt_uint16_t value = 0;
@@ -459,20 +484,20 @@ static rt_err_t _standard_request(struct udevice *device, ureq_t setup)
dcd = device->dcd;
- switch (setup->request_type & USB_REQ_TYPE_RECIPIENT_MASK)
+ switch(setup->request_type & USB_REQ_TYPE_RECIPIENT_MASK)
{
case USB_REQ_TYPE_DEVICE:
- switch (setup->request)
+ switch(setup->request)
{
case USB_REQ_GET_STATUS:
- dcd_ep_write(device->dcd, 0, &value, 2);
+ rt_usbd_ep0_write(device, &value, 2);
break;
case USB_REQ_CLEAR_FEATURE:
- dcd_clear_feature(dcd, setup->value, setup->index);
- dcd_send_status(dcd);
+ rt_usbd_clear_feature(device, setup->value, setup->index);
+ dcd_ep0_send_status(dcd);
break;
case USB_REQ_SET_FEATURE:
- dcd_set_feature(dcd, setup->value, setup->index);
+ rt_usbd_set_feature(device, setup->value, setup->index);
break;
case USB_REQ_SET_ADDRESS:
_set_address(device, setup);
@@ -481,7 +506,7 @@ static rt_err_t _standard_request(struct udevice *device, ureq_t setup)
_get_descriptor(device, setup);
break;
case USB_REQ_SET_DESCRIPTOR:
- dcd_ep_stall(dcd, 0);
+ rt_usbd_ep0_set_stall(device);
break;
case USB_REQ_GET_CONFIGURATION:
_get_config(device, setup);
@@ -491,12 +516,12 @@ static rt_err_t _standard_request(struct udevice *device, ureq_t setup)
break;
default:
rt_kprintf("unknown device request\n");
- dcd_ep_stall(device->dcd, 0);
+ rt_usbd_ep0_set_stall(device);
break;
}
break;
case USB_REQ_TYPE_INTERFACE:
- switch (setup->request)
+ switch(setup->request)
{
case USB_REQ_GET_INTERFACE:
_get_interface(device, setup);
@@ -508,8 +533,7 @@ static rt_err_t _standard_request(struct udevice *device, ureq_t setup)
if (_request_interface(device, setup) != RT_EOK)
{
rt_kprintf("unknown interface request\n");
- dcd_ep_stall(device->dcd, 0);
-
+ rt_usbd_ep0_set_stall(device);
return - RT_ERROR;
}
else
@@ -517,53 +541,69 @@ static rt_err_t _standard_request(struct udevice *device, ureq_t setup)
}
break;
case USB_REQ_TYPE_ENDPOINT:
- switch (setup->request)
+ switch(setup->request)
{
case USB_REQ_GET_STATUS:
{
- /* TODO */
uep_t ep;
ep = rt_usbd_find_endpoint(device, RT_NULL, setup->index);
- value = ep->is_stall;
- dcd_ep_write(dcd, 0, &value, 2);
+ value = ep->stalled;
+ rt_usbd_ep0_write(device, &value, 2);
}
break;
case USB_REQ_CLEAR_FEATURE:
{
uep_t ep;
-
+ uio_request_t req;
+ struct rt_list_node *node;
+
ep = rt_usbd_find_endpoint(device, RT_NULL, setup->index);
- ep->is_stall = 0;
- dcd_clear_feature(dcd, setup->value, setup->index);
- dcd_send_status(dcd);
+ if(USB_EP_HALT == setup->value && ep->stalled == RT_TRUE)
+ {
+ rt_usbd_clear_feature(device, setup->value, setup->index);
+ dcd_ep0_send_status(dcd);
+ ep->stalled = RT_FALSE;
+
+ for (node = ep->request_list.next; node != &ep->request_list; node = node->next)
+ {
+ req = (uio_request_t)rt_list_entry(node, struct uio_request, list);
+ rt_usbd_io_request(device, ep, req);
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("fired a request\n"));
+ }
+
+ rt_list_init(&ep->request_list);
+ }
}
break;
case USB_REQ_SET_FEATURE:
{
uep_t ep;
-
- ep = rt_usbd_find_endpoint(device, RT_NULL, setup->index);
- ep->is_stall = 1;
- dcd_set_feature(dcd, setup->value, setup->index);
- dcd_send_status(dcd);
+
+ if(USB_EP_HALT == setup->value)
+ {
+ ep = rt_usbd_find_endpoint(device, RT_NULL, setup->index);
+ ep->stalled = RT_TRUE;
+ rt_usbd_set_feature(device, setup->value, setup->index);
+ dcd_ep0_send_status(dcd);
+ }
}
break;
case USB_REQ_SYNCH_FRAME:
break;
default:
rt_kprintf("unknown endpoint request\n");
- dcd_ep_stall(device->dcd, 0);
+ rt_usbd_ep0_set_stall(device);
break;
}
break;
case USB_REQ_TYPE_OTHER:
rt_kprintf("unknown other type request\n");
- dcd_ep_stall(device->dcd, 0);
+ rt_usbd_ep0_set_stall(device);
break;
default:
rt_kprintf("unknown type request\n");
- dcd_ep_stall(device->dcd, 0);
+ rt_usbd_ep0_set_stall(device);
break;
}
@@ -571,47 +611,68 @@ static rt_err_t _standard_request(struct udevice *device, ureq_t setup)
}
/**
- * This function will handle class request.
+ * This function will handle function request.
*
* @param device the usb device object.
* @param setup the setup request.
*
* @return RT_EOK on successful, -RT_ERROR on invalid request.
*/
-static rt_err_t _class_request(udevice_t device, ureq_t setup)
+static rt_err_t _function_request(udevice_t device, ureq_t setup)
{
uintf_t intf;
- uclass_t cls;
+ ufunction_t func;
/* parameter check */
RT_ASSERT(device != RT_NULL);
RT_ASSERT(setup != RT_NULL);
/* verify request value */
- if (setup->index > device->curr_cfg->cfg_desc.bNumInterfaces)
+ if(setup->index > device->curr_cfg->cfg_desc.bNumInterfaces)
{
- dcd_ep_stall(device->dcd, 0);
-
+ rt_usbd_ep0_set_stall(device);
return -RT_ERROR;
}
- switch (setup->request_type & USB_REQ_TYPE_RECIPIENT_MASK)
+ switch(setup->request_type & USB_REQ_TYPE_RECIPIENT_MASK)
{
case USB_REQ_TYPE_INTERFACE:
- intf = rt_usbd_find_interface(device, setup->index & 0xFF, &cls);
- intf->handler(device, cls, setup);
+ intf = rt_usbd_find_interface(device, setup->index & 0xFF, &func);
+ if(intf == RT_NULL)
+ {
+ rt_kprintf("unkwown interface request\n");
+ rt_usbd_ep0_set_stall(device);
+ }
+ else
+ {
+ intf->handler(func, setup);
+ }
break;
case USB_REQ_TYPE_ENDPOINT:
break;
default:
- rt_kprintf("unknown class request type\n");
- dcd_ep_stall(device->dcd, 0);
+ rt_kprintf("unknown function request type\n");
+ rt_usbd_ep0_set_stall(device);
break;
}
return RT_EOK;
}
+static rt_err_t _dump_setup_packet(ureq_t setup)
+{
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("[\n"));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("setup_request 0x%x\n",
+ setup->request_type));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("value 0x%x\n", setup->value));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("length 0x%x\n", setup->length));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("index 0x%x\n", setup->index));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("request 0x%x\n", setup->request));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("]\n"));
+
+ return RT_EOK;
+}
+
/**
* This function will handle setup request.
*
@@ -626,29 +687,22 @@ static rt_err_t _setup_request(udevice_t device, ureq_t setup)
RT_ASSERT(device != RT_NULL);
RT_ASSERT(setup != RT_NULL);
- RT_DEBUG_LOG(RT_DEBUG_USB, ("[\n"));
- RT_DEBUG_LOG(RT_DEBUG_USB, ("setup_request_handler 0x%x\n",
- setup->request_type));
- RT_DEBUG_LOG(RT_DEBUG_USB, ("value 0x%x\n", setup->value));
- RT_DEBUG_LOG(RT_DEBUG_USB, ("length 0x%x\n", setup->length));
- RT_DEBUG_LOG(RT_DEBUG_USB, ("index 0x%x\n", setup->index));
- RT_DEBUG_LOG(RT_DEBUG_USB, ("request 0x%x\n", setup->request));
- RT_DEBUG_LOG(RT_DEBUG_USB, ("]\n"));
+ _dump_setup_packet(setup);
- switch ((setup->request_type & USB_REQ_TYPE_MASK))
+ switch((setup->request_type & USB_REQ_TYPE_MASK))
{
case USB_REQ_TYPE_STANDARD:
_standard_request(device, setup);
break;
case USB_REQ_TYPE_CLASS:
- _class_request(device, setup);
+ _function_request(device, setup);
break;
case USB_REQ_TYPE_VENDOR:
rt_kprintf("vendor type request\n");
break;
default:
rt_kprintf("unknown setup request type\n");
- dcd_ep_stall(device->dcd, 0);
+ rt_usbd_ep0_set_stall(device);
return -RT_ERROR;
}
@@ -656,104 +710,207 @@ static rt_err_t _setup_request(udevice_t device, ureq_t setup)
}
/**
- * This function will notity sof event to all of class.
+ * This function will hanle data notify event.
*
- * @param device the usb device object.
+ * @param device the usb device object.
+ * @param ep_msg the endpoint message.
*
* @return RT_EOK.
*/
-rt_err_t _sof_notify(udevice_t device)
+static rt_err_t _data_notify(udevice_t device, struct ep_msg* ep_msg)
{
- struct rt_list_node *i;
- uclass_t cls;
+ uep_t ep;
+ ufunction_t func;
+ rt_size_t size = 0;
+
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(ep_msg != RT_NULL);
+
+ if (device->state != USB_STATE_CONFIGURED)
+ {
+ return -RT_ERROR;
+ }
+
+ ep = rt_usbd_find_endpoint(device, &func, ep_msg->ep_addr);
+ if(ep == RT_NULL)
+ {
+ rt_kprintf("invalid endpoint\n");
+ return -RT_ERROR;
+ }
+
+ if(EP_ADDRESS(ep) & USB_DIR_IN)
+ {
+ if(ep->request.remain_size >= EP_MAXPACKET(ep))
+ {
+ dcd_ep_write(device->dcd, EP_ADDRESS(ep),
+ ep->request.buffer, EP_MAXPACKET(ep));
+ ep->request.remain_size -= EP_MAXPACKET(ep);
+ ep->request.buffer += EP_MAXPACKET(ep);
+ }
+ else if(ep->request.remain_size > 0)
+ {
+ dcd_ep_write(device->dcd, EP_ADDRESS(ep),
+ ep->request.buffer, ep->request.remain_size);
+ ep->request.remain_size = 0;
+ }
+ else
+ {
+ EP_HANDLER(ep, func, size);
+ }
+ }
+ else
+ {
+ size = ep_msg->size;
+ if(ep->request.remain_size == 0)
+ {
+ return RT_EOK;
+ }
+
+ if(size == 0)
+ {
+ size = dcd_ep_read(device->dcd, EP_ADDRESS(ep),
+ ep->request.buffer);
+ }
+ ep->request.remain_size -= size;
+ ep->request.buffer += size;
+
+ if(ep->request.req_type == UIO_REQUEST_READ_BEST)
+ {
+ EP_HANDLER(ep, func, size);
+ }
+ else if(ep->request.remain_size == 0)
+ {
+ EP_HANDLER(ep, func, ep->request.size);
+ }
+ }
+ return RT_EOK;
+}
+
+static rt_err_t _ep0_out_notify(udevice_t device, struct ep_msg* ep_msg)
+{
+ uep_t ep0;
+ rt_size_t size;
+
RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(ep_msg != RT_NULL);
+ RT_ASSERT(device->dcd != 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)
+ ep0 = &device->dcd->ep0;
+ size = ep_msg->size;
+ if(ep0->request.remain_size == 0)
+ {
+ return RT_EOK;
+ }
+ if(size == 0)
+ {
+ size = dcd_ep_read(device->dcd, EP0_OUT_ADDR, ep0->request.buffer);
+ if(size == 0)
+ {
+ return RT_EOK;
+ }
+ }
+
+ ep0->request.remain_size -= size;
+ ep0->request.buffer += size;
+ if(ep0->request.remain_size == 0)
{
- cls = (uclass_t)rt_list_entry(i, struct uclass, list);
- if (cls->ops->sof_handler != RT_NULL)
- cls->ops->sof_handler(device, cls);
+ /* invoke callback */
+ if(ep0->rx_indicate != RT_NULL)
+ {
+ ep0->rx_indicate(device, size);
+ }
}
return RT_EOK;
}
/**
- * This function will stop all class.
+ * This function will notity sof event to all of function.
*
* @param device the usb device object.
*
* @return RT_EOK.
*/
-rt_err_t _stop_notify(udevice_t device)
+static rt_err_t _sof_notify(udevice_t device)
{
struct rt_list_node *i;
- uclass_t cls;
+ ufunction_t func;
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)
+ /* to notity every function that sof event comes */
+ for (i=device->curr_cfg->func_list.next;
+ i!=&device->curr_cfg->func_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);
+ func = (ufunction_t)rt_list_entry(i, struct ufunction, list);
+ if(func->ops->sof_handler != RT_NULL)
+ func->ops->sof_handler(func);
}
return RT_EOK;
}
/**
- * This function will run all class.
+ * This function will disable all USB functions.
*
* @param device the usb device object.
*
* @return RT_EOK.
*/
-rt_err_t _run_notify(udevice_t device)
+static rt_err_t _stop_notify(udevice_t device)
{
struct rt_list_node *i;
- uclass_t cls;
+ ufunction_t func;
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;
+ /* to notity every function */
+ for (i = device->curr_cfg->func_list.next;
+ i != &device->curr_cfg->func_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);
+ func = (ufunction_t)rt_list_entry(i, struct ufunction, list);
+ FUNC_DISABLE(func);
}
return RT_EOK;
}
-/**
- * This function will reset all class.
- *
- * @param device the usb device object.
- *
- * @return RT_EOK.
- */
-rt_err_t _reset_notify(udevice_t device)
+static rt_size_t rt_usbd_ep_write(udevice_t device, uep_t ep, void *buffer, rt_size_t size)
{
- struct rt_list_node *i;
- uclass_t cls;
+ rt_uint16_t maxpacket;
+
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(device->dcd != RT_NULL);
+ RT_ASSERT(ep != RT_NULL);
- RT_ASSERT(device != RT_NULL);
+ maxpacket = EP_MAXPACKET(ep);
+ if(ep->request.remain_size >= maxpacket)
+ {
+ dcd_ep_write(device->dcd, EP_ADDRESS(ep), ep->request.buffer, maxpacket);
+ ep->request.remain_size -= maxpacket;
+ ep->request.buffer += maxpacket;
+ }
+ else
+ {
+ dcd_ep_write(device->dcd, EP_ADDRESS(ep), ep->request.buffer,
+ ep->request.remain_size);
+ ep->request.remain_size = 0;
+ }
- _stop_notify(device);
- _run_notify(device);
+ return size;
+}
- return RT_EOK;
+static rt_size_t rt_usbd_ep_read_prepare(udevice_t device, uep_t ep, void *buffer, rt_size_t size)
+{
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(device->dcd != RT_NULL);
+ RT_ASSERT(ep != RT_NULL);
+ RT_ASSERT(buffer != RT_NULL);
+ RT_ASSERT(ep->ep_desc != RT_NULL);
+
+ return dcd_ep_read_prepare(device->dcd, EP_ADDRESS(ep), buffer, size);
}
/**
@@ -763,18 +920,17 @@ rt_err_t _reset_notify(udevice_t device)
*
* @return an usb device object on success, RT_NULL on fail.
*/
-udevice_t rt_usbd_device_create(void)
+udevice_t rt_usbd_device_new(void)
{
udevice_t udevice;
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_device_create\n"));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_device_new\n"));
/* allocate memory for the object */
udevice = rt_malloc(sizeof(struct udevice));
- if (udevice == RT_NULL)
+ if(udevice == RT_NULL)
{
rt_kprintf("alloc memery failed\n");
-
return RT_NULL;
}
rt_memset(udevice, 0, sizeof(struct udevice));
@@ -783,7 +939,7 @@ udevice_t rt_usbd_device_create(void)
rt_list_init(&udevice->cfg_list);
/* insert the device object to device list */
- rt_list_insert_after(&device_list, &udevice->list);
+ rt_list_insert_before(&device_list, &udevice->list);
return udevice;
}
@@ -791,7 +947,7 @@ udevice_t rt_usbd_device_create(void)
/**
* This function will set usb device string description.
*
- * @param device the usb device object.
+ * @param device the usb device object.
* @param ustring pointer to string pointer array.
*
* @return RT_EOK.
@@ -808,6 +964,17 @@ rt_err_t rt_usbd_device_set_string(udevice_t device, const char** ustring)
return RT_EOK;
}
+rt_err_t rt_usbd_device_set_qualifier(udevice_t device, struct usb_qualifier_descriptor* qualifier)
+{
+ /* parameter check */
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(qualifier != RT_NULL);
+
+ device->dev_qualifier = qualifier;
+
+ return RT_EOK;
+}
+
/**
* This function will set an usb controller driver to a device.
*
@@ -855,31 +1022,30 @@ rt_err_t rt_usbd_device_set_descriptor(udevice_t device, udev_desc_t dev_desc)
*
* @return an usb configuration object.
*/
-uconfig_t rt_usbd_config_create(void)
+uconfig_t rt_usbd_config_new(void)
{
uconfig_t cfg;
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_config_create\n"));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_config_new\n"));
/* allocate memory for the object */
cfg = rt_malloc(sizeof(struct uconfig));
- if (cfg == RT_NULL)
+ if(cfg == RT_NULL)
{
rt_kprintf("alloc memery failed\n");
-
return RT_NULL;
}
rt_memset(cfg, 0, sizeof(struct uconfig));
/* set default value */
- cfg->cfg_desc.bLength = USB_DESC_LENGTH_CONFIG;
- cfg->cfg_desc.type = USB_DESC_TYPE_CONFIGURATION;
+ cfg->cfg_desc.bLength = USB_DESC_LENGTH_CONFIG;
+ cfg->cfg_desc.type = USB_DESC_TYPE_CONFIGURATION;
cfg->cfg_desc.wTotalLength = USB_DESC_LENGTH_CONFIG;
cfg->cfg_desc.bmAttributes = 0xC0;
- cfg->cfg_desc.MaxPower = 0x32;
+ cfg->cfg_desc.MaxPower = 0x32;
- /* to initialize class object list */
- rt_list_init(&cfg->cls_list);
+ /* to initialize function object list */
+ rt_list_init(&cfg->func_list);
return cfg;
}
@@ -892,21 +1058,20 @@ uconfig_t rt_usbd_config_create(void)
*
* @return an usb interface object on success, RT_NULL on fail.
*/
-uintf_t rt_usbd_interface_create(udevice_t device, uintf_handler_t handler)
+uintf_t rt_usbd_interface_new(udevice_t device, uintf_handler_t handler)
{
uintf_t intf;
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_interface_create\n"));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_interface_new\n"));
/* parameter check */
RT_ASSERT(device != RT_NULL);
/* allocate memory for the object */
intf = (uintf_t)rt_malloc(sizeof(struct uinterface));
- if (intf == RT_NULL)
+ if(intf == RT_NULL)
{
rt_kprintf("alloc memery failed\n");
-
return RT_NULL;
}
intf->intf_num = device->nr_intf;
@@ -928,21 +1093,20 @@ uintf_t rt_usbd_interface_create(udevice_t device, uintf_handler_t handler)
*
* @return an usb alternate setting object on success, RT_NULL on fail.
*/
-ualtsetting_t rt_usbd_altsetting_create(rt_size_t desc_size)
+ualtsetting_t rt_usbd_altsetting_new(rt_size_t desc_size)
{
ualtsetting_t setting;
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_altsetting_create\n"));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_altsetting_new\n"));
/* parameter check */
RT_ASSERT(desc_size > 0);
/* allocate memory for the object */
setting = (ualtsetting_t)rt_malloc(sizeof(struct ualtsetting));
- if (setting == RT_NULL)
+ if(setting == RT_NULL)
{
rt_kprintf("alloc memery failed\n");
-
return RT_NULL;
}
/* allocate memory for the desc */
@@ -951,7 +1115,6 @@ ualtsetting_t rt_usbd_altsetting_create(rt_size_t desc_size)
{
rt_kprintf("alloc desc memery failed\n");
rt_free(setting);
-
return RT_NULL;
}
@@ -973,56 +1136,53 @@ ualtsetting_t rt_usbd_altsetting_create(rt_size_t desc_size)
*
* @return RT_EOK.
*/
-rt_err_t rt_usbd_altsetting_config_descriptor(ualtsetting_t setting,
- const void *desc,
- rt_off_t intf_pos)
+rt_err_t rt_usbd_altsetting_config_descriptor(ualtsetting_t setting, const void* desc, rt_off_t intf_pos)
{
RT_ASSERT(setting != RT_NULL);
RT_ASSERT(setting->desc !=RT_NULL);
rt_memcpy(setting->desc, desc, setting->desc_size);
- setting->intf_desc = (uintf_desc_t)((char *)setting->desc + intf_pos);
+ setting->intf_desc = (uintf_desc_t)((char*)setting->desc + intf_pos);
return RT_EOK;
}
/**
- * This function will create an usb class object.
+ * This function will create an usb function object.
*
* @param device the usb device object.
* @param dev_desc the device descriptor.
* @param ops the operation set.
*
- * @return an usb class object on success, RT_NULL on fail.
+ * @return an usb function object on success, RT_NULL on fail.
*/
-uclass_t rt_usbd_class_create(udevice_t device,
- udev_desc_t dev_desc,
- uclass_ops_t ops)
+ufunction_t rt_usbd_function_new(udevice_t device, udev_desc_t dev_desc,
+ ufunction_ops_t ops)
{
- uclass_t cls;
+ ufunction_t func;
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_class_create\n"));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_function_new\n"));
/* parameter check */
RT_ASSERT(device != RT_NULL);
RT_ASSERT(dev_desc != RT_NULL);
/* allocate memory for the object */
- cls = (uclass_t)rt_malloc(sizeof(struct uclass));
- if (cls == RT_NULL)
+ func = (ufunction_t)rt_malloc(sizeof(struct ufunction));
+ if(func == RT_NULL)
{
rt_kprintf("alloc memery failed\n");
-
return RT_NULL;
}
- cls->dev_desc = dev_desc;
- cls->ops = ops;
- cls->device = device;
+ func->dev_desc = dev_desc;
+ func->ops = ops;
+ func->device = device;
+ func->enabled = RT_FALSE;
/* to initialize interface list */
- rt_list_init(&cls->intf_list);
+ rt_list_init(&func->intf_list);
- return cls;
+ return func;
}
/**
@@ -1033,26 +1193,27 @@ uclass_t rt_usbd_class_create(udevice_t device,
*
* @return an usb endpoint object on success, RT_NULL on fail.
*/
-uep_t rt_usbd_endpoint_create(uep_desc_t ep_desc, udep_handler_t handler)
+uep_t rt_usbd_endpoint_new(uep_desc_t ep_desc, udep_handler_t handler)
{
uep_t ep;
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_endpoint_create\n"));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_endpoint_new\n"));
/* parameter check */
RT_ASSERT(ep_desc != RT_NULL);
/* allocate memory for the object */
ep = (uep_t)rt_malloc(sizeof(struct uendpoint));
- if (ep == RT_NULL)
+ if(ep == RT_NULL)
{
rt_kprintf("alloc memery failed\n");
-
return RT_NULL;
}
ep->ep_desc = ep_desc;
ep->handler = handler;
ep->buffer = RT_NULL;
+ ep->stalled = RT_FALSE;
+ rt_list_init(&ep->request_list);
return ep;
}
@@ -1066,7 +1227,7 @@ uep_t rt_usbd_endpoint_create(uep_desc_t ep_desc, udep_handler_t handler)
*/
udevice_t rt_usbd_find_device(udcd_t dcd)
{
- struct rt_list_node *node;
+ struct rt_list_node* node;
udevice_t device;
/* parameter check */
@@ -1076,12 +1237,10 @@ udevice_t rt_usbd_find_device(udcd_t dcd)
for (node = device_list.next; node != &device_list; node = node->next)
{
device = (udevice_t)rt_list_entry(node, struct udevice, list);
- if (device->dcd == dcd)
- return device;
+ if(device->dcd == dcd) return device;
}
rt_kprintf("can't find device\n");
-
return RT_NULL;
}
@@ -1095,7 +1254,7 @@ udevice_t rt_usbd_find_device(udcd_t dcd)
*/
uconfig_t rt_usbd_find_config(udevice_t device, rt_uint8_t value)
{
- struct rt_list_node *node;
+ struct rt_list_node* node;
uconfig_t cfg = RT_NULL;
RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_find_config\n"));
@@ -1105,17 +1264,16 @@ uconfig_t rt_usbd_find_config(udevice_t device, rt_uint8_t value)
RT_ASSERT(value <= device->dev_desc.bNumConfigurations);
/* search a configration in the the device */
- for (node = device->cfg_list.next;
- node != &device->cfg_list;
- node = node->next)
+ for (node = device->cfg_list.next; node != &device->cfg_list; node = node->next)
{
cfg = (uconfig_t)rt_list_entry(node, struct udevice, list);
- if (cfg->cfg_desc.bConfigurationValue == value)
+ if(cfg->cfg_desc.bConfigurationValue == value)
+ {
return cfg;
+ }
}
rt_kprintf("can't find configuration %d\n", value);
-
return RT_NULL;
}
@@ -1127,12 +1285,10 @@ uconfig_t rt_usbd_find_config(udevice_t device, rt_uint8_t value)
*
* @return an usb configuration object on found or RT_NULL on not found.
*/
-uintf_t rt_usbd_find_interface(udevice_t device,
- rt_uint8_t value,
- uclass_t *pcls)
+uintf_t rt_usbd_find_interface(udevice_t device, rt_uint8_t value, ufunction_t *pfunc)
{
struct rt_list_node *i, *j;
- uclass_t cls;
+ ufunction_t func;
uintf_t intf;
RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_find_interface\n"));
@@ -1142,26 +1298,23 @@ uintf_t rt_usbd_find_interface(udevice_t device,
RT_ASSERT(value < device->nr_intf);
/* search an interface in the current configuration */
- for (i = device->curr_cfg->cls_list.next;
- i != &device->curr_cfg->cls_list;
- i = i->next)
+ for (i=device->curr_cfg->func_list.next;
+ i!=&device->curr_cfg->func_list; i=i->next)
{
- cls = (uclass_t)rt_list_entry(i, struct uclass, list);
- for (j=cls->intf_list.next; j!=&cls->intf_list; j=j->next)
+ func = (ufunction_t)rt_list_entry(i, struct ufunction, list);
+ for(j=func->intf_list.next; j!=&func->intf_list; j=j->next)
{
intf = (uintf_t)rt_list_entry(j, struct uinterface, list);
- if (intf->intf_num == value)
+ if(intf->intf_num == value)
{
- if (pcls != RT_NULL)
- *pcls = cls;
-
+ if (pfunc != RT_NULL)
+ *pfunc = func;
return intf;
}
}
}
rt_kprintf("can't find interface %d\n", value);
-
return RT_NULL;
}
@@ -1183,23 +1336,22 @@ ualtsetting_t rt_usbd_find_altsetting(uintf_t intf, rt_uint8_t value)
/* parameter check */
RT_ASSERT(intf != RT_NULL);
- if (intf->curr_setting != RT_NULL)
+ if(intf->curr_setting != RT_NULL)
{
/* if the value equal to the current alternate setting, then do not search */
- if (intf->curr_setting->intf_desc->bAlternateSetting == value)
+ if(intf->curr_setting->intf_desc->bAlternateSetting == value)
return intf->curr_setting;
}
/* search a setting in the alternate setting list */
- for (i=intf->setting_list.next; i!=&intf->setting_list; i=i->next)
+ for(i=intf->setting_list.next; i!=&intf->setting_list; i=i->next)
{
setting =(ualtsetting_t)rt_list_entry(i, struct ualtsetting, list);
- if (setting->intf_desc->bAlternateSetting == value)
+ if(setting->intf_desc->bAlternateSetting == value)
return setting;
}
rt_kprintf("can't find alternate setting %d\n", value);
-
return RT_NULL;
}
@@ -1211,37 +1363,32 @@ ualtsetting_t rt_usbd_find_altsetting(uintf_t intf, rt_uint8_t value)
*
* @return an usb endpoint object on found or RT_NULL on not found.
*/
-uep_t rt_usbd_find_endpoint(udevice_t device,
- uclass_t *pcls,
- rt_uint8_t ep_addr)
+uep_t rt_usbd_find_endpoint(udevice_t device, ufunction_t* pfunc, rt_uint8_t ep_addr)
{
uep_t ep;
struct rt_list_node *i, *j, *k;
- uclass_t cls;
+ ufunction_t func;
uintf_t intf;
/* parameter check */
RT_ASSERT(device != RT_NULL);
/* search a endpoint in the current configuration */
- for (i = device->curr_cfg->cls_list.next;
- i != &device->curr_cfg->cls_list;
- i = i->next)
+ for (i=device->curr_cfg->func_list.next;
+ i!=&device->curr_cfg->func_list; i=i->next)
{
- cls = (uclass_t)rt_list_entry(i, struct uclass, list);
- for (j=cls->intf_list.next; j!=&cls->intf_list; j=j->next)
+ func = (ufunction_t)rt_list_entry(i, struct ufunction, list);
+ for(j=func->intf_list.next; j!=&func->intf_list; j=j->next)
{
intf = (uintf_t)rt_list_entry(j, struct uinterface, list);
- for (k = intf->curr_setting->ep_list.next;
- k != &intf->curr_setting->ep_list;
- k = k->next)
+ for(k=intf->curr_setting->ep_list.next;
+ k!=&intf->curr_setting->ep_list; k=k->next)
{
ep = (uep_t)rt_list_entry(k, struct uendpoint, list);
- if (ep->ep_desc->bEndpointAddress == ep_addr)
+ if(EP_ADDRESS(ep) == ep_addr)
{
- if (pcls != RT_NULL)
- *pcls = cls;
-
+ if (pfunc != RT_NULL)
+ *pfunc = func;
return ep;
}
}
@@ -1249,7 +1396,6 @@ uep_t rt_usbd_find_endpoint(udevice_t device,
}
rt_kprintf("can't find endpoint 0x%x\n", ep_addr);
-
return RT_NULL;
}
@@ -1264,7 +1410,7 @@ uep_t rt_usbd_find_endpoint(udevice_t device,
rt_err_t rt_usbd_device_add_config(udevice_t device, uconfig_t cfg)
{
struct rt_list_node *i, *j, *k;
- uclass_t cls;
+ ufunction_t func;
uintf_t intf;
uep_t ep;
@@ -1278,79 +1424,81 @@ rt_err_t rt_usbd_device_add_config(udevice_t device, uconfig_t cfg)
cfg->cfg_desc.bConfigurationValue = device->dev_desc.bNumConfigurations + 1;
device->dev_desc.bNumConfigurations++;
- for (i=cfg->cls_list.next; i!=&cfg->cls_list; i=i->next)
+ for (i=cfg->func_list.next; i!=&cfg->func_list; i=i->next)
{
- cls = (uclass_t)rt_list_entry(i, struct uclass, list);
+ func = (ufunction_t)rt_list_entry(i, struct ufunction, list);
- for (j=cls->intf_list.next; j!=&cls->intf_list; j=j->next)
+ for(j=func->intf_list.next; j!=&func->intf_list; j=j->next)
{
intf = (uintf_t)rt_list_entry(j, struct uinterface, list);
cfg->cfg_desc.bNumInterfaces++;
/* allocate address for every endpoint in the interface alternate setting */
- for (k = intf->curr_setting->ep_list.next;
- k != &intf->curr_setting->ep_list;
- k = k->next)
+ for(k=intf->curr_setting->ep_list.next;
+ k!=&intf->curr_setting->ep_list; k=k->next)
{
ep = (uep_t)rt_list_entry(k, struct uendpoint, list);
- dcd_ep_alloc(device->dcd, ep);
+ if(rt_usbd_ep_assign(device, ep) != RT_EOK)
+ {
+ rt_kprintf("endpoint assign error\n");
+ }
}
/* construct complete configuration descriptor */
- rt_memcpy((void *)&cfg->cfg_desc.data[cfg->cfg_desc.wTotalLength - USB_DESC_LENGTH_CONFIG],
- (void *)intf->curr_setting->desc,
- intf->curr_setting->desc_size);
+ rt_memcpy((void*)&cfg->cfg_desc.data[cfg->cfg_desc.wTotalLength - USB_DESC_LENGTH_CONFIG],
+ (void*)intf->curr_setting->desc,
+ intf->curr_setting->desc_size);
cfg->cfg_desc.wTotalLength += intf->curr_setting->desc_size;
}
}
/* insert the configuration to the list */
- rt_list_insert_after(&device->cfg_list, &cfg->list);
+ rt_list_insert_before(&device->cfg_list, &cfg->list);
return RT_EOK;
}
/**
- * This function will add a class to a configuration.
+ * This function will add a function to a configuration.
*
* @param cfg the configuration object.
- * @param cls the class object.
+ * @param func the function object.
*
* @return RT_EOK.
*/
-rt_err_t rt_usbd_config_add_class(uconfig_t cfg, uclass_t cls)
+rt_err_t rt_usbd_config_add_function(uconfig_t cfg, ufunction_t func)
{
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_config_add_class\n"));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_config_add_function\n"));
/* parameter check */
RT_ASSERT(cfg != RT_NULL);
- RT_ASSERT(cls != RT_NULL);
+ RT_ASSERT(func != RT_NULL);
- /* insert the class to the list */
- rt_list_insert_after(&cfg->cls_list, &cls->list);
+ /* insert the function to the list */
+ rt_list_insert_before(&cfg->func_list, &func->list);
return RT_EOK;
}
/**
- * This function will add an interface to a class.
+ * This function will add an interface to a function.
*
- * @param cls the class object.
+ * @param func the function object.
* @param intf the interface object.
*
* @return RT_EOK.
*/
-rt_err_t rt_usbd_class_add_interface(uclass_t cls, uintf_t intf)
+rt_err_t rt_usbd_function_add_interface(ufunction_t func, uintf_t intf)
{
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_class_add_interface\n"));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_function_add_interface\n"));
/* parameter check */
- RT_ASSERT(cls != RT_NULL);
+ RT_ASSERT(func != RT_NULL);
RT_ASSERT(intf != RT_NULL);
/* insert the interface to the list */
- rt_list_insert_after(&cls->intf_list, &intf->list);
+ rt_list_insert_before(&func->intf_list, &intf->list);
return RT_EOK;
}
@@ -1374,7 +1522,7 @@ rt_err_t rt_usbd_interface_add_altsetting(uintf_t intf, ualtsetting_t setting)
setting->intf_desc->bInterfaceNumber = intf->intf_num;
/* insert the alternate setting to the list */
- rt_list_insert_after(&intf->setting_list, &setting->list);
+ rt_list_insert_before(&intf->setting_list, &setting->list);
return RT_EOK;
}
@@ -1396,7 +1544,7 @@ rt_err_t rt_usbd_altsetting_add_endpoint(ualtsetting_t setting, uep_t ep)
RT_ASSERT(ep != RT_NULL);
/* insert the endpoint to the list */
- rt_list_insert_after(&setting->ep_list, &ep->list);
+ rt_list_insert_before(&setting->ep_list, &ep->list);
return RT_EOK;
}
@@ -1451,9 +1599,387 @@ rt_err_t rt_usbd_set_config(udevice_t device, rt_uint8_t value)
/* set as current configuration */
device->curr_cfg = cfg;
+ dcd_set_config(device->dcd, value);
+
return RT_TRUE;
}
+/**
+ * This function will request an IO transaction.
+ *
+ * @param device the usb device object.
+ * @param ep the endpoint object.
+ * @param req IO request.
+ *
+ * @return RT_EOK.
+ */
+rt_size_t rt_usbd_io_request(udevice_t device, uep_t ep, uio_request_t req)
+{
+ rt_size_t size = 0;
+
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(req != RT_NULL);
+
+ if(ep->stalled == RT_FALSE)
+ {
+ switch(req->req_type)
+ {
+ case UIO_REQUEST_READ_BEST:
+ case UIO_REQUEST_READ_FULL:
+ ep->request.remain_size = ep->request.size;
+ size = rt_usbd_ep_read_prepare(device, ep, req->buffer, req->size);
+ break;
+ case UIO_REQUEST_WRITE:
+ ep->request.remain_size = ep->request.size;
+ size = rt_usbd_ep_write(device, ep, req->buffer, req->size);
+ break;
+ default:
+ rt_kprintf("unknown request type\n");
+ break;
+ }
+ }
+ else
+ {
+ rt_list_insert_before(&ep->request_list, &req->list);
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("suspend a request\n"));
+ }
+
+ return size;
+}
+
+/**
+ * This function will set feature for an usb device.
+ *
+ * @param device the usb device object.
+ * @param value the configuration number.
+ *
+ * @return RT_EOK.
+ */
+rt_err_t rt_usbd_set_feature(udevice_t device, rt_uint16_t value, rt_uint16_t index)
+{
+ RT_ASSERT(device != RT_NULL);
+
+ if (value == USB_FEATURE_DEV_REMOTE_WAKEUP)
+ {
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("set feature remote wakeup\n"));
+ }
+ else if (value == USB_FEATURE_ENDPOINT_HALT)
+ {
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("set feature stall\n"));
+ dcd_ep_set_stall(device->dcd, (rt_uint32_t)(index & 0xFF));
+ }
+
+ return RT_EOK;
+}
+
+/**
+ * This function will clear feature for an usb device.
+ *
+ * @param device the usb device object.
+ * @param value the configuration number.
+ *
+ * @return RT_EOK.
+ */
+rt_err_t rt_usbd_clear_feature(udevice_t device, rt_uint16_t value, rt_uint16_t index)
+{
+ RT_ASSERT(device != RT_NULL);
+
+ if (value == USB_FEATURE_DEV_REMOTE_WAKEUP)
+ {
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("clear feature remote wakeup\n"));
+ }
+ else if (value == USB_FEATURE_ENDPOINT_HALT)
+ {
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("clear feature stall\n"));
+ dcd_ep_clear_stall(device->dcd, (rt_uint32_t)(index & 0xFF));
+ }
+
+ return RT_EOK;
+}
+
+rt_err_t rt_usbd_ep0_set_stall(udevice_t device)
+{
+ RT_ASSERT(device != RT_NULL);
+
+ return dcd_ep_set_stall(device->dcd, 0);
+}
+
+rt_err_t rt_usbd_ep0_clear_stall(udevice_t device)
+{
+ RT_ASSERT(device != RT_NULL);
+
+ return dcd_ep_clear_stall(device->dcd, 0);
+}
+
+rt_err_t rt_usbd_ep_set_stall(udevice_t device, uep_t ep)
+{
+ rt_err_t ret;
+
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(ep != RT_NULL);
+ RT_ASSERT(ep->ep_desc != RT_NULL);
+
+ ret = dcd_ep_set_stall(device->dcd, EP_ADDRESS(ep));
+ if(ret == RT_EOK)
+ {
+ ep->stalled = RT_TRUE;
+ }
+
+ return ret;
+}
+
+rt_err_t rt_usbd_ep_clear_stall(udevice_t device, uep_t ep)
+{
+ rt_err_t ret;
+
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(ep != RT_NULL);
+ RT_ASSERT(ep->ep_desc != RT_NULL);
+
+ ret = dcd_ep_clear_stall(device->dcd, EP_ADDRESS(ep));
+ if(ret == RT_EOK)
+ {
+ ep->stalled = RT_FALSE;
+ }
+
+ return ret;
+}
+
+static rt_err_t rt_usbd_ep_assign(udevice_t device, uep_t ep)
+{
+ int i = 0;
+
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(device->dcd != RT_NULL);
+ RT_ASSERT(device->dcd->ep_pool != RT_NULL);
+ RT_ASSERT(ep != RT_NULL);
+ RT_ASSERT(ep->ep_desc != RT_NULL);
+
+ while(device->dcd->ep_pool[i].addr != 0xFF)
+ {
+ if(device->dcd->ep_pool[i].status == ID_UNASSIGNED &&
+ ep->ep_desc->bmAttributes == device->dcd->ep_pool[i].type)
+ {
+ EP_ADDRESS(ep) |= device->dcd->ep_pool[i].addr;
+ ep->id = &device->dcd->ep_pool[i];
+ device->dcd->ep_pool[i].status = ID_ASSIGNED;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("assigned %d\n", device->dcd->ep_pool[i].addr));
+ return RT_EOK;
+ }
+
+ i++;
+ }
+
+ return -RT_ERROR;
+}
+
+static rt_err_t rt_usbd_ep_unassign(udevice_t device, uep_t ep)
+{
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(device->dcd != RT_NULL);
+ RT_ASSERT(device->dcd->ep_pool != RT_NULL);
+ RT_ASSERT(ep != RT_NULL);
+ RT_ASSERT(ep->ep_desc != RT_NULL);
+
+ ep->id->status = ID_UNASSIGNED;
+
+ return RT_EOK;
+}
+
+rt_err_t rt_usbd_ep0_setup_handler(udcd_t dcd, struct ureqest* setup)
+{
+ struct udev_msg msg;
+ rt_size_t size;
+
+ RT_ASSERT(dcd != RT_NULL);
+
+ if(setup == RT_NULL)
+ {
+ size = dcd_ep_read(dcd, EP0_OUT_ADDR, (void*)&msg.content.setup);
+ if(size != sizeof(struct ureqest))
+ {
+ rt_kprintf("read setup packet error\n");
+ return -RT_ERROR;
+ }
+ }
+ else
+ {
+ rt_memcpy((void*)&msg.content.setup, (void*)setup, sizeof(struct ureqest));
+ }
+
+ msg.type = USB_MSG_SETUP_NOTIFY;
+ msg.dcd = dcd;
+ rt_usbd_event_signal(&msg);
+
+ return RT_EOK;
+}
+
+rt_err_t rt_usbd_ep0_in_handler(udcd_t dcd)
+{
+ 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;
+ }
+ else if(dcd->ep0.request.remain_size > 0)
+ {
+ dcd_ep_write(dcd, EP0_IN_ADDR, dcd->ep0.request.buffer, dcd->ep0.request.remain_size);
+ dcd->ep0.request.remain_size = 0;
+ }
+ else
+ {
+ dcd_ep_write(dcd, EP0_IN_ADDR, RT_NULL, 0);
+ }
+
+ return RT_EOK;
+}
+
+rt_err_t rt_usbd_ep0_out_handler(udcd_t dcd, rt_size_t size)
+{
+ struct udev_msg msg;
+
+ RT_ASSERT(dcd != RT_NULL);
+
+ msg.type = USB_MSG_EP0_OUT;
+ msg.dcd = dcd;
+ msg.content.ep_msg.size = size;
+ rt_usbd_event_signal(&msg);
+
+ return RT_EOK;
+}
+
+rt_err_t rt_usbd_ep_in_handler(udcd_t dcd, rt_uint8_t address)
+{
+ struct udev_msg msg;
+
+ RT_ASSERT(dcd != RT_NULL);
+
+ msg.type = USB_MSG_DATA_NOTIFY;
+ msg.dcd = dcd;
+ msg.content.ep_msg.ep_addr = address;
+ msg.content.ep_msg.size = 0;
+ rt_usbd_event_signal(&msg);
+
+ return RT_EOK;
+}
+
+rt_err_t rt_usbd_ep_out_handler(udcd_t dcd, rt_uint8_t address, rt_size_t size)
+{
+ struct udev_msg msg;
+
+ RT_ASSERT(dcd != RT_NULL);
+
+ msg.type = USB_MSG_DATA_NOTIFY;
+ msg.dcd = dcd;
+ msg.content.ep_msg.ep_addr = address;
+ msg.content.ep_msg.size = size;
+ rt_usbd_event_signal(&msg);
+
+ return RT_EOK;
+}
+
+rt_err_t rt_usbd_reset_handler(udcd_t dcd)
+{
+ struct udev_msg msg;
+
+ RT_ASSERT(dcd != RT_NULL);
+
+ msg.type = USB_MSG_RESET;
+ msg.dcd = dcd;
+ rt_usbd_event_signal(&msg);
+
+ return RT_EOK;
+}
+
+rt_err_t rt_usbd_connect_handler(udcd_t dcd)
+{
+ struct udev_msg msg;
+
+ RT_ASSERT(dcd != RT_NULL);
+
+ msg.type = USB_MSG_PLUG_IN;
+ msg.dcd = dcd;
+ rt_usbd_event_signal(&msg);
+
+ return RT_EOK;
+}
+
+rt_err_t rt_usbd_disconnect_handler(udcd_t dcd)
+{
+ struct udev_msg msg;
+
+ RT_ASSERT(dcd != RT_NULL);
+
+ msg.type = USB_MSG_PLUG_OUT;
+ msg.dcd = dcd;
+ rt_usbd_event_signal(&msg);
+
+ return RT_EOK;
+}
+
+rt_err_t rt_usbd_sof_handler(udcd_t dcd)
+{
+ struct udev_msg msg;
+
+ RT_ASSERT(dcd != RT_NULL);
+
+ msg.type = USB_MSG_SOF;
+ msg.dcd = dcd;
+ rt_usbd_event_signal(&msg);
+
+ return RT_EOK;
+}
+
+rt_size_t rt_usbd_ep0_write(udevice_t device, void *buffer, rt_size_t size)
+{
+ uep_t ep0;
+
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(device->dcd != RT_NULL);
+ RT_ASSERT(buffer != RT_NULL);
+ RT_ASSERT(size > 0);
+
+ ep0 = &device->dcd->ep0;
+ ep0->request.size = size;
+ ep0->request.buffer = buffer;
+ ep0->request.remain_size = size;
+ if(ep0->request.remain_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;
+ }
+ else
+ {
+ dcd_ep_write(device->dcd, EP0_IN_ADDR, ep0->request.buffer, ep0->request.remain_size);
+ ep0->request.remain_size = 0;
+ }
+
+ return size;
+}
+
+rt_size_t rt_usbd_ep0_read(udevice_t device, void *buffer, rt_size_t size,
+ rt_err_t (*rx_ind)(udevice_t device, rt_size_t size))
+{
+ uep_t ep0;
+
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(device->dcd != RT_NULL);
+ RT_ASSERT(buffer != RT_NULL);
+
+ ep0 = &device->dcd->ep0;
+ ep0->request.size = size;
+ ep0->request.buffer = buffer;
+ ep0->request.remain_size = size;
+ ep0->rx_indicate = rx_ind;
+ dcd_ep_read_prepare(device->dcd, EP0_OUT_ADDR, buffer, size);
+
+ return size;
+}
+
static struct rt_messagequeue usb_mq;
/**
@@ -1464,26 +1990,27 @@ static struct rt_messagequeue usb_mq;
*
* @return none.
*/
-static void rt_usbd_thread_entry(void *parameter)
+static void rt_usbd_thread_entry(void* parameter)
{
- while (1)
+ while(1)
{
struct udev_msg msg;
udevice_t device;
- uclass_t cls;
- uep_t ep;
/* receive message */
- if (rt_mq_recv(&usb_mq, &msg, sizeof(struct udev_msg), RT_WAITING_FOREVER) != RT_EOK)
+ if(rt_mq_recv(&usb_mq, &msg, sizeof(struct udev_msg),
+ RT_WAITING_FOREVER) != RT_EOK )
continue;
device = rt_usbd_find_device(msg.dcd);
- if (device == RT_NULL)
+ if(device == RT_NULL)
{
rt_kprintf("invalid usb device\n");
continue;
}
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("message type %d\n", msg.type));
+
switch (msg.type)
{
case USB_MSG_SOF:
@@ -1492,26 +2019,28 @@ static void rt_usbd_thread_entry(void *parameter)
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);
- else
- rt_kprintf("invalid endpoint\n");
+ _data_notify(device, &msg.content.ep_msg);
break;
case USB_MSG_SETUP_NOTIFY:
- _setup_request(device, (ureq_t)msg.content.setup_msg.packet);
+ _setup_request(device, &msg.content.setup);
+ break;
+ case USB_MSG_EP0_OUT:
+ _ep0_out_notify(device, &msg.content.ep_msg);
break;
- case USB_MSG_RESET:
+ case USB_MSG_RESET:
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("reset %d\n", device->state));
if (device->state == USB_STATE_ADDRESS)
- _reset_notify(device);
+ _stop_notify(device);
+ break;
+ case USB_MSG_PLUG_IN:
+ device->state = USB_STATE_ATTACHED;
break;
case USB_MSG_PLUG_OUT:
+ device->state = USB_STATE_NOTATTACHED;
_stop_notify(device);
break;
default:
- rt_kprintf("unknown msg type\n");
+ rt_kprintf("unknown msg type %d\n", msg.type);
break;
}
}
@@ -1525,12 +2054,12 @@ static void rt_usbd_thread_entry(void *parameter)
*
* @return the error code, RT_EOK on successfully.
*/
-rt_err_t rt_usbd_post_event(struct udev_msg *msg, rt_size_t size)
+rt_err_t rt_usbd_event_signal(struct udev_msg* msg)
{
RT_ASSERT(msg != RT_NULL);
/* send message to usb message queue */
- return rt_mq_send(&usb_mq, (void *)msg, size);
+ return rt_mq_send(&usb_mq, (void*)msg, sizeof(struct udev_msg));
}
@@ -1548,30 +2077,21 @@ static rt_uint8_t usb_mq_pool[(USBD_MQ_MSG_SZ+sizeof(void*))*USBD_MQ_MAX_MSG];
* This function will initialize usb device thread.
*
* @return none.
+ *
*/
rt_err_t rt_usbd_core_init(void)
{
rt_list_init(&device_list);
/* create an usb message queue */
- rt_mq_init(&usb_mq,
- "usbd",
- usb_mq_pool,
- USBD_MQ_MSG_SZ,
- sizeof(usb_mq_pool),
- RT_IPC_FLAG_FIFO);
+ rt_mq_init(&usb_mq, "usbd", usb_mq_pool, USBD_MQ_MSG_SZ,
+ sizeof(usb_mq_pool), RT_IPC_FLAG_FIFO);
/* init usb device thread */
- rt_thread_init(&usb_thread,
- "usbd",
- rt_usbd_thread_entry,
- RT_NULL,
- usb_thread_stack,
- RT_USBD_THREAD_STACK_SZ,
- RT_USBD_THREAD_PRIO,
- 20);
+ rt_thread_init(&usb_thread, "usbd", rt_usbd_thread_entry, RT_NULL,
+ usb_thread_stack, RT_USBD_THREAD_STACK_SZ, RT_USBD_THREAD_PRIO, 20);
/* rt_thread_init should always be OK, so start the thread without further
* checking. */
-
return rt_thread_startup(&usb_thread);
}
+
diff --git a/components/drivers/usb/usbdevice/core/usbdevice.c b/components/drivers/usb/usbdevice/core/usbdevice.c
index f5b2b9beac..adef1db2a0 100644
--- a/components/drivers/usb/usbdevice/core/usbdevice.c
+++ b/components/drivers/usb/usbdevice/core/usbdevice.c
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Change Logs:
* Date Author Notes
* 2012-10-02 Yi Qiu first version
@@ -28,13 +28,15 @@
#ifdef RT_USING_USB_DEVICE
+#define USB_DEVICE_CONTROLLER_NAME "usbd"
+
#ifdef RT_USB_DEVICE_COMPOSITE
const static char* ustring[] =
{
"Language",
"RT-Thread Team.",
"RTT Composite Device",
- "1.1.0",
+ "320219198301",
"Configuration",
"Interface",
};
@@ -60,54 +62,54 @@ static struct udevice_descriptor compsit_desc =
};
#endif
-rt_err_t rt_usb_device_init(const char* udc_name)
+rt_err_t rt_usb_device_init(void)
{
rt_device_t udc;
udevice_t udevice;
uconfig_t cfg;
- uclass_t cls;
+ ufunction_t func;
+
+ /* create and startup usb device thread */
+ rt_usbd_core_init();
- RT_ASSERT(udc_name != RT_NULL);
+ /* create a device object */
+ udevice = rt_usbd_device_new();
- udc = rt_device_find(udc_name);
+ udc = rt_device_find(USB_DEVICE_CONTROLLER_NAME);
if(udc == RT_NULL)
{
- rt_kprintf("can't find usb device controller %s\n", udc_name);
+ rt_kprintf("can't find usb device controller %s\n", USB_DEVICE_CONTROLLER_NAME);
return -RT_ERROR;
}
- /* create and startup usb device thread */
- rt_usbd_core_init();
-
- /* create a device object */
- udevice = rt_usbd_device_create();
-
/* set usb controller driver to the device */
rt_usbd_device_set_controller(udevice, (udcd_t)udc);
/* create a configuration object */
- cfg = rt_usbd_config_create();
+ cfg = rt_usbd_config_new();
#ifdef RT_USB_DEVICE_MSTORAGE
- /* create a mass storage class object */
- cls = rt_usbd_class_mstorage_create(udevice);
+ /* create a mass storage function object */
+ func = rt_usbd_function_mstorage_create(udevice);
- /* add the class to the configuration */
- rt_usbd_config_add_class(cfg, cls);
+ /* add the function to the configuration */
+ rt_usbd_config_add_function(cfg, func);
#endif
+
#ifdef RT_USB_DEVICE_CDC
- /* create a cdc class object */
- cls = rt_usbd_class_cdc_create(udevice);
+ /* create a cdc function object */
+ func = rt_usbd_function_cdc_create(udevice);
- /* add the class to the configuration */
- rt_usbd_config_add_class(cfg, cls);
+ /* add the function to the configuration */
+ rt_usbd_config_add_function(cfg, func);
#endif
+
#ifdef RT_USB_DEVICE_RNDIS
- /* create a rndis class object */
- cls = rt_usbd_class_rndis_create(udevice);
+ /* create a rndis function object */
+ func = rt_usbd_function_rndis_create(udevice);
- /* add the class to the configuration */
- rt_usbd_config_add_class(cfg, cls);
+ /* add the function to the configuration */
+ rt_usbd_config_add_function(cfg, func);
#endif
/* set device descriptor to the device */
@@ -115,18 +117,18 @@ rt_err_t rt_usb_device_init(const char* udc_name)
rt_usbd_device_set_descriptor(udevice, &compsit_desc);
rt_usbd_device_set_string(udevice, ustring);
#else
- rt_usbd_device_set_descriptor(udevice, cls->dev_desc);
+ rt_usbd_device_set_descriptor(udevice, func->dev_desc);
#endif
/* add the configuration to the device */
rt_usbd_device_add_config(udevice, cfg);
- /* set default configuration to 1 */
- rt_usbd_set_config(udevice, 1);
-
/* initialize usb device controller */
rt_device_init(udc);
+ /* set default configuration to 1 */
+ rt_usbd_set_config(udevice, 1);
+
return RT_EOK;
}