summaryrefslogtreecommitdiff
path: root/components/drivers/usb
diff options
context:
space:
mode:
authorBernard Xiong <[email protected]>2013-01-08 18:13:32 -0800
committerBernard Xiong <[email protected]>2013-01-08 18:13:32 -0800
commitaccace98e05eda28c116eb04502eb92d01b6ef1e (patch)
tree4a425c96e0be3980779c8205c7c3fe2f1a144630 /components/drivers/usb
parent1fab41d48a490f6483582147500d43f4ca889a8e (diff)
parent02b8e9366f362926799bfaecc0891830ba62f646 (diff)
Merge pull request #8 from mbbill/correct_crlf
Correct crlf
Diffstat (limited to 'components/drivers/usb')
-rw-r--r--components/drivers/usb/SConscript28
-rw-r--r--components/drivers/usb/usbdevice/SConscript46
-rw-r--r--components/drivers/usb/usbdevice/class/cdc.h348
-rw-r--r--components/drivers/usb/usbdevice/class/cdc_vcom.c1182
-rw-r--r--components/drivers/usb/usbdevice/class/mstorage.c1196
-rw-r--r--components/drivers/usb/usbdevice/class/mstorage.h132
-rw-r--r--components/drivers/usb/usbdevice/core/core.c2642
-rw-r--r--components/drivers/usb/usbdevice/core/usbdevice.c234
-rw-r--r--components/drivers/usb/usbhost/SConscript68
-rw-r--r--components/drivers/usb/usbhost/class/adk.c814
-rw-r--r--components/drivers/usb/usbhost/class/adk.h94
-rw-r--r--components/drivers/usb/usbhost/core/core.c938
-rw-r--r--components/drivers/usb/usbhost/core/driver.c288
-rw-r--r--components/drivers/usb/usbhost/core/hub.c1222
-rw-r--r--components/drivers/usb/usbhost/core/usbhost.c148
15 files changed, 4690 insertions, 4690 deletions
diff --git a/components/drivers/usb/SConscript b/components/drivers/usb/SConscript
index 1cb7618499..744d8d7821 100644
--- a/components/drivers/usb/SConscript
+++ b/components/drivers/usb/SConscript
@@ -1,14 +1,14 @@
-# for module compiling
-import os
-from building import *
-
-cwd = GetCurrentDir()
-objs = []
-list = os.listdir(cwd)
-
-for d in list:
- path = os.path.join(cwd, d)
- if os.path.isfile(os.path.join(path, 'SConscript')):
- objs = objs + SConscript(os.path.join(d, 'SConscript'))
-
-Return('objs')
+# for module compiling
+import os
+from building import *
+
+cwd = GetCurrentDir()
+objs = []
+list = os.listdir(cwd)
+
+for d in list:
+ path = os.path.join(cwd, d)
+ if os.path.isfile(os.path.join(path, 'SConscript')):
+ objs = objs + SConscript(os.path.join(d, 'SConscript'))
+
+Return('objs')
diff --git a/components/drivers/usb/usbdevice/SConscript b/components/drivers/usb/usbdevice/SConscript
index afaac2e89f..d46ec3db59 100644
--- a/components/drivers/usb/usbdevice/SConscript
+++ b/components/drivers/usb/usbdevice/SConscript
@@ -1,23 +1,23 @@
-Import('RTT_ROOT')
-from building import *
-
-cwd = GetCurrentDir()
-src = Split("""
-core/core.c
-core/usbdevice.c
-""")
-
-if GetDepend('RT_USB_DEVICE_CDC'):
- src += Glob('class/cdc_vcom.c')
-
-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)
-
-Return('group')
+Import('RTT_ROOT')
+from building import *
+
+cwd = GetCurrentDir()
+src = Split("""
+core/core.c
+core/usbdevice.c
+""")
+
+if GetDepend('RT_USB_DEVICE_CDC'):
+ src += Glob('class/cdc_vcom.c')
+
+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)
+
+Return('group')
diff --git a/components/drivers/usb/usbdevice/class/cdc.h b/components/drivers/usb/usbdevice/class/cdc.h
index 859148ae43..ff938fd452 100644
--- a/components/drivers/usb/usbdevice/class/cdc.h
+++ b/components/drivers/usb/usbdevice/class/cdc.h
@@ -1,174 +1,174 @@
-/*
- * File : cdc.h
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2012, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2012-10-03 Yi Qiu first version
- * 2012-12-12 heyuanjie87 add CDC endpoints collection
- */
-
-#ifndef __CDC_H__
-#define __CDC_H__
-
-#define USB_CDC_PRODUCT_ID 0x5740 /* Product ID */
-#define USB_CDC_BUFSIZE 0x40
-
-#define USB_CDC_CLASS_COMM 0x02
-#define USB_CDC_CLASS_DATA 0x0A
-
-#define USB_CDC_SUBCLASS_DLCM 0x01
-#define USB_CDC_SUBCLASS_ACM 0x02
-#define USB_CDC_SUBCLASS_TCM 0x03
-#define USB_CDC_SUBCLASS_MCCM 0x04
-#define USB_CDC_SUBCLASS_CCM 0x05
-#define USB_CDC_SUBCLASS_ETH 0x06
-#define USB_CDC_SUBCLASS_ATM 0x07
-
-#define USB_CDC_PROTOCOL_V25TER 0x01
-
-#define USB_CDC_PROTOCOL_I430 0x30
-#define USB_CDC_PROTOCOL_HDLC 0x31
-#define USB_CDC_PROTOCOL_TRANS 0x32
-#define USB_CDC_PROTOCOL_Q921M 0x50
-#define USB_CDC_PROTOCOL_Q921 0x51
-#define USB_CDC_PROTOCOL_Q921TM 0x52
-#define USB_CDC_PROTOCOL_V42BIS 0x90
-#define USB_CDC_PROTOCOL_Q931 0x91
-#define USB_CDC_PROTOCOL_V120 0x92
-#define USB_CDC_PROTOCOL_CAPI20 0x93
-#define USB_CDC_PROTOCOL_HOST 0xFD
-#define USB_CDC_PROTOCOL_PUFD 0xFE
-#define USB_CDC_PROTOCOL_VENDOR 0xFF
-
-#define USB_CDC_CS_INTERFACE 0x24
-#define USB_CDC_CS_ENDPOINT 0x25
-
-#define USB_CDC_SCS_HEADER 0x00
-#define USB_CDC_SCS_CALL_MGMT 0x01
-#define USB_CDC_SCS_ACM 0x02
-#define USB_CDC_SCS_UNION 0x06
-
-#define CDC_SEND_ENCAPSULATED_COMMAND 0x00
-#define CDC_GET_ENCAPSULATED_RESPONSE 0x01
-#define CDC_SET_COMM_FEATURE 0x02
-#define CDC_GET_COMM_FEATURE 0x03
-#define CDC_CLEAR_COMM_FEATURE 0x04
-#define CDC_SET_AUX_LINE_STATE 0x10
-#define CDC_SET_HOOK_STATE 0x11
-#define CDC_PULSE_SETUP 0x12
-#define CDC_SEND_PULSE 0x13
-#define CDC_SET_PULSE_TIME 0x14
-#define CDC_RING_AUX_JACK 0x15
-#define CDC_SET_LINE_CODING 0x20
-#define CDC_GET_LINE_CODING 0x21
-#define CDC_SET_CONTROL_LINE_STATE 0x22
-#define CDC_SEND_BREAK 0x23
-#define CDC_SET_RINGER_PARMS 0x30
-#define CDC_GET_RINGER_PARMS 0x31
-#define CDC_SET_OPERATION_PARMS 0x32
-#define CDC_GET_OPERATION_PARMS 0x33
-#define CDC_SET_LINE_PARMS 0x34
-#define CDC_GET_LINE_PARMS 0x35
-#define CDC_DIAL_DIGITS 0x36
-#define CDC_SET_UNIT_PARAMETER 0x37
-#define CDC_GET_UNIT_PARAMETER 0x38
-#define CDC_CLEAR_UNIT_PARAMETER 0x39
-#define CDC_GET_PROFILE 0x3A
-#define CDC_SET_ETH_MULTICAST_FILTERS 0x40
-#define CDC_SET_ETH_POWER_MGMT_FILT 0x41
-#define CDC_GET_ETH_POWER_MGMT_FILT 0x42
-#define CDC_SET_ETH_PACKET_FILTER 0x43
-#define CDC_GET_ETH_STATISTIC 0x44
-#define CDC_SET_ATM_DATA_FORMAT 0x50
-#define CDC_GET_ATM_DEVICE_STATISTICS 0x51
-#define CDC_SET_ATM_DEFAULT_VC 0x52
-#define CDC_GET_ATM_VC_STATISTICS 0x53
-
-#pragma pack(1)
-
-struct ucdc_header_descriptor
-{
- rt_uint8_t length;
- rt_uint8_t type;
- rt_uint8_t subtype;
- rt_uint16_t bcd;
-};
-typedef struct ucdc_header_descriptor* ucdc_hdr_desc_t;
-
-struct ucdc_acm_descriptor
-{
- rt_uint8_t length;
- rt_uint8_t type;
- rt_uint8_t subtype;
- rt_uint8_t capabilties;
-};
-typedef struct ucdc_acm_descriptor* ucdc_acm_desc_t;
-
-struct ucdc_call_mgmt_descriptor
-{
- rt_uint8_t length;
- rt_uint8_t type;
- rt_uint8_t subtype;
- rt_uint8_t capabilties;
- rt_uint8_t data_interface;
-};
-typedef struct ucdc_call_mgmt_descriptor* ucdc_call_mgmt_desc_t;
-
-struct ucdc_union_descriptor
-{
- rt_uint8_t length;
- rt_uint8_t type;
- rt_uint8_t subtype;
- rt_uint8_t master_interface;
- rt_uint8_t slave_interface0;
-};
-typedef struct ucdc_union_descriptor* ucdc_union_desc_t;
-
-struct ucdc_comm_descriptor
-{
-#ifdef RT_USB_DEVICE_COMPOSITE
- struct uiad_descriptor iad_desc;
-#endif
- struct uinterface_descriptor intf_desc;
- struct ucdc_header_descriptor hdr_desc;
- struct ucdc_call_mgmt_descriptor call_mgmt_desc;
- struct ucdc_acm_descriptor acm_desc;
- struct ucdc_union_descriptor union_desc;
- struct uendpoint_descriptor ep_desc;
-};
-typedef struct ucdc_comm_descriptor* ucdc_comm_desc_t;
-
-struct ucdc_data_descriptor
-{
- struct uinterface_descriptor intf_desc;
- struct uendpoint_descriptor ep_out_desc;
- struct uendpoint_descriptor ep_in_desc;
-};
-typedef struct ucdc_data_descriptor* ucdc_data_desc_t;
-
-struct ucdc_line_coding
-{
- rt_uint32_t dwDTERate;
- rt_uint8_t bCharFormat;
- rt_uint8_t bParityType;
- rt_uint8_t bDataBits;
-};
-typedef struct ucdc_line_coding* ucdc_line_coding_t;
-
-struct cdc_eps
-{
- uep_t ep_out;
- uep_t ep_in;
- uep_t ep_cmd;
-};
-typedef struct cdc_eps* cdc_eps_t;
-
-#pragma pack()
-
-#endif
+/*
+ * File : cdc.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2012, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2012-10-03 Yi Qiu first version
+ * 2012-12-12 heyuanjie87 add CDC endpoints collection
+ */
+
+#ifndef __CDC_H__
+#define __CDC_H__
+
+#define USB_CDC_PRODUCT_ID 0x5740 /* Product ID */
+#define USB_CDC_BUFSIZE 0x40
+
+#define USB_CDC_CLASS_COMM 0x02
+#define USB_CDC_CLASS_DATA 0x0A
+
+#define USB_CDC_SUBCLASS_DLCM 0x01
+#define USB_CDC_SUBCLASS_ACM 0x02
+#define USB_CDC_SUBCLASS_TCM 0x03
+#define USB_CDC_SUBCLASS_MCCM 0x04
+#define USB_CDC_SUBCLASS_CCM 0x05
+#define USB_CDC_SUBCLASS_ETH 0x06
+#define USB_CDC_SUBCLASS_ATM 0x07
+
+#define USB_CDC_PROTOCOL_V25TER 0x01
+
+#define USB_CDC_PROTOCOL_I430 0x30
+#define USB_CDC_PROTOCOL_HDLC 0x31
+#define USB_CDC_PROTOCOL_TRANS 0x32
+#define USB_CDC_PROTOCOL_Q921M 0x50
+#define USB_CDC_PROTOCOL_Q921 0x51
+#define USB_CDC_PROTOCOL_Q921TM 0x52
+#define USB_CDC_PROTOCOL_V42BIS 0x90
+#define USB_CDC_PROTOCOL_Q931 0x91
+#define USB_CDC_PROTOCOL_V120 0x92
+#define USB_CDC_PROTOCOL_CAPI20 0x93
+#define USB_CDC_PROTOCOL_HOST 0xFD
+#define USB_CDC_PROTOCOL_PUFD 0xFE
+#define USB_CDC_PROTOCOL_VENDOR 0xFF
+
+#define USB_CDC_CS_INTERFACE 0x24
+#define USB_CDC_CS_ENDPOINT 0x25
+
+#define USB_CDC_SCS_HEADER 0x00
+#define USB_CDC_SCS_CALL_MGMT 0x01
+#define USB_CDC_SCS_ACM 0x02
+#define USB_CDC_SCS_UNION 0x06
+
+#define CDC_SEND_ENCAPSULATED_COMMAND 0x00
+#define CDC_GET_ENCAPSULATED_RESPONSE 0x01
+#define CDC_SET_COMM_FEATURE 0x02
+#define CDC_GET_COMM_FEATURE 0x03
+#define CDC_CLEAR_COMM_FEATURE 0x04
+#define CDC_SET_AUX_LINE_STATE 0x10
+#define CDC_SET_HOOK_STATE 0x11
+#define CDC_PULSE_SETUP 0x12
+#define CDC_SEND_PULSE 0x13
+#define CDC_SET_PULSE_TIME 0x14
+#define CDC_RING_AUX_JACK 0x15
+#define CDC_SET_LINE_CODING 0x20
+#define CDC_GET_LINE_CODING 0x21
+#define CDC_SET_CONTROL_LINE_STATE 0x22
+#define CDC_SEND_BREAK 0x23
+#define CDC_SET_RINGER_PARMS 0x30
+#define CDC_GET_RINGER_PARMS 0x31
+#define CDC_SET_OPERATION_PARMS 0x32
+#define CDC_GET_OPERATION_PARMS 0x33
+#define CDC_SET_LINE_PARMS 0x34
+#define CDC_GET_LINE_PARMS 0x35
+#define CDC_DIAL_DIGITS 0x36
+#define CDC_SET_UNIT_PARAMETER 0x37
+#define CDC_GET_UNIT_PARAMETER 0x38
+#define CDC_CLEAR_UNIT_PARAMETER 0x39
+#define CDC_GET_PROFILE 0x3A
+#define CDC_SET_ETH_MULTICAST_FILTERS 0x40
+#define CDC_SET_ETH_POWER_MGMT_FILT 0x41
+#define CDC_GET_ETH_POWER_MGMT_FILT 0x42
+#define CDC_SET_ETH_PACKET_FILTER 0x43
+#define CDC_GET_ETH_STATISTIC 0x44
+#define CDC_SET_ATM_DATA_FORMAT 0x50
+#define CDC_GET_ATM_DEVICE_STATISTICS 0x51
+#define CDC_SET_ATM_DEFAULT_VC 0x52
+#define CDC_GET_ATM_VC_STATISTICS 0x53
+
+#pragma pack(1)
+
+struct ucdc_header_descriptor
+{
+ rt_uint8_t length;
+ rt_uint8_t type;
+ rt_uint8_t subtype;
+ rt_uint16_t bcd;
+};
+typedef struct ucdc_header_descriptor* ucdc_hdr_desc_t;
+
+struct ucdc_acm_descriptor
+{
+ rt_uint8_t length;
+ rt_uint8_t type;
+ rt_uint8_t subtype;
+ rt_uint8_t capabilties;
+};
+typedef struct ucdc_acm_descriptor* ucdc_acm_desc_t;
+
+struct ucdc_call_mgmt_descriptor
+{
+ rt_uint8_t length;
+ rt_uint8_t type;
+ rt_uint8_t subtype;
+ rt_uint8_t capabilties;
+ rt_uint8_t data_interface;
+};
+typedef struct ucdc_call_mgmt_descriptor* ucdc_call_mgmt_desc_t;
+
+struct ucdc_union_descriptor
+{
+ rt_uint8_t length;
+ rt_uint8_t type;
+ rt_uint8_t subtype;
+ rt_uint8_t master_interface;
+ rt_uint8_t slave_interface0;
+};
+typedef struct ucdc_union_descriptor* ucdc_union_desc_t;
+
+struct ucdc_comm_descriptor
+{
+#ifdef RT_USB_DEVICE_COMPOSITE
+ struct uiad_descriptor iad_desc;
+#endif
+ struct uinterface_descriptor intf_desc;
+ struct ucdc_header_descriptor hdr_desc;
+ struct ucdc_call_mgmt_descriptor call_mgmt_desc;
+ struct ucdc_acm_descriptor acm_desc;
+ struct ucdc_union_descriptor union_desc;
+ struct uendpoint_descriptor ep_desc;
+};
+typedef struct ucdc_comm_descriptor* ucdc_comm_desc_t;
+
+struct ucdc_data_descriptor
+{
+ struct uinterface_descriptor intf_desc;
+ struct uendpoint_descriptor ep_out_desc;
+ struct uendpoint_descriptor ep_in_desc;
+};
+typedef struct ucdc_data_descriptor* ucdc_data_desc_t;
+
+struct ucdc_line_coding
+{
+ rt_uint32_t dwDTERate;
+ rt_uint8_t bCharFormat;
+ rt_uint8_t bParityType;
+ rt_uint8_t bDataBits;
+};
+typedef struct ucdc_line_coding* ucdc_line_coding_t;
+
+struct cdc_eps
+{
+ uep_t ep_out;
+ uep_t ep_in;
+ uep_t ep_cmd;
+};
+typedef struct cdc_eps* cdc_eps_t;
+
+#pragma pack()
+
+#endif
diff --git a/components/drivers/usb/usbdevice/class/cdc_vcom.c b/components/drivers/usb/usbdevice/class/cdc_vcom.c
index ac558c9e32..addbb66c8e 100644
--- a/components/drivers/usb/usbdevice/class/cdc_vcom.c
+++ b/components/drivers/usb/usbdevice/class/cdc_vcom.c
@@ -1,591 +1,591 @@
-/*
- * File : cdc_vcom.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2012, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2012-10-02 Yi Qiu first version
- * 2012-12-12 heyuanjie87 change endpoints and class handler
- */
-
-#include <rtthread.h>
-#include <rtdevice.h>
-#include <rthw.h>
-#include "cdc.h"
-
-#ifdef RT_USB_DEVICE_CDC
-
-#define CDC_RX_BUFSIZE 64
-#define CDC_TX_BUFSIZE 2048
-static rt_uint8_t rx_pool[CDC_RX_BUFSIZE];
-static rt_uint8_t tx_pool[CDC_TX_BUFSIZE];
-static struct rt_ringbuffer rx_ringbuffer;
-static struct rt_ringbuffer tx_ringbuffer;
-static struct rt_serial_device vcom_serial;
-static struct serial_ringbuffer vcom_int_rx;
-static rt_bool_t vcom_connected = RT_FALSE;
-
-static struct udevice_descriptor dev_desc =
-{
- USB_DESC_LENGTH_DEVICE, //bLength;
- USB_DESC_TYPE_DEVICE, //type;
- USB_BCD_VERSION, //bcdUSB;
- USB_CLASS_CDC, //bDeviceClass;
- 0x00, //bDeviceSubClass;
- 0x00, //bDeviceProtocol;
- 0x40, //bMaxPacketSize0;
- USB_VENDOR_ID, //idVendor;
- USB_CDC_PRODUCT_ID, //idProduct;
- USB_BCD_DEVICE, //bcdDevice;
- USB_STRING_MANU_INDEX, //iManufacturer;
- USB_STRING_PRODUCT_INDEX, //iProduct;
- USB_STRING_SERIAL_INDEX, //iSerialNumber;
- USB_DYNAMIC, //bNumConfigurations;
-};
-
-/* communcation interface descriptor */
-const static struct ucdc_comm_descriptor _comm_desc =
-{
-#ifdef RT_USB_DEVICE_COMPOSITE
- /* Interface Association Descriptor */
- USB_DESC_LENGTH_IAD,
- USB_DESC_TYPE_IAD,
- USB_DYNAMIC,
- 0x02,
- USB_CDC_CLASS_COMM,
- USB_CDC_SUBCLASS_ACM,
- USB_CDC_PROTOCOL_V25TER,
- 0x00,
-#endif
- /* Interface Descriptor */
- USB_DESC_LENGTH_INTERFACE,
- USB_DESC_TYPE_INTERFACE,
- USB_DYNAMIC,
- 0x00,
- 0x01,
- USB_CDC_CLASS_COMM,
- USB_CDC_SUBCLASS_ACM,
- USB_CDC_PROTOCOL_V25TER,
- 0x00,
- /* Header Functional Descriptor */
- 0x05,
- USB_CDC_CS_INTERFACE,
- USB_CDC_SCS_HEADER,
- 0x0110,
- /* Call Management Functional Descriptor */
- 0x05,
- USB_CDC_CS_INTERFACE,
- USB_CDC_SCS_CALL_MGMT,
- 0x00,
- USB_DYNAMIC,
- /* Abstract Control Management Functional Descriptor */
- 0x04,
- USB_CDC_CS_INTERFACE,
- USB_CDC_SCS_ACM,
- 0x02,
- /* Union Functional Descriptor */
- 0x05,
- USB_CDC_CS_INTERFACE,
- USB_CDC_SCS_UNION,
- USB_DYNAMIC,
- USB_DYNAMIC,
- /* Endpoint Descriptor */
- USB_DESC_LENGTH_ENDPOINT,
- USB_DESC_TYPE_ENDPOINT,
- USB_DYNAMIC | USB_DIR_IN,
- USB_EP_ATTR_INT,
- 0x08,
- 0xFF,
-};
-
-/* data interface descriptor */
-const static struct ucdc_data_descriptor _data_desc =
-{
- /* interface descriptor */
- USB_DESC_LENGTH_INTERFACE,
- USB_DESC_TYPE_INTERFACE,
- USB_DYNAMIC,
- 0x00,
- 0x02,
- USB_CDC_CLASS_DATA,
- 0x00,
- 0x00,
- 0x00,
- /* endpoint, bulk out */
- USB_DESC_LENGTH_ENDPOINT,
- USB_DESC_TYPE_ENDPOINT,
- USB_DYNAMIC | USB_DIR_OUT,
- USB_EP_ATTR_BULK,
- USB_CDC_BUFSIZE,
- 0x00,
- /* endpoint, bulk in */
- USB_DESC_LENGTH_ENDPOINT,
- USB_DESC_TYPE_ENDPOINT,
- USB_DYNAMIC | USB_DIR_IN,
- USB_EP_ATTR_BULK,
- USB_CDC_BUFSIZE,
- 0x00,
-};
-
-/**
- * This function will handle cdc 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)
-{
- rt_uint32_t level;
- rt_size_t length;
- cdc_eps_t eps;
- rt_size_t mps;
-
- eps = (cdc_eps_t)cls->eps;
- mps = eps->ep_in->ep_desc->wMaxPacketSize;
- size = RT_RINGBUFFER_SIZE(&tx_ringbuffer);
- if(size == 0) return RT_EOK;
-
- length = size > mps ? mps : size;
-
- level = rt_hw_interrupt_disable();
- rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, length);
- rt_hw_interrupt_enable(level);
-
- /* send data to host */
- dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, length);
-
- return RT_EOK;
-}
-
-/**
- * This function will handle cdc 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)
-{
- rt_uint32_t level;
- cdc_eps_t eps;
-
- RT_ASSERT(device != RT_NULL);
-
- eps = (cdc_eps_t)cls->eps;
- /* receive data from USB VCOM */
- level = rt_hw_interrupt_disable();
- rt_ringbuffer_put(&rx_ringbuffer, eps->ep_out->buffer, size);
- rt_hw_interrupt_enable(level);
-
- /* notify receive data */
- rt_hw_serial_isr(&vcom_serial);
-
- dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer,
- eps->ep_out->ep_desc->wMaxPacketSize);
-
- return RT_EOK;
-}
-
-/**
- * This function will handle cdc interrupt in endpoint request.
- *
- * @param device the usb device object.
- * @param size request size.
- *
- * @return RT_EOK.
- */
-static rt_err_t _ep_cmd_handler(udevice_t device, uclass_t cls, rt_size_t size)
-{
- RT_ASSERT(device != RT_NULL);
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_cmd_handler\n"));
-
- return RT_EOK;
-}
-
-/**
- * This function will handle cdc_get_line_coding request.
- *
- * @param device the usb device object.
- * @param setup the setup request.
- *
- * @return RT_EOK on successful.
- */
-static rt_err_t _cdc_get_line_coding(udevice_t device, ureq_t setup)
-{
- struct ucdc_line_coding data;
- rt_uint16_t size;
-
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(setup != RT_NULL);
-
- 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);
-
- return RT_EOK;
-}
-
-/**
- * This function will handle cdc_set_line_coding request.
- *
- * @param device the usb device object.
- * @param setup the setup request.
- *
- * @return RT_EOK on successful.
- */
-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);
-
- 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");
- }
-
- return RT_EOK;
-}
-
-/**
- * This function will handle cdc interface request.
- *
- * @param device the usb device 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)
-{
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(setup != RT_NULL);
-
- switch(setup->request)
- {
- case CDC_SEND_ENCAPSULATED_COMMAND:
- break;
- case CDC_GET_ENCAPSULATED_RESPONSE:
- break;
- case CDC_SET_COMM_FEATURE:
- break;
- case CDC_GET_COMM_FEATURE:
- break;
- case CDC_CLEAR_COMM_FEATURE:
- break;
- case CDC_SET_LINE_CODING:
- _cdc_set_line_coding(device, setup);
- vcom_connected = RT_TRUE;
- break;
- case CDC_GET_LINE_CODING:
- _cdc_get_line_coding(device, setup);
- break;
- case CDC_SET_CONTROL_LINE_STATE:
- rt_device_control((rt_device_t)device->dcd, CONTROL_SEND_STATUS, RT_NULL);
- break;
- case CDC_SEND_BREAK:
- break;
- default:
- rt_kprintf("unknown cdc request\n",setup->request_type);
- return -RT_ERROR;
- }
-
- return RT_EOK;
-}
-
-/**
- * This function will run cdc class, 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_run(udevice_t device, uclass_t cls)
-{
- 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;
-
- eps->ep_in->buffer=tx_pool;
- eps->ep_out->buffer=rx_pool;
-
- dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer,
- eps->ep_out->ep_desc->wMaxPacketSize);
-
- return RT_EOK;
-}
-
-/**
- * This function will stop cdc class, 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)
-{
- RT_ASSERT(device != RT_NULL);
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("cdc class stop\n"));
-
- return RT_EOK;
-}
-
-/**
- * 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;
- static rt_uint32_t frame_count = 0;
- cdc_eps_t eps;
-
- if(vcom_connected != RT_TRUE) return -RT_ERROR;
-
- eps = (cdc_eps_t)cls->eps;
- if (frame_count ++ == 5)
- {
- rt_size_t mps = eps->ep_in->ep_desc->wMaxPacketSize;
-
- /* reset the frame counter */
- frame_count = 0;
-
- size = RT_RINGBUFFER_SIZE(&tx_ringbuffer);
- if(size == 0) return -RT_EFULL;
-
- size = size > mps ? mps : size;
-
- level = rt_hw_interrupt_disable();
- rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, size);
- rt_hw_interrupt_enable(level);
-
- /* send data to host */
- dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, size);
- }
-
- return RT_EOK;
-}
-
-static struct uclass_ops ops =
-{
- _class_run,
- _class_stop,
- _class_sof_handler,
-};
-
-/**
- * This function will configure cdc descriptor.
- *
- * @param comm the communication interface number.
- * @param data the data interface number.
- *
- * @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)
-{
- comm->call_mgmt_desc.data_interface = dintf_nr;
- comm->union_desc.master_interface = cintf_nr;
- comm->union_desc.slave_interface0 = dintf_nr;
-#ifdef RT_USB_DEVICE_COMPOSITE
- comm->iad_desc.bFirstInterface = cintf_nr;
-#endif
-
- return RT_EOK;
-}
-
-/**
- * This function will create a cdc class instance.
- *
- * @param device the usb device object.
- *
- * @return RT_EOK on successful.
- */
-uclass_t rt_usbd_class_cdc_create(udevice_t device)
-{
- uclass_t cdc;
- cdc_eps_t eps;
- uintf_t intf_comm, intf_data;
- ualtsetting_t comm_setting, data_setting;
- ucdc_data_desc_t data_desc;
- ucdc_comm_desc_t comm_desc;
-
- /* parameter check */
- RT_ASSERT(device != RT_NULL);
-
- /* 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 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);
-
- /* 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));
-
- /* config desc in alternate setting */
- rt_usbd_altsetting_config_descriptor(comm_setting, &_comm_desc,
- (rt_off_t)&((ucdc_comm_desc_t)0)->intf_desc);
- rt_usbd_altsetting_config_descriptor(data_setting, &_data_desc, 0);
- /* 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);
-
- /* add the command endpoint to the cdc communication interface */
- rt_usbd_altsetting_add_endpoint(comm_setting, eps->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);
-
- return cdc;
-}
-
-/**
-* UART device in RT-Thread
-*/
-static rt_err_t _vcom_configure(struct rt_serial_device *serial,
- struct serial_configure *cfg)
-{
- return RT_EOK;
-}
-
-static rt_err_t _vcom_control(struct rt_serial_device *serial,
- int cmd, void *arg)
-{
- switch (cmd)
- {
- case RT_DEVICE_CTRL_CLR_INT:
- /* disable rx irq */
- break;
- case RT_DEVICE_CTRL_SET_INT:
- /* enable rx irq */
- break;
- }
-
- return RT_EOK;
-}
-
-static int _vcom_putc(struct rt_serial_device *serial, char c)
-{
- rt_uint32_t level;
-
- if (vcom_connected != RT_TRUE) return 0;
-
- level = rt_hw_interrupt_disable();
- if (RT_RINGBUFFER_EMPTY(&tx_ringbuffer))
- {
- rt_ringbuffer_putchar(&tx_ringbuffer, c);
- }
- rt_hw_interrupt_enable(level);
-
- return 1;
-}
-
-static int _vcom_getc(struct rt_serial_device *serial)
-{
- int result;
- rt_uint8_t ch;
- rt_uint32_t level;
-
- result = -1;
-
- level = rt_hw_interrupt_disable();
- if (RT_RINGBUFFER_SIZE(&rx_ringbuffer))
- {
- rt_ringbuffer_getchar(&rx_ringbuffer, &ch);
- result = ch;
- }
- rt_hw_interrupt_enable(level);
-
- return result;
-}
-
-static const struct rt_uart_ops usb_vcom_ops =
-{
- _vcom_configure,
- _vcom_control,
- _vcom_putc,
- _vcom_getc,
-};
-
-void rt_usb_vcom_init(void)
-{
- struct serial_configure config;
-
- /* initialize ring buffer */
- rt_ringbuffer_init(&rx_ringbuffer, rx_pool, CDC_RX_BUFSIZE);
- rt_ringbuffer_init(&tx_ringbuffer, tx_pool, CDC_TX_BUFSIZE);
-
- config.baud_rate = BAUD_RATE_115200;
- config.bit_order = BIT_ORDER_LSB;
- config.data_bits = DATA_BITS_8;
- config.parity = PARITY_NONE;
- 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;
-
- /* register vcom device */
- rt_hw_serial_register(&vcom_serial, "vcom",
- RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM,
- RT_NULL);
-}
-
-#endif
-
+/*
+ * File : cdc_vcom.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2012, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2012-10-02 Yi Qiu first version
+ * 2012-12-12 heyuanjie87 change endpoints and class handler
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <rthw.h>
+#include "cdc.h"
+
+#ifdef RT_USB_DEVICE_CDC
+
+#define CDC_RX_BUFSIZE 64
+#define CDC_TX_BUFSIZE 2048
+static rt_uint8_t rx_pool[CDC_RX_BUFSIZE];
+static rt_uint8_t tx_pool[CDC_TX_BUFSIZE];
+static struct rt_ringbuffer rx_ringbuffer;
+static struct rt_ringbuffer tx_ringbuffer;
+static struct rt_serial_device vcom_serial;
+static struct serial_ringbuffer vcom_int_rx;
+static rt_bool_t vcom_connected = RT_FALSE;
+
+static struct udevice_descriptor dev_desc =
+{
+ USB_DESC_LENGTH_DEVICE, //bLength;
+ USB_DESC_TYPE_DEVICE, //type;
+ USB_BCD_VERSION, //bcdUSB;
+ USB_CLASS_CDC, //bDeviceClass;
+ 0x00, //bDeviceSubClass;
+ 0x00, //bDeviceProtocol;
+ 0x40, //bMaxPacketSize0;
+ USB_VENDOR_ID, //idVendor;
+ USB_CDC_PRODUCT_ID, //idProduct;
+ USB_BCD_DEVICE, //bcdDevice;
+ USB_STRING_MANU_INDEX, //iManufacturer;
+ USB_STRING_PRODUCT_INDEX, //iProduct;
+ USB_STRING_SERIAL_INDEX, //iSerialNumber;
+ USB_DYNAMIC, //bNumConfigurations;
+};
+
+/* communcation interface descriptor */
+const static struct ucdc_comm_descriptor _comm_desc =
+{
+#ifdef RT_USB_DEVICE_COMPOSITE
+ /* Interface Association Descriptor */
+ USB_DESC_LENGTH_IAD,
+ USB_DESC_TYPE_IAD,
+ USB_DYNAMIC,
+ 0x02,
+ USB_CDC_CLASS_COMM,
+ USB_CDC_SUBCLASS_ACM,
+ USB_CDC_PROTOCOL_V25TER,
+ 0x00,
+#endif
+ /* Interface Descriptor */
+ USB_DESC_LENGTH_INTERFACE,
+ USB_DESC_TYPE_INTERFACE,
+ USB_DYNAMIC,
+ 0x00,
+ 0x01,
+ USB_CDC_CLASS_COMM,
+ USB_CDC_SUBCLASS_ACM,
+ USB_CDC_PROTOCOL_V25TER,
+ 0x00,
+ /* Header Functional Descriptor */
+ 0x05,
+ USB_CDC_CS_INTERFACE,
+ USB_CDC_SCS_HEADER,
+ 0x0110,
+ /* Call Management Functional Descriptor */
+ 0x05,
+ USB_CDC_CS_INTERFACE,
+ USB_CDC_SCS_CALL_MGMT,
+ 0x00,
+ USB_DYNAMIC,
+ /* Abstract Control Management Functional Descriptor */
+ 0x04,
+ USB_CDC_CS_INTERFACE,
+ USB_CDC_SCS_ACM,
+ 0x02,
+ /* Union Functional Descriptor */
+ 0x05,
+ USB_CDC_CS_INTERFACE,
+ USB_CDC_SCS_UNION,
+ USB_DYNAMIC,
+ USB_DYNAMIC,
+ /* Endpoint Descriptor */
+ USB_DESC_LENGTH_ENDPOINT,
+ USB_DESC_TYPE_ENDPOINT,
+ USB_DYNAMIC | USB_DIR_IN,
+ USB_EP_ATTR_INT,
+ 0x08,
+ 0xFF,
+};
+
+/* data interface descriptor */
+const static struct ucdc_data_descriptor _data_desc =
+{
+ /* interface descriptor */
+ USB_DESC_LENGTH_INTERFACE,
+ USB_DESC_TYPE_INTERFACE,
+ USB_DYNAMIC,
+ 0x00,
+ 0x02,
+ USB_CDC_CLASS_DATA,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* endpoint, bulk out */
+ USB_DESC_LENGTH_ENDPOINT,
+ USB_DESC_TYPE_ENDPOINT,
+ USB_DYNAMIC | USB_DIR_OUT,
+ USB_EP_ATTR_BULK,
+ USB_CDC_BUFSIZE,
+ 0x00,
+ /* endpoint, bulk in */
+ USB_DESC_LENGTH_ENDPOINT,
+ USB_DESC_TYPE_ENDPOINT,
+ USB_DYNAMIC | USB_DIR_IN,
+ USB_EP_ATTR_BULK,
+ USB_CDC_BUFSIZE,
+ 0x00,
+};
+
+/**
+ * This function will handle cdc 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)
+{
+ rt_uint32_t level;
+ rt_size_t length;
+ cdc_eps_t eps;
+ rt_size_t mps;
+
+ eps = (cdc_eps_t)cls->eps;
+ mps = eps->ep_in->ep_desc->wMaxPacketSize;
+ size = RT_RINGBUFFER_SIZE(&tx_ringbuffer);
+ if(size == 0) return RT_EOK;
+
+ length = size > mps ? mps : size;
+
+ level = rt_hw_interrupt_disable();
+ rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, length);
+ rt_hw_interrupt_enable(level);
+
+ /* send data to host */
+ dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, length);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle cdc 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)
+{
+ rt_uint32_t level;
+ cdc_eps_t eps;
+
+ RT_ASSERT(device != RT_NULL);
+
+ eps = (cdc_eps_t)cls->eps;
+ /* receive data from USB VCOM */
+ level = rt_hw_interrupt_disable();
+ rt_ringbuffer_put(&rx_ringbuffer, eps->ep_out->buffer, size);
+ rt_hw_interrupt_enable(level);
+
+ /* notify receive data */
+ rt_hw_serial_isr(&vcom_serial);
+
+ dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer,
+ eps->ep_out->ep_desc->wMaxPacketSize);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle cdc interrupt in endpoint request.
+ *
+ * @param device the usb device object.
+ * @param size request size.
+ *
+ * @return RT_EOK.
+ */
+static rt_err_t _ep_cmd_handler(udevice_t device, uclass_t cls, rt_size_t size)
+{
+ RT_ASSERT(device != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_cmd_handler\n"));
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle cdc_get_line_coding request.
+ *
+ * @param device the usb device object.
+ * @param setup the setup request.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _cdc_get_line_coding(udevice_t device, ureq_t setup)
+{
+ struct ucdc_line_coding data;
+ rt_uint16_t size;
+
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(setup != RT_NULL);
+
+ 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);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle cdc_set_line_coding request.
+ *
+ * @param device the usb device object.
+ * @param setup the setup request.
+ *
+ * @return RT_EOK on successful.
+ */
+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);
+
+ 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");
+ }
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle cdc interface request.
+ *
+ * @param device the usb device 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)
+{
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(setup != RT_NULL);
+
+ switch(setup->request)
+ {
+ case CDC_SEND_ENCAPSULATED_COMMAND:
+ break;
+ case CDC_GET_ENCAPSULATED_RESPONSE:
+ break;
+ case CDC_SET_COMM_FEATURE:
+ break;
+ case CDC_GET_COMM_FEATURE:
+ break;
+ case CDC_CLEAR_COMM_FEATURE:
+ break;
+ case CDC_SET_LINE_CODING:
+ _cdc_set_line_coding(device, setup);
+ vcom_connected = RT_TRUE;
+ break;
+ case CDC_GET_LINE_CODING:
+ _cdc_get_line_coding(device, setup);
+ break;
+ case CDC_SET_CONTROL_LINE_STATE:
+ rt_device_control((rt_device_t)device->dcd, CONTROL_SEND_STATUS, RT_NULL);
+ break;
+ case CDC_SEND_BREAK:
+ break;
+ default:
+ rt_kprintf("unknown cdc request\n",setup->request_type);
+ return -RT_ERROR;
+ }
+
+ return RT_EOK;
+}
+
+/**
+ * This function will run cdc class, 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_run(udevice_t device, uclass_t cls)
+{
+ 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;
+
+ eps->ep_in->buffer=tx_pool;
+ eps->ep_out->buffer=rx_pool;
+
+ dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer,
+ eps->ep_out->ep_desc->wMaxPacketSize);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will stop cdc class, 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)
+{
+ RT_ASSERT(device != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("cdc class stop\n"));
+
+ return RT_EOK;
+}
+
+/**
+ * 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;
+ static rt_uint32_t frame_count = 0;
+ cdc_eps_t eps;
+
+ if(vcom_connected != RT_TRUE) return -RT_ERROR;
+
+ eps = (cdc_eps_t)cls->eps;
+ if (frame_count ++ == 5)
+ {
+ rt_size_t mps = eps->ep_in->ep_desc->wMaxPacketSize;
+
+ /* reset the frame counter */
+ frame_count = 0;
+
+ size = RT_RINGBUFFER_SIZE(&tx_ringbuffer);
+ if(size == 0) return -RT_EFULL;
+
+ size = size > mps ? mps : size;
+
+ level = rt_hw_interrupt_disable();
+ rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, size);
+ rt_hw_interrupt_enable(level);
+
+ /* send data to host */
+ dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, size);
+ }
+
+ return RT_EOK;
+}
+
+static struct uclass_ops ops =
+{
+ _class_run,
+ _class_stop,
+ _class_sof_handler,
+};
+
+/**
+ * This function will configure cdc descriptor.
+ *
+ * @param comm the communication interface number.
+ * @param data the data interface number.
+ *
+ * @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)
+{
+ comm->call_mgmt_desc.data_interface = dintf_nr;
+ comm->union_desc.master_interface = cintf_nr;
+ comm->union_desc.slave_interface0 = dintf_nr;
+#ifdef RT_USB_DEVICE_COMPOSITE
+ comm->iad_desc.bFirstInterface = cintf_nr;
+#endif
+
+ return RT_EOK;
+}
+
+/**
+ * This function will create a cdc class instance.
+ *
+ * @param device the usb device object.
+ *
+ * @return RT_EOK on successful.
+ */
+uclass_t rt_usbd_class_cdc_create(udevice_t device)
+{
+ uclass_t cdc;
+ cdc_eps_t eps;
+ uintf_t intf_comm, intf_data;
+ ualtsetting_t comm_setting, data_setting;
+ ucdc_data_desc_t data_desc;
+ ucdc_comm_desc_t comm_desc;
+
+ /* parameter check */
+ RT_ASSERT(device != RT_NULL);
+
+ /* 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 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);
+
+ /* 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));
+
+ /* config desc in alternate setting */
+ rt_usbd_altsetting_config_descriptor(comm_setting, &_comm_desc,
+ (rt_off_t)&((ucdc_comm_desc_t)0)->intf_desc);
+ rt_usbd_altsetting_config_descriptor(data_setting, &_data_desc, 0);
+ /* 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);
+
+ /* add the command endpoint to the cdc communication interface */
+ rt_usbd_altsetting_add_endpoint(comm_setting, eps->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);
+
+ return cdc;
+}
+
+/**
+* UART device in RT-Thread
+*/
+static rt_err_t _vcom_configure(struct rt_serial_device *serial,
+ struct serial_configure *cfg)
+{
+ return RT_EOK;
+}
+
+static rt_err_t _vcom_control(struct rt_serial_device *serial,
+ int cmd, void *arg)
+{
+ switch (cmd)
+ {
+ case RT_DEVICE_CTRL_CLR_INT:
+ /* disable rx irq */
+ break;
+ case RT_DEVICE_CTRL_SET_INT:
+ /* enable rx irq */
+ break;
+ }
+
+ return RT_EOK;
+}
+
+static int _vcom_putc(struct rt_serial_device *serial, char c)
+{
+ rt_uint32_t level;
+
+ if (vcom_connected != RT_TRUE) return 0;
+
+ level = rt_hw_interrupt_disable();
+ if (RT_RINGBUFFER_EMPTY(&tx_ringbuffer))
+ {
+ rt_ringbuffer_putchar(&tx_ringbuffer, c);
+ }
+ rt_hw_interrupt_enable(level);
+
+ return 1;
+}
+
+static int _vcom_getc(struct rt_serial_device *serial)
+{
+ int result;
+ rt_uint8_t ch;
+ rt_uint32_t level;
+
+ result = -1;
+
+ level = rt_hw_interrupt_disable();
+ if (RT_RINGBUFFER_SIZE(&rx_ringbuffer))
+ {
+ rt_ringbuffer_getchar(&rx_ringbuffer, &ch);
+ result = ch;
+ }
+ rt_hw_interrupt_enable(level);
+
+ return result;
+}
+
+static const struct rt_uart_ops usb_vcom_ops =
+{
+ _vcom_configure,
+ _vcom_control,
+ _vcom_putc,
+ _vcom_getc,
+};
+
+void rt_usb_vcom_init(void)
+{
+ struct serial_configure config;
+
+ /* initialize ring buffer */
+ rt_ringbuffer_init(&rx_ringbuffer, rx_pool, CDC_RX_BUFSIZE);
+ rt_ringbuffer_init(&tx_ringbuffer, tx_pool, CDC_TX_BUFSIZE);
+
+ config.baud_rate = BAUD_RATE_115200;
+ config.bit_order = BIT_ORDER_LSB;
+ config.data_bits = DATA_BITS_8;
+ config.parity = PARITY_NONE;
+ 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;
+
+ /* register vcom device */
+ rt_hw_serial_register(&vcom_serial, "vcom",
+ RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM,
+ RT_NULL);
+}
+
+#endif
+
diff --git a/components/drivers/usb/usbdevice/class/mstorage.c b/components/drivers/usb/usbdevice/class/mstorage.c
index 000bad5b62..389c2ea479 100644
--- a/components/drivers/usb/usbdevice/class/mstorage.c
+++ b/components/drivers/usb/usbdevice/class/mstorage.c
@@ -1,598 +1,598 @@
-/*
- * File : mstorage.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2012, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * 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
- */
-
-#include <rtthread.h>
-#include <rtservice.h>
-#include <rtdevice.h>
-#include "mstorage.h"
-
-#ifdef RT_USB_DEVICE_MSTORAGE
-
-#define STATUS_CBW 0x00
-#define STATUS_CSW 0x01
-#define STATUS_RECEIVE 0x02
-#define STATUS_SEND 0x03
-
-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 struct udevice_descriptor dev_desc =
-{
- USB_DESC_LENGTH_DEVICE, //bLength;
- USB_DESC_TYPE_DEVICE, //type;
- USB_BCD_VERSION, //bcdUSB;
- USB_CLASS_MASS_STORAGE, //bDeviceClass;
- 0x00, //bDeviceSubClass;
- 0x00, //bDeviceProtocol;
- 0x40, //bMaxPacketSize0;
- USB_VENDOR_ID, //idVendor;
- USB_MASS_STORAGE_PRODUCT_ID,//idProduct;
- USB_BCD_DEVICE, //bcdDevice;
- USB_STRING_MANU_INDEX, //iManufacturer;
- USB_STRING_PRODUCT_INDEX, //iProduct;
- USB_STRING_SERIAL_INDEX, //iSerialNumber;
- USB_DYNAMIC, //bNumConfigurations;
-};
-
-const static struct umass_descriptor _mass_desc =
-{
- USB_DESC_LENGTH_INTERFACE, //bLength;
- USB_DESC_TYPE_INTERFACE, //type;
- USB_DYNAMIC, //bInterfaceNumber;
- 0x00, //bAlternateSetting;
- 0x02, //bNumEndpoints
- USB_CLASS_MASS_STORAGE, //bInterfaceClass;
- 0x06, //bInterfaceSubClass;
- 0x50, //bInterfaceProtocol;
- 0x00, //iInterface;
-
- USB_DESC_LENGTH_ENDPOINT, //bLength;
- USB_DESC_TYPE_ENDPOINT, //type;
- USB_DYNAMIC | USB_DIR_OUT, //bEndpointAddress;
- USB_EP_ATTR_BULK, //bmAttributes;
- 0x40, //wMaxPacketSize;
- 0x00, //bInterval;
-
- USB_DESC_LENGTH_ENDPOINT, //bLength;
- USB_DESC_TYPE_ENDPOINT, //type;
- USB_DYNAMIC | USB_DIR_IN, //bEndpointAddress;
- USB_EP_ATTR_BULK, //bmAttributes;
- 0x40, //wMaxPacketSize;
- 0x00, //bInterval;
-};
-
-/**
- * This function will allocate an usb device instance from system.
- *
- * @param parent the hub instance to which the new allocated device attached.
- * @param port the hub port.
- *
- * @return the allocate instance on successful, or RT_NULL on failure.
- */
-static rt_err_t _inquiry_cmd(udevice_t device, uep_t ep_in)
-{
- rt_uint8_t data[36];
-
- *(rt_uint32_t*)&data[0] = 0x0 | (0x80 << 8);
- *(rt_uint32_t*)&data[4] = 31;
-
- rt_memset(&data[8], 0x20, 28);
- rt_memcpy(&data[8], "RTT", 3);
- rt_memcpy(&data[16], "USB Disk", 8);
-
- dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 36);
-
- return RT_EOK;
-}
-
-/**
- * This function will handle sense request.
- *
- * @param device the usb device object.
- *
- * @return RT_EOK on successful.
- */
-static rt_err_t _request_sense(udevice_t device, uep_t ep_in)
-{
- struct request_sense_data data;
-
- data.ErrorCode = 0x70;
- data.Valid = 0;
- data.SenseKey = 5;
- data.Information[0] = 0;
- data.Information[1] = 0;
- data.Information[2] = 0;
- data.Information[3] = 0;
- data.AdditionalSenseLength = 0x0b;
- data.AdditionalSenseCode = 0x20;
- data.AdditionalSenseCodeQualifier =0;
-
- dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, sizeof(struct request_sense_data));
-
- return RT_EOK;
-}
-
-/**
- * This function will handle mode_sense_6 request.
- *
- * @param device the usb device object.
- *
- * @return RT_EOK on successful.
- */
-static rt_err_t _mode_sense_6(udevice_t device, uep_t ep_in)
-{
- rt_uint8_t data[4];
-
- data[0]=3;
- data[1]=0;
- data[2]=0;
- data[3]=0;
-
- dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 4);
-
- return RT_EOK;
-}
-
-/**
- * This function will handle read_capacities request.
- *
- * @param device the usb device object.
- *
- * @return RT_EOK on successful.
- */
-static rt_err_t _read_capacities(udevice_t device, uep_t ep_in)
-{
- rt_uint8_t data[12];
- rt_uint32_t sector_count, sector_size;
-
- RT_ASSERT(device != RT_NULL);
-
- sector_count = geometry.sector_count;
- sector_size = geometry.bytes_per_sector;
-
- *(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;
-
- dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 12);
-
- return RT_EOK;
-}
-
-/**
- * This function will handle read_capacity request.
- *
- * @param device the usb device object.
- *
- * @return RT_EOK on successful.
- */
-static rt_err_t _read_capacity(udevice_t device, uep_t ep_in)
-{
- rt_uint8_t data[8];
- rt_uint32_t sector_count, sector_size;
-
- RT_ASSERT(device != RT_NULL);
-
- sector_count = geometry.sector_count;
- sector_size = geometry.bytes_per_sector;
-
- 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;
-
- dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 8);
-
- return RT_EOK;
-}
-
-/**
- * This function will handle read_10 request.
- *
- * @param device the usb device 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)
-{
- RT_ASSERT(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 ;
-
- RT_ASSERT(_count < 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
- {
- status = STATUS_CSW;
- }
-
- return RT_EOK;
-}
-
-/**
- * This function will handle write_10 request.
- *
- * @param device the usb device 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)
-{
- RT_ASSERT(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;
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("_write_10 count 0x%x 0x%x\n",
- _count, geometry.sector_count));
-
- dcd_ep_read(device->dcd, ep_out, ep_out->buffer, geometry.bytes_per_sector);
-
- return RT_EOK;
-}
-
-/**
- * This function will handle verify_10 request.
- *
- * @param device the usb device object.
- *
- * @return RT_EOK on successful.
- */
-static rt_err_t _verify_10(udevice_t device)
-{
- return RT_EOK;
-}
-
-/**
- * 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)
-{
- mass_eps_t eps;
- RT_ASSERT(device != RT_NULL);
-
- eps = cls->eps;
- if(status == STATUS_CSW)
- {
- dcd_ep_write(device->dcd, eps->ep_in, (rt_uint8_t*)&csw, SIZEOF_CSW);
- status = STATUS_CBW;
- dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer, SIZEOF_CBW);
- }
- if(status == STATUS_SEND)
- {
- 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)
- {
- _block ++;
- status = STATUS_SEND;
- }
- else
- {
- status = STATUS_CSW;
- }
- }
-
- return RT_EOK;
-}
-
-#ifdef MASS_CBW_DUMP
-static void cbw_dump(struct ustorage_cbw* cbw)
-{
- RT_ASSERT(cbw != RT_NULL);
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("signature 0x%x\n", cbw->signature));
- RT_DEBUG_LOG(RT_DEBUG_USB, ("tag 0x%x\n", cbw->tag));
- RT_DEBUG_LOG(RT_DEBUG_USB, ("xfer_len 0x%x\n", cbw->xfer_len));
- RT_DEBUG_LOG(RT_DEBUG_USB, ("dflags 0x%x\n", cbw->dflags));
- RT_DEBUG_LOG(RT_DEBUG_USB, ("lun 0x%x\n", cbw->lun));
- RT_DEBUG_LOG(RT_DEBUG_USB, ("cb_len 0x%x\n", cbw->cb_len));
- RT_DEBUG_LOG(RT_DEBUG_USB, ("cb[0] 0x%x\n", cbw->cb[0]));
-}
-#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)
-{
- mass_eps_t eps;
- RT_ASSERT(device != RT_NULL);
-
- eps = (mass_eps_t)cls->eps;
- if(status == STATUS_CBW)
- {
- struct ustorage_cbw* cbw;
-
- /* dump cbw information */
- cbw = (struct ustorage_cbw*)eps->ep_out->buffer;
-
- if(cbw->signature == CBW_SIGNATURE)
- {
- csw.signature = CSW_SIGNATURE;
- csw.tag = cbw->tag;
- csw.data_reside = 0;
- csw.status = 0;
- }
- else
- return -RT_ERROR;
-
- switch(cbw->cb[0])
- {
- case SCSI_TEST_UNIT_READY:
- 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);
- break;
- case SCSI_REQUEST_SENSE:
- _request_sense(device, eps->ep_in);
- status = STATUS_CSW;
- break;
- case SCSI_INQUIRY_CMD:
- _inquiry_cmd(device, eps->ep_in);
- status = STATUS_CSW;
- break;
- case SCSI_MODE_SENSE_6:
- _mode_sense_6(device, eps->ep_in);
- status = STATUS_CSW;
- break;
- case SCSI_ALLOW_MEDIUM_REMOVAL:
- 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);
- 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);
- break;
- case SCSI_WRITE_10:
- _write_10(device, cbw, eps->ep_out);
- status = STATUS_RECEIVE;
- break;
- case SCSI_VERIFY_10:
- _verify_10(device);
- break;
- }
- }
- else if(status == STATUS_RECEIVE)
- {
- RT_DEBUG_LOG(RT_DEBUG_USB, ("write size 0x%x block 0x%x oount 0x%x\n",
- size, _block, _size));
-
- _size -= size;
- csw.data_reside -= size;
-
- rt_device_write(disk, _block, eps->ep_in->buffer, 1);
- _block ++;
- if(_size == 0)
- {
- 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;
- }
- else
- {
- dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer,
- geometry.bytes_per_sector);
- }
- }
- else
- {
- rt_kprintf("none cbw status\n");
- }
-
- return RT_EOK;
-}
-
-
-/**
- * This function will handle mass storage interface request.
- *
- * @param device the usb device 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)
-{
- rt_uint8_t lun = 0;
-
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(setup != RT_NULL);
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("_interface_handler\n"));
-
- switch(setup->request)
- {
- case USBREQ_GET_MAX_LUN:
- dcd_ep_write(device->dcd, 0, &lun, 1);
- break;
- case USBREQ_MASS_STORAGE_RESET:
- break;
- default:
- rt_kprintf("unknown interface request\n");
- break;
- }
-
- return RT_EOK;
-}
-
-/**
- * This function will run mass storage class, 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_run(udevice_t device, uclass_t cls)
-{
- mass_eps_t eps;
- rt_uint8_t *buffer;
- RT_ASSERT(device != RT_NULL);
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("mass storage run\n"));
- eps = (mass_eps_t)cls->eps;
-
- disk = rt_device_find(RT_USB_MSTORAGE_DISK_NAME);
- if(disk == RT_NULL)
- {
- rt_kprintf("no 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)
- 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);
-
- return RT_EOK;
-}
-
-/**
- * This function will stop mass storage class, 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)
-{
- mass_eps_t eps;
- RT_ASSERT(device != RT_NULL);
-
- 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;
-
- return RT_EOK;
-}
-
-static struct uclass_ops ops =
-{
- _class_run,
- _class_stop,
- RT_NULL,
-};
-
-/**
- * This function will create a mass storage class instance.
- *
- * @param device the usb device object.
- *
- * @return RT_EOK on successful.
- */
-uclass_t rt_usbd_class_mstorage_create(udevice_t device)
-{
- uintf_t intf;
- mass_eps_t eps;
- uclass_t mstorage;
- ualtsetting_t setting;
- umass_desc_t mass_desc;
-
- /* parameter check */
- RT_ASSERT(device != RT_NULL);
-
- /* 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 an interface */
- intf = rt_usbd_interface_create(device, _interface_handler);
-
- /* create an alternate setting */
- setting = rt_usbd_altsetting_create(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);
-
- /* 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);
-
- /* 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);
-
- return mstorage;
-}
-
-#endif
+/*
+ * File : mstorage.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2012, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * 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
+ */
+
+#include <rtthread.h>
+#include <rtservice.h>
+#include <rtdevice.h>
+#include "mstorage.h"
+
+#ifdef RT_USB_DEVICE_MSTORAGE
+
+#define STATUS_CBW 0x00
+#define STATUS_CSW 0x01
+#define STATUS_RECEIVE 0x02
+#define STATUS_SEND 0x03
+
+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 struct udevice_descriptor dev_desc =
+{
+ USB_DESC_LENGTH_DEVICE, //bLength;
+ USB_DESC_TYPE_DEVICE, //type;
+ USB_BCD_VERSION, //bcdUSB;
+ USB_CLASS_MASS_STORAGE, //bDeviceClass;
+ 0x00, //bDeviceSubClass;
+ 0x00, //bDeviceProtocol;
+ 0x40, //bMaxPacketSize0;
+ USB_VENDOR_ID, //idVendor;
+ USB_MASS_STORAGE_PRODUCT_ID,//idProduct;
+ USB_BCD_DEVICE, //bcdDevice;
+ USB_STRING_MANU_INDEX, //iManufacturer;
+ USB_STRING_PRODUCT_INDEX, //iProduct;
+ USB_STRING_SERIAL_INDEX, //iSerialNumber;
+ USB_DYNAMIC, //bNumConfigurations;
+};
+
+const static struct umass_descriptor _mass_desc =
+{
+ USB_DESC_LENGTH_INTERFACE, //bLength;
+ USB_DESC_TYPE_INTERFACE, //type;
+ USB_DYNAMIC, //bInterfaceNumber;
+ 0x00, //bAlternateSetting;
+ 0x02, //bNumEndpoints
+ USB_CLASS_MASS_STORAGE, //bInterfaceClass;
+ 0x06, //bInterfaceSubClass;
+ 0x50, //bInterfaceProtocol;
+ 0x00, //iInterface;
+
+ USB_DESC_LENGTH_ENDPOINT, //bLength;
+ USB_DESC_TYPE_ENDPOINT, //type;
+ USB_DYNAMIC | USB_DIR_OUT, //bEndpointAddress;
+ USB_EP_ATTR_BULK, //bmAttributes;
+ 0x40, //wMaxPacketSize;
+ 0x00, //bInterval;
+
+ USB_DESC_LENGTH_ENDPOINT, //bLength;
+ USB_DESC_TYPE_ENDPOINT, //type;
+ USB_DYNAMIC | USB_DIR_IN, //bEndpointAddress;
+ USB_EP_ATTR_BULK, //bmAttributes;
+ 0x40, //wMaxPacketSize;
+ 0x00, //bInterval;
+};
+
+/**
+ * This function will allocate an usb device instance from system.
+ *
+ * @param parent the hub instance to which the new allocated device attached.
+ * @param port the hub port.
+ *
+ * @return the allocate instance on successful, or RT_NULL on failure.
+ */
+static rt_err_t _inquiry_cmd(udevice_t device, uep_t ep_in)
+{
+ rt_uint8_t data[36];
+
+ *(rt_uint32_t*)&data[0] = 0x0 | (0x80 << 8);
+ *(rt_uint32_t*)&data[4] = 31;
+
+ rt_memset(&data[8], 0x20, 28);
+ rt_memcpy(&data[8], "RTT", 3);
+ rt_memcpy(&data[16], "USB Disk", 8);
+
+ dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 36);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle sense request.
+ *
+ * @param device the usb device object.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _request_sense(udevice_t device, uep_t ep_in)
+{
+ struct request_sense_data data;
+
+ data.ErrorCode = 0x70;
+ data.Valid = 0;
+ data.SenseKey = 5;
+ data.Information[0] = 0;
+ data.Information[1] = 0;
+ data.Information[2] = 0;
+ data.Information[3] = 0;
+ data.AdditionalSenseLength = 0x0b;
+ data.AdditionalSenseCode = 0x20;
+ data.AdditionalSenseCodeQualifier =0;
+
+ dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, sizeof(struct request_sense_data));
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle mode_sense_6 request.
+ *
+ * @param device the usb device object.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _mode_sense_6(udevice_t device, uep_t ep_in)
+{
+ rt_uint8_t data[4];
+
+ data[0]=3;
+ data[1]=0;
+ data[2]=0;
+ data[3]=0;
+
+ dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 4);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle read_capacities request.
+ *
+ * @param device the usb device object.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _read_capacities(udevice_t device, uep_t ep_in)
+{
+ rt_uint8_t data[12];
+ rt_uint32_t sector_count, sector_size;
+
+ RT_ASSERT(device != RT_NULL);
+
+ sector_count = geometry.sector_count;
+ sector_size = geometry.bytes_per_sector;
+
+ *(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;
+
+ dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 12);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle read_capacity request.
+ *
+ * @param device the usb device object.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _read_capacity(udevice_t device, uep_t ep_in)
+{
+ rt_uint8_t data[8];
+ rt_uint32_t sector_count, sector_size;
+
+ RT_ASSERT(device != RT_NULL);
+
+ sector_count = geometry.sector_count;
+ sector_size = geometry.bytes_per_sector;
+
+ 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;
+
+ dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 8);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle read_10 request.
+ *
+ * @param device the usb device 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)
+{
+ RT_ASSERT(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 ;
+
+ RT_ASSERT(_count < 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
+ {
+ status = STATUS_CSW;
+ }
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle write_10 request.
+ *
+ * @param device the usb device 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)
+{
+ RT_ASSERT(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;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_write_10 count 0x%x 0x%x\n",
+ _count, geometry.sector_count));
+
+ dcd_ep_read(device->dcd, ep_out, ep_out->buffer, geometry.bytes_per_sector);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle verify_10 request.
+ *
+ * @param device the usb device object.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _verify_10(udevice_t device)
+{
+ return RT_EOK;
+}
+
+/**
+ * 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)
+{
+ mass_eps_t eps;
+ RT_ASSERT(device != RT_NULL);
+
+ eps = cls->eps;
+ if(status == STATUS_CSW)
+ {
+ dcd_ep_write(device->dcd, eps->ep_in, (rt_uint8_t*)&csw, SIZEOF_CSW);
+ status = STATUS_CBW;
+ dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer, SIZEOF_CBW);
+ }
+ if(status == STATUS_SEND)
+ {
+ 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)
+ {
+ _block ++;
+ status = STATUS_SEND;
+ }
+ else
+ {
+ status = STATUS_CSW;
+ }
+ }
+
+ return RT_EOK;
+}
+
+#ifdef MASS_CBW_DUMP
+static void cbw_dump(struct ustorage_cbw* cbw)
+{
+ RT_ASSERT(cbw != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("signature 0x%x\n", cbw->signature));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("tag 0x%x\n", cbw->tag));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("xfer_len 0x%x\n", cbw->xfer_len));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("dflags 0x%x\n", cbw->dflags));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("lun 0x%x\n", cbw->lun));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("cb_len 0x%x\n", cbw->cb_len));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("cb[0] 0x%x\n", cbw->cb[0]));
+}
+#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)
+{
+ mass_eps_t eps;
+ RT_ASSERT(device != RT_NULL);
+
+ eps = (mass_eps_t)cls->eps;
+ if(status == STATUS_CBW)
+ {
+ struct ustorage_cbw* cbw;
+
+ /* dump cbw information */
+ cbw = (struct ustorage_cbw*)eps->ep_out->buffer;
+
+ if(cbw->signature == CBW_SIGNATURE)
+ {
+ csw.signature = CSW_SIGNATURE;
+ csw.tag = cbw->tag;
+ csw.data_reside = 0;
+ csw.status = 0;
+ }
+ else
+ return -RT_ERROR;
+
+ switch(cbw->cb[0])
+ {
+ case SCSI_TEST_UNIT_READY:
+ 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);
+ break;
+ case SCSI_REQUEST_SENSE:
+ _request_sense(device, eps->ep_in);
+ status = STATUS_CSW;
+ break;
+ case SCSI_INQUIRY_CMD:
+ _inquiry_cmd(device, eps->ep_in);
+ status = STATUS_CSW;
+ break;
+ case SCSI_MODE_SENSE_6:
+ _mode_sense_6(device, eps->ep_in);
+ status = STATUS_CSW;
+ break;
+ case SCSI_ALLOW_MEDIUM_REMOVAL:
+ 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);
+ 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);
+ break;
+ case SCSI_WRITE_10:
+ _write_10(device, cbw, eps->ep_out);
+ status = STATUS_RECEIVE;
+ break;
+ case SCSI_VERIFY_10:
+ _verify_10(device);
+ break;
+ }
+ }
+ else if(status == STATUS_RECEIVE)
+ {
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("write size 0x%x block 0x%x oount 0x%x\n",
+ size, _block, _size));
+
+ _size -= size;
+ csw.data_reside -= size;
+
+ rt_device_write(disk, _block, eps->ep_in->buffer, 1);
+ _block ++;
+ if(_size == 0)
+ {
+ 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;
+ }
+ else
+ {
+ dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer,
+ geometry.bytes_per_sector);
+ }
+ }
+ else
+ {
+ rt_kprintf("none cbw status\n");
+ }
+
+ return RT_EOK;
+}
+
+
+/**
+ * This function will handle mass storage interface request.
+ *
+ * @param device the usb device 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)
+{
+ rt_uint8_t lun = 0;
+
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(setup != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_interface_handler\n"));
+
+ switch(setup->request)
+ {
+ case USBREQ_GET_MAX_LUN:
+ dcd_ep_write(device->dcd, 0, &lun, 1);
+ break;
+ case USBREQ_MASS_STORAGE_RESET:
+ break;
+ default:
+ rt_kprintf("unknown interface request\n");
+ break;
+ }
+
+ return RT_EOK;
+}
+
+/**
+ * This function will run mass storage class, 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_run(udevice_t device, uclass_t cls)
+{
+ mass_eps_t eps;
+ rt_uint8_t *buffer;
+ RT_ASSERT(device != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("mass storage run\n"));
+ eps = (mass_eps_t)cls->eps;
+
+ disk = rt_device_find(RT_USB_MSTORAGE_DISK_NAME);
+ if(disk == RT_NULL)
+ {
+ rt_kprintf("no 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)
+ 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);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will stop mass storage class, 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)
+{
+ mass_eps_t eps;
+ RT_ASSERT(device != RT_NULL);
+
+ 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;
+
+ return RT_EOK;
+}
+
+static struct uclass_ops ops =
+{
+ _class_run,
+ _class_stop,
+ RT_NULL,
+};
+
+/**
+ * This function will create a mass storage class instance.
+ *
+ * @param device the usb device object.
+ *
+ * @return RT_EOK on successful.
+ */
+uclass_t rt_usbd_class_mstorage_create(udevice_t device)
+{
+ uintf_t intf;
+ mass_eps_t eps;
+ uclass_t mstorage;
+ ualtsetting_t setting;
+ umass_desc_t mass_desc;
+
+ /* parameter check */
+ RT_ASSERT(device != RT_NULL);
+
+ /* 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 an interface */
+ intf = rt_usbd_interface_create(device, _interface_handler);
+
+ /* create an alternate setting */
+ setting = rt_usbd_altsetting_create(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);
+
+ /* 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);
+
+ /* 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);
+
+ return mstorage;
+}
+
+#endif
diff --git a/components/drivers/usb/usbdevice/class/mstorage.h b/components/drivers/usb/usbdevice/class/mstorage.h
index b25b8b0a4b..740d9e6568 100644
--- a/components/drivers/usb/usbdevice/class/mstorage.h
+++ b/components/drivers/usb/usbdevice/class/mstorage.h
@@ -1,66 +1,66 @@
-/*
- * File : mstorage.h
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2012, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2012-10-01 Yi Qiu first version
- * 2012-12-12 heyuanjie87 add MASS endpoints collection
- */
-
-#ifndef __MSTORAGE_H__
-#define __MSTORAGE_H__
-
-#include <rtthread.h>
-
-#define USBREQ_GET_MAX_LUN 0xfe
-#define USBREQ_MASS_STORAGE_RESET 0xff
-
-#define USB_MASS_STORAGE_PRODUCT_ID 0x1000 /* Product ID */
-
-#pragma pack(1)
-
-struct umass_descriptor
-{
- struct uinterface_descriptor intf_desc;
- struct uendpoint_descriptor ep_out_desc;
- struct uendpoint_descriptor ep_in_desc;
-};
-typedef struct umass_descriptor* umass_desc_t;
-
-struct capacity_data
-{
- rt_uint8_t LastLogicalBlockAddress[4];
- rt_uint8_t BlockLengthInBytes[4];
-};
-
-struct request_sense_data
-{
- rt_uint8_t ErrorCode:7;
- rt_uint8_t Valid:1;
- rt_uint8_t Reserved1;
- rt_uint8_t SenseKey:4;
- rt_uint8_t Reserved2:4;
- rt_uint8_t Information[4];
- rt_uint8_t AdditionalSenseLength;
- rt_uint8_t Reserved3[4];
- rt_uint8_t AdditionalSenseCode;
- rt_uint8_t AdditionalSenseCodeQualifier;
- 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
+/*
+ * File : mstorage.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2012, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2012-10-01 Yi Qiu first version
+ * 2012-12-12 heyuanjie87 add MASS endpoints collection
+ */
+
+#ifndef __MSTORAGE_H__
+#define __MSTORAGE_H__
+
+#include <rtthread.h>
+
+#define USBREQ_GET_MAX_LUN 0xfe
+#define USBREQ_MASS_STORAGE_RESET 0xff
+
+#define USB_MASS_STORAGE_PRODUCT_ID 0x1000 /* Product ID */
+
+#pragma pack(1)
+
+struct umass_descriptor
+{
+ struct uinterface_descriptor intf_desc;
+ struct uendpoint_descriptor ep_out_desc;
+ struct uendpoint_descriptor ep_in_desc;
+};
+typedef struct umass_descriptor* umass_desc_t;
+
+struct capacity_data
+{
+ rt_uint8_t LastLogicalBlockAddress[4];
+ rt_uint8_t BlockLengthInBytes[4];
+};
+
+struct request_sense_data
+{
+ rt_uint8_t ErrorCode:7;
+ rt_uint8_t Valid:1;
+ rt_uint8_t Reserved1;
+ rt_uint8_t SenseKey:4;
+ rt_uint8_t Reserved2:4;
+ rt_uint8_t Information[4];
+ rt_uint8_t AdditionalSenseLength;
+ rt_uint8_t Reserved3[4];
+ rt_uint8_t AdditionalSenseCode;
+ rt_uint8_t AdditionalSenseCodeQualifier;
+ 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 192cbe70bf..a4d729cb65 100644
--- a/components/drivers/usb/usbdevice/core/core.c
+++ b/components/drivers/usb/usbdevice/core/core.c
@@ -1,1321 +1,1321 @@
-/*
- * File : core.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2012, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2012-10-01 Yi Qiu first version
- * 2012-12-12 heyuanjie87 change endpoint and class handler
- * 2012-12-30 heyuanjie87 change inferface handler
- */
-
-#include <rtthread.h>
-#include <rtdevice.h>
-
-static rt_list_t device_list;
-
-/**
- * This function will handle get_device_descriptor request.
- *
- * @param device the usb device object.
- * @param setup the setup request.
- *
- * @return RT_EOK on successful.
- */
-static rt_err_t _get_device_descriptor(struct udevice* device, ureq_t setup)
-{
- rt_size_t size;
-
- /* parameter check */
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(setup != RT_NULL);
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_device_descriptor\n"));
-
- /* device descriptor length should less than USB_DESC_LENGTH_DEVICE*/
- size = (setup->length > USB_DESC_LENGTH_DEVICE) ?
- 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);
-
- return RT_EOK;
-}
-
-/**
- * This function will handle get_config_descriptor request.
- *
- * @param device the usb device object.
- * @param setup the setup request.
- *
- * @return RT_EOK on successful.
- */
-static rt_err_t _get_config_descriptor(struct udevice* device, ureq_t setup)
-{
- rt_size_t size;
- ucfg_desc_t cfg_desc;
-
- /* parameter check */
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(setup != RT_NULL);
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_config_descriptor\n"));
-
- cfg_desc = &device->curr_cfg->cfg_desc;
- size = (setup->length > cfg_desc->wTotalLength) ?
- cfg_desc->wTotalLength : setup->length;
-
- /* send configuration descriptor to endpoint 0 */
- dcd_ep_write(device->dcd, 0, (rt_uint8_t*)cfg_desc, size);
-
- return RT_EOK;
-}
-
-/**
- * This function will handle get_string_descriptor 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 _get_string_descriptor(struct udevice* device, ureq_t setup)
-{
- struct ustring_descriptor str_desc;
- rt_uint8_t index, i;
- rt_uint32_t len;
-
- /* parameter check */
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(setup != RT_NULL);
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_string_descriptor\n"));
-
- str_desc.type = USB_DESC_TYPE_STRING;
- index = setup->value & 0xFF;
-
- if(index > USB_STRING_INTERFACE_INDEX)
- {
- rt_kprintf("unknown string index\n");
- dcd_ep_stall(device->dcd, 0);
- return -RT_ERROR;
- }
- if(index == 0)
- {
- str_desc.bLength = 4;
- str_desc.String[0] = 0x09;
- str_desc.String[1] = 0x04;
- }
- else
- {
- len = rt_strlen(device->str[index]);
- str_desc.bLength = len*2 + 2;
-
- for(i=0; i<len; i++)
- {
- str_desc.String[i*2] = device->str[index][i];
- str_desc.String[i*2 + 1] = 0;
- }
- }
-
- if(setup->length == 0xFF)
- len = str_desc.bLength;
- else
- len = setup->length;
-
- /* send string descriptor to endpoint 0 */
- dcd_ep_write(device->dcd, 0, (rt_uint8_t*)&str_desc, len);
-
- return RT_EOK;
-}
-
-/**
- * This function will handle get_descriptor request.
- *
- * @param device the usb device object.
- * @param setup the setup request.
- *
- * @return RT_EOK on successful.
- */
-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)
- {
- switch(setup->value >> 8)
- {
- case USB_DESC_TYPE_DEVICE:
- _get_device_descriptor(device, setup);
- break;
- case USB_DESC_TYPE_CONFIGURATION:
- _get_config_descriptor(device, setup);
- break;
- case USB_DESC_TYPE_STRING:
- _get_string_descriptor(device, setup);
- break;
- case USB_DESC_TYPE_DEVICEQUALIFIER:
- dcd_ep_stall(device->dcd, 0);
- break;
- default:
- rt_kprintf("unsupported descriptor request\n");
- dcd_ep_stall(device->dcd, 0);
- break;
- }
- }
- else
- {
- rt_kprintf("request direction error\n");
- dcd_ep_stall(device->dcd, 0);
- }
-
- return RT_EOK;
-}
-
-/**
- * This function will handle get_interface request.
- *
- * @param device the usb device object.
- * @param setup the setup request.
- *
- * @return RT_EOK on successful.
- */
-static rt_err_t _get_interface(struct udevice* device, ureq_t setup)
-{
- rt_uint8_t value;
- uintf_t intf;
-
- /* parameter check */
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(setup != RT_NULL);
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_interface\n"));
-
- /* find the specified interface and its alternate setting */
- intf = rt_usbd_find_interface(device, setup->index & 0xFF, RT_NULL);
- value = intf->curr_setting->intf_desc->bAlternateSetting;
-
- /* send the interface alternate setting to endpoint 0*/
- dcd_ep_write(device->dcd, 0, &value, 1);
-
- return RT_EOK;
-}
-
-/**
- * This function will handle set_interface request.
- *
- * @param device the usb device object.
- * @param setup the setup request.
- *
- * @return RT_EOK on successful.
- */
-static rt_err_t _set_interface(struct udevice* device, ureq_t setup)
-{
- uintf_t intf;
- uep_t ep;
- struct rt_list_node* i;
- ualtsetting_t setting;
-
- /* parameter check */
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(setup != RT_NULL);
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("_set_interface\n"));
-
- /* find the specified interface */
- intf = rt_usbd_find_interface(device, setup->index & 0xFF, RT_NULL);
-
- /* set alternate setting to the interface */
- rt_usbd_set_altsetting(intf, setup->value & 0xFF);
- 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)
- {
- ep = (uep_t)rt_list_entry(i, struct uendpoint, list);
- dcd_ep_stop(device->dcd, ep);
- dcd_ep_run(device->dcd, ep);
- }
-
- return RT_EOK;
-}
-
-/**
- * This function will handle get_config request.
- *
- * @param device the usb device object.
- * @param setup the setup request.
- *
- * @return RT_EOK on successful.
- */
-static rt_err_t _get_config(struct udevice* device, ureq_t setup)
-{
- rt_uint8_t value;
-
- /* parameter check */
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(setup != RT_NULL);
- RT_ASSERT(device->curr_cfg != RT_NULL);
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_config\n"));
-
- /* get current configuration */
- value = device->curr_cfg->cfg_desc.bConfigurationValue;
-
- /* write the current configuration to endpoint 0 */
- dcd_ep_write(device->dcd, 0, &value, 1);
-
- return RT_EOK;
-}
-
-/**
- * This function will handle set_config request.
- *
- * @param device the usb device object.
- * @param setup the setup request.
- *
- * @return RT_EOK on successful.
- */
-static rt_err_t _set_config(struct udevice* device, ureq_t setup)
-{
- struct rt_list_node *i, *j, *k;
- uconfig_t cfg;
- uintf_t intf;
- ualtsetting_t setting;
- uep_t ep;
-
- /* parameter check */
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(setup != RT_NULL);
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("_set_config\n"));
-
- /* set current configuration */
- rt_usbd_set_config(device, setup->value);
- cfg = device->curr_cfg;
-
- for (i=cfg->cls_list.next; i!=&cfg->cls_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)
- {
- 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)
- {
- 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);
- }
- }
- /* after running all endpoints, then run class */
- if(cls->ops->run != RT_NULL)
- cls->ops->run(device, cls);
- }
-
- /* issue status stage */
- rt_device_control((rt_device_t)device->dcd, CONTROL_SEND_STATUS, RT_NULL);
-
- return RT_EOK;
-}
-
-/**
- * This function will handle set_address request.
- *
- * @param device the usb device object.
- * @param setup the setup request.
- *
- * @return RT_EOK on successful.
- */
-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"));
-
- /* set address in device control driver */
- dcd_set_address(device->dcd, setup->value);
-
- /* issue status stage */
- rt_device_control((rt_device_t)device->dcd, CONTROL_SEND_STATUS, RT_NULL);
-
- return RT_EOK;
-}
-
-/**
- * This function will handle standard request.
- *
- * @param device the usb device object.
- * @param setup the setup request.
- *
- * @return RT_EOK on successful.
- */
-static rt_err_t _standard_request(struct udevice* device, ureq_t setup)
-{
- udcd_t dcd;
- rt_uint16_t value = 0;
-
- /* parameter check */
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(setup != RT_NULL);
-
- dcd = device->dcd;
-
- switch(setup->request_type & USB_REQ_TYPE_RECIPIENT_MASK)
- {
- case USB_REQ_TYPE_DEVICE:
- switch(setup->request)
- {
- case USB_REQ_GET_STATUS:
- dcd_ep_write(device->dcd, 0, &value, 2);
- break;
- case USB_REQ_CLEAR_FEATURE:
- dcd_clear_feature(dcd, setup->value);
- break;
- case USB_REQ_SET_FEATURE:
- dcd_set_feature(dcd, setup->value);
- break;
- case USB_REQ_SET_ADDRESS:
- _set_address(device, setup);
- break;
- case USB_REQ_GET_DESCRIPTOR:
- _get_descriptor(device, setup);
- break;
- case USB_REQ_SET_DESCRIPTOR:
- dcd_ep_stall(dcd, 0);
- break;
- case USB_REQ_GET_CONFIGURATION:
- _get_config(device, setup);
- break;
- case USB_REQ_SET_CONFIGURATION:
- _set_config(device, setup);
- break;
- default:
- rt_kprintf("unknown device request\n");
- dcd_ep_stall(device->dcd, 0);
- break;
- }
- break;
- case USB_REQ_TYPE_INTERFACE:
- switch(setup->request)
- {
- case USB_REQ_GET_INTERFACE:
- _get_interface(device, setup);
- break;
- case USB_REQ_SET_INTERFACE:
- _set_interface(device, setup);
- break;
- default:
- rt_kprintf("unknown interface request\n");
- dcd_ep_stall(device->dcd, 0);
- break;
- }
- break;
- case USB_REQ_TYPE_ENDPOINT:
- switch(setup->request)
- {
- case USB_REQ_GET_STATUS:
- /* TODO */
- dcd_ep_write(dcd, 0, &value, 2);
- break;
- case USB_REQ_CLEAR_FEATURE:
- dcd_clear_feature(dcd, setup->value);
- break;
- case USB_REQ_SET_FEATURE:
- dcd_set_feature(dcd, setup->value);
- break;
- case USB_REQ_SYNCH_FRAME:
- break;
- default:
- rt_kprintf("unknown endpoint request\n");
- dcd_ep_stall(device->dcd, 0);
- break;
- }
- break;
- case USB_REQ_TYPE_OTHER:
- rt_kprintf("unknown other type request\n");
- dcd_ep_stall(device->dcd, 0);
- break;
- default:
- rt_kprintf("unknown type request\n");
- dcd_ep_stall(device->dcd, 0);
- break;
- }
-
- return RT_EOK;
-}
-
-/**
- * This function will handle class 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)
-{
- uintf_t intf;
- uclass_t cls;
-
- /* parameter check */
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(setup != RT_NULL);
-
- /* verify request value */
- if(setup->index > device->curr_cfg->cfg_desc.bNumInterfaces)
- {
- dcd_ep_stall(device->dcd, 0);
- return -RT_ERROR;
- }
-
- 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);
- break;
- case USB_REQ_TYPE_ENDPOINT:
- break;
- default:
- rt_kprintf("unknown class request type\n");
- dcd_ep_stall(device->dcd, 0);
- break;
- }
-
- return RT_EOK;
-}
-
-/**
- * This function will handle setup 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 _setup_request(udevice_t device, ureq_t setup)
-{
- /* parameter check */
- 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"));
-
- 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);
- 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);
- return -RT_ERROR;
- }
-
- return RT_EOK;
-}
-
-/**
- * This function will notity sof event to all of class.
- *
- * @param device the usb device object.
- *
- * @return RT_EOK.
- */
-rt_err_t _sof_notify(udevice_t device)
-{
- struct rt_list_node *i;
- uclass_t cls;
-
- RT_ASSERT(device != RT_NULL);
-
- /* to notity every class that sof event comes */
- for (i=device->curr_cfg->cls_list.next;
- i!=&device->curr_cfg->cls_list; i=i->next)
- {
- cls = (uclass_t)rt_list_entry(i, struct uclass, list);
- if(cls->ops->sof_handler != RT_NULL)
- cls->ops->sof_handler(device, cls);
- }
-
- return RT_EOK;
-}
-
-/**
- * This function will create an usb device object.
- *
- * @param ustring the usb string array to contain string descriptor.
- *
- * @return an usb device object on success, RT_NULL on fail.
- */
-udevice_t rt_usbd_device_create(const char** ustring)
-{
- udevice_t udevice;
-
- /* parameter check */
- RT_ASSERT(ustring != RT_NULL);
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_device_create\n"));
-
- /* allocate memory for the object */
- udevice = rt_malloc(sizeof(struct udevice));
- if(udevice == RT_NULL)
- {
- rt_kprintf("alloc memery failed\n");
- return RT_NULL;
- }
- rt_memset(udevice, 0, sizeof(struct udevice));
-
- /* set string descriptor array to the device object */
- udevice->str = ustring;
-
- /* to initialize configuration list */
- rt_list_init(&udevice->cfg_list);
-
- /* insert the device object to device list */
- rt_list_insert_after(&device_list, &udevice->list);
-
- return udevice;
-}
-
-/**
- * This function will set an usb controller driver to a device.
- *
- * @param device the usb device object.
- * @param dcd the usb device controller driver.
- *
- * @return RT_EOK on successful.
- */
-rt_err_t rt_usbd_device_set_controller(udevice_t device, udcd_t dcd)
-{
- /* parameter check */
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(dcd != RT_NULL);
-
- /* set usb device controller driver to the device */
- device->dcd = dcd;
-
- return RT_EOK;
-}
-
-/**
- * This function will set an usb device descriptor to a device.
- *
- * @param device the usb device object.
- * @param dev_desc the usb device descriptor.
- *
- * @return RT_EOK on successful.
- */
-rt_err_t rt_usbd_device_set_descriptor(udevice_t device, udev_desc_t dev_desc)
-{
- /* parameter check */
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(dev_desc != RT_NULL);
-
- /* copy the usb device descriptor to the device */
- rt_memcpy((void *)&device->dev_desc, (void *)dev_desc, USB_DESC_LENGTH_DEVICE);
-
- return RT_EOK;
-}
-
-/**
- * This function will create an usb configuration object.
- *
- * @param none.
- *
- * @return an usb configuration object.
- */
-uconfig_t rt_usbd_config_create(void)
-{
- uconfig_t cfg;
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_config_create\n"));
-
- /* allocate memory for the object */
- cfg = rt_malloc(sizeof(struct uconfig));
- 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.wTotalLength = USB_DESC_LENGTH_CONFIG;
- cfg->cfg_desc.bmAttributes = 0xC0;
- cfg->cfg_desc.MaxPower = 0x32;
-
- /* to initialize class object list */
- rt_list_init(&cfg->cls_list);
-
- return cfg;
-}
-
-/**
- * This function will create an usb interface object.
- *
- * @param device the usb device object.
- * @handler the callback handler of object
- *
- * @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 intf;
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_interface_create\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)
- {
- rt_kprintf("alloc memery failed\n");
- return RT_NULL;
- }
- intf->intf_num = device->nr_intf;
- device->nr_intf++;
- intf->handler = handler;
- intf->curr_setting = RT_NULL;
-
- /* to initialize the alternate setting object list */
- rt_list_init(&intf->setting_list);
-
- return intf;
-}
-
-/**
- * This function will create an usb alternate setting object.
- *
- * @param intf_desc the interface descriptor.
- * @desc_size the size of the interface descriptor.
- *
- * @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 setting;
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_altsetting_create\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)
- {
- rt_kprintf("alloc memery failed\n");
- return RT_NULL;
- }
- /* allocate memory for the desc */
- setting->desc = rt_malloc(desc_size);
- if (setting->desc == RT_NULL)
- {
- rt_kprintf("alloc desc memery failed\n");
- rt_free(setting);
- return RT_NULL;
- }
-
- setting->desc_size = desc_size;
- setting->intf_desc = RT_NULL;
-
- /* to initialize endpoint list */
- rt_list_init(&setting->ep_list);
-
- return setting;
-}
-
-/**
- * This function will config an desc in alternate setting object.
- *
- * @param setting the altsetting to be config.
- * @param desc use it to init desc in setting.
- * @param intf_pos the offset of interface descriptor in desc.
- *
- * @return RT_EOK.
- */
-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);
-
- return RT_EOK;
-}
-
-/**
- * This function will create an usb class 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.
- */
-uclass_t rt_usbd_class_create(udevice_t device, udev_desc_t dev_desc,
- uclass_ops_t ops)
-{
- uclass_t cls;
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_class_create\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)
- {
- rt_kprintf("alloc memery failed\n");
- return RT_NULL;
- }
- cls->dev_desc = dev_desc;
- cls->ops = ops;
- cls->device = device;
-
- /* to initialize interface list */
- rt_list_init(&cls->intf_list);
-
- return cls;
-}
-
-/**
- * This function will create an usb endpoint object.
- *
- * @param ep_desc the endpoint descriptor.
- * @handler the callback handler of object
- *
- * @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 ep;
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_endpoint_create\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)
- {
- rt_kprintf("alloc memery failed\n");
- return RT_NULL;
- }
- ep->ep_desc = ep_desc;
- ep->handler = handler;
- ep->buffer = RT_NULL;
-
- return ep;
-}
-
-/**
- * This function will find an usb device object.
- *
- * @dcd usd device controller driver.
- *
- * @return an usb device object on found or RT_NULL on not found.
- */
-udevice_t rt_usbd_find_device(udcd_t dcd)
-{
- struct rt_list_node* node;
- udevice_t device;
-
- /* parameter check */
- RT_ASSERT(dcd != RT_NULL);
-
- /* search a device in the the device list */
- 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;
- }
-
- rt_kprintf("can't find device\n");
- return RT_NULL;
-}
-
-/**
- * This function will find an usb configuration object.
- *
- * @param device the usb device object.
- * @param value the configuration number.
- *
- * @return an usb configuration object on found or RT_NULL on not found.
- */
-uconfig_t rt_usbd_find_config(udevice_t device, rt_uint8_t value)
-{
- struct rt_list_node* node;
- uconfig_t cfg = RT_NULL;
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_find_config\n"));
-
- /* parameter check */
- RT_ASSERT(device != RT_NULL);
- 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)
- {
- cfg = (uconfig_t)rt_list_entry(node, struct udevice, list);
- if(cfg->cfg_desc.bConfigurationValue == value) return cfg;
- }
-
- rt_kprintf("can't find configuration %d\n", value);
- return RT_NULL;
-}
-
-/**
- * This function will find an usb interface object.
- *
- * @param device the usb device object.
- * @param value the interface number.
- *
- * @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)
-{
- struct rt_list_node *i, *j;
- uclass_t cls;
- uintf_t intf;
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_find_interface\n"));
-
- /* parameter check */
- RT_ASSERT(device != RT_NULL);
- 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)
- {
- cls = (uclass_t)rt_list_entry(i, struct uclass, list);
- for(j=cls->intf_list.next; j!=&cls->intf_list; j=j->next)
- {
- intf = (uintf_t)rt_list_entry(j, struct uinterface, list);
- if(intf->intf_num == value)
- {
- if (pcls != RT_NULL)
- *pcls = cls;
- return intf;
- }
- }
- }
-
- rt_kprintf("can't find interface %d\n", value);
- return RT_NULL;
-}
-
-/**
- * This function will find an usb interface alternate setting object.
- *
- * @param device the usb device object.
- * @param value the alternate setting number.
- *
- * @return an usb interface alternate setting object on found or RT_NULL on not found.
- */
-ualtsetting_t rt_usbd_find_altsetting(uintf_t intf, rt_uint8_t value)
-{
- struct rt_list_node *i;
- ualtsetting_t setting;
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_find_altsetting\n"));
-
- /* parameter check */
- RT_ASSERT(intf != 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)
- 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)
- {
- setting =(ualtsetting_t)rt_list_entry(i, struct ualtsetting, list);
- if(setting->intf_desc->bAlternateSetting == value)
- return setting;
- }
-
- rt_kprintf("can't find alternate setting %d\n", value);
- return RT_NULL;
-}
-
-/**
- * This function will find an usb endpoint object.
- *
- * @param device the usb device object.
- * @param ep_addr endpoint address.
- *
- * @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 ep;
- struct rt_list_node *i, *j, *k;
- uclass_t cls;
- 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)
- {
- cls = (uclass_t)rt_list_entry(i, struct uclass, list);
- for(j=cls->intf_list.next; j!=&cls->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)
- {
- ep = (uep_t)rt_list_entry(k, struct uendpoint, list);
- if(ep->ep_desc->bEndpointAddress == ep_addr)
- {
- if (pcls != RT_NULL)
- *pcls = cls;
- return ep;
- }
- }
- }
- }
-
- rt_kprintf("can't find endpoint 0x%x\n", ep_addr);
- return RT_NULL;
-}
-
-/**
- * This function will add a configuration to an usb device.
- *
- * @param device the usb device object.
- * @param cfg the configuration object.
- *
- * @return RT_EOK.
- */
-rt_err_t rt_usbd_device_add_config(udevice_t device, uconfig_t cfg)
-{
- struct rt_list_node *i, *j, *k;
- uclass_t cls;
- uintf_t intf;
- uep_t ep;
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_device_add_config\n"));
-
- /* parameter check */
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(cfg != RT_NULL);
-
- /* set configuration number to the configuration descriptor */
- 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)
- {
- cls = (uclass_t)rt_list_entry(i, struct uclass, list);
-
- for(j=cls->intf_list.next; j!=&cls->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)
- {
- ep = (uep_t)rt_list_entry(k, struct uendpoint, list);
- dcd_ep_alloc(device->dcd, ep);
- }
-
- /* 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);
- cfg->cfg_desc.wTotalLength += intf->curr_setting->desc_size;
- }
- }
-
- /* insert the configuration to the list */
- rt_list_insert_after(&device->cfg_list, &cfg->list);
-
- return RT_EOK;
-}
-
-/**
- * This function will add a class to a configuration.
- *
- * @param cfg the configuration object.
- * @param cls the class object.
- *
- * @return RT_EOK.
- */
-rt_err_t rt_usbd_config_add_class(uconfig_t cfg, uclass_t cls)
-{
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_config_add_class\n"));
-
- /* parameter check */
- RT_ASSERT(cfg != RT_NULL);
- RT_ASSERT(cls != RT_NULL);
-
- /* insert the class to the list */
- rt_list_insert_after(&cfg->cls_list, &cls->list);
-
- return RT_EOK;
-}
-
-/**
- * This function will add an interface to a class.
- *
- * @param cls the class object.
- * @param intf the interface object.
- *
- * @return RT_EOK.
- */
-rt_err_t rt_usbd_class_add_interface(uclass_t cls, uintf_t intf)
-{
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_class_add_interface\n"));
-
- /* parameter check */
- RT_ASSERT(cls != RT_NULL);
- RT_ASSERT(intf != RT_NULL);
-
- /* insert the interface to the list */
- rt_list_insert_after(&cls->intf_list, &intf->list);
-
- return RT_EOK;
-}
-
-/**
- * This function will add an alternate setting to an interface.
- *
- * @param intf the interface object.
- * @param setting the alternate setting object.
- *
- * @return RT_EOK.
- */
-rt_err_t rt_usbd_interface_add_altsetting(uintf_t intf, ualtsetting_t setting)
-{
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_interface_add_altsetting\n"));
-
- /* parameter check */
- RT_ASSERT(intf != RT_NULL);
- RT_ASSERT(setting != RT_NULL);
-
- setting->intf_desc->bInterfaceNumber = intf->intf_num;
-
- /* insert the alternate setting to the list */
- rt_list_insert_after(&intf->setting_list, &setting->list);
-
- return RT_EOK;
-}
-
-/**
- * This function will add an endpoint to an alternate setting.
- *
- * @param setting the alternate setting object.
- * @param ep the endpoint object.
- *
- * @return RT_EOK.
- */
-rt_err_t rt_usbd_altsetting_add_endpoint(ualtsetting_t setting, uep_t ep)
-{
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_altsetting_add_endpoint\n"));
-
- /* parameter check */
- RT_ASSERT(setting != RT_NULL);
- RT_ASSERT(ep != RT_NULL);
-
- /* insert the endpoint to the list */
- rt_list_insert_after(&setting->ep_list, &ep->list);
-
- return RT_EOK;
-}
-
-/**
- * This function will set an alternate setting for an interface.
- *
- * @param intf_desc the interface descriptor.
- * @param value the alternate setting number.
- *
- * @return RT_EOK.
- */
-rt_err_t rt_usbd_set_altsetting(uintf_t intf, rt_uint8_t value)
-{
- ualtsetting_t setting;
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_set_altsetting\n"));
-
- /* parameter check */
- RT_ASSERT(intf != RT_NULL);
- RT_ASSERT(setting != RT_NULL);
-
- /* find an alternate setting */
- setting = rt_usbd_find_altsetting(intf, value);
-
- /* set as current alternate setting */
- intf->curr_setting = setting;
-
- return RT_EOK;
-}
-
-/**
- * This function will set a configuration for an usb device.
- *
- * @param device the usb device object.
- * @param value the configuration number.
- *
- * @return RT_EOK.
- */
-rt_err_t rt_usbd_set_config(udevice_t device, rt_uint8_t value)
-{
- uconfig_t cfg;
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_set_config\n"));
-
- /* parameter check */
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(value <= device->dev_desc.bNumConfigurations);
-
- /* find a configuration */
- cfg = rt_usbd_find_config(device, value);
-
- /* set as current configuration */
- device->curr_cfg = cfg;
-
- return RT_TRUE;
-}
-
-static struct rt_messagequeue *usb_mq;
-
-/**
- * This function is the main entry of usb device thread, it is in charge of
- * processing all messages received from the usb message buffer.
- *
- * @param parameter the parameter of the usb device thread.
- *
- * @return none.
- */
-static void rt_usbd_thread_entry(void* parameter)
-{
- 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 ) continue;
-
- switch (msg.type)
- {
- case USB_MSG_SETUP_NOTIFY:
- device = rt_usbd_find_device(msg.dcd);
- if(device != RT_NULL)
- _setup_request(device, (ureq_t)msg.content.setup_msg.packet);
- else
- rt_kprintf("invalid usb device\n");
- break;
- case USB_MSG_DATA_NOTIFY:
- 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");
- break;
- case USB_MSG_SOF:
- device = rt_usbd_find_device(msg.dcd);
- if(device != RT_NULL)
- _sof_notify(device);
- else
- rt_kprintf("invalid usb device\n");
- break;
- default:
- break;
- }
- }
-}
-
-/**
- * This function will post an message to usb message queue,
- *
- * @param msg the message to be posted
- * @param size the size of the message .
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usbd_post_event(struct udev_msg* msg, rt_size_t size)
-{
- RT_ASSERT(msg != RT_NULL);
-
- /* send message to usb message queue */
- return rt_mq_send(usb_mq, (void*)msg, size);
-}
-
-/**
- * This function will initialize usb device thread.
- *
- * @return none.
- *
- */
-rt_err_t rt_usbd_core_init(void)
-{
- rt_thread_t thread;
-
- rt_list_init(&device_list);
-
- /* create an usb message queue */
- usb_mq = rt_mq_create("usbd", 32, 16, RT_IPC_FLAG_FIFO);
-
- /* create usb device thread */
- thread = rt_thread_create("usbd", rt_usbd_thread_entry, RT_NULL,
- 2048, 8, 20);
- if(thread != RT_NULL)
- {
- /* startup usb device thread */
- rt_thread_startup(thread);
- }
-
- return RT_EOK;
-}
-
+/*
+ * File : core.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2012, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2012-10-01 Yi Qiu first version
+ * 2012-12-12 heyuanjie87 change endpoint and class handler
+ * 2012-12-30 heyuanjie87 change inferface handler
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+static rt_list_t device_list;
+
+/**
+ * This function will handle get_device_descriptor request.
+ *
+ * @param device the usb device object.
+ * @param setup the setup request.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _get_device_descriptor(struct udevice* device, ureq_t setup)
+{
+ rt_size_t size;
+
+ /* parameter check */
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(setup != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_device_descriptor\n"));
+
+ /* device descriptor length should less than USB_DESC_LENGTH_DEVICE*/
+ size = (setup->length > USB_DESC_LENGTH_DEVICE) ?
+ 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);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle get_config_descriptor request.
+ *
+ * @param device the usb device object.
+ * @param setup the setup request.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _get_config_descriptor(struct udevice* device, ureq_t setup)
+{
+ rt_size_t size;
+ ucfg_desc_t cfg_desc;
+
+ /* parameter check */
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(setup != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_config_descriptor\n"));
+
+ cfg_desc = &device->curr_cfg->cfg_desc;
+ size = (setup->length > cfg_desc->wTotalLength) ?
+ cfg_desc->wTotalLength : setup->length;
+
+ /* send configuration descriptor to endpoint 0 */
+ dcd_ep_write(device->dcd, 0, (rt_uint8_t*)cfg_desc, size);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle get_string_descriptor 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 _get_string_descriptor(struct udevice* device, ureq_t setup)
+{
+ struct ustring_descriptor str_desc;
+ rt_uint8_t index, i;
+ rt_uint32_t len;
+
+ /* parameter check */
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(setup != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_string_descriptor\n"));
+
+ str_desc.type = USB_DESC_TYPE_STRING;
+ index = setup->value & 0xFF;
+
+ if(index > USB_STRING_INTERFACE_INDEX)
+ {
+ rt_kprintf("unknown string index\n");
+ dcd_ep_stall(device->dcd, 0);
+ return -RT_ERROR;
+ }
+ if(index == 0)
+ {
+ str_desc.bLength = 4;
+ str_desc.String[0] = 0x09;
+ str_desc.String[1] = 0x04;
+ }
+ else
+ {
+ len = rt_strlen(device->str[index]);
+ str_desc.bLength = len*2 + 2;
+
+ for(i=0; i<len; i++)
+ {
+ str_desc.String[i*2] = device->str[index][i];
+ str_desc.String[i*2 + 1] = 0;
+ }
+ }
+
+ if(setup->length == 0xFF)
+ len = str_desc.bLength;
+ else
+ len = setup->length;
+
+ /* send string descriptor to endpoint 0 */
+ dcd_ep_write(device->dcd, 0, (rt_uint8_t*)&str_desc, len);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle get_descriptor request.
+ *
+ * @param device the usb device object.
+ * @param setup the setup request.
+ *
+ * @return RT_EOK on successful.
+ */
+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)
+ {
+ switch(setup->value >> 8)
+ {
+ case USB_DESC_TYPE_DEVICE:
+ _get_device_descriptor(device, setup);
+ break;
+ case USB_DESC_TYPE_CONFIGURATION:
+ _get_config_descriptor(device, setup);
+ break;
+ case USB_DESC_TYPE_STRING:
+ _get_string_descriptor(device, setup);
+ break;
+ case USB_DESC_TYPE_DEVICEQUALIFIER:
+ dcd_ep_stall(device->dcd, 0);
+ break;
+ default:
+ rt_kprintf("unsupported descriptor request\n");
+ dcd_ep_stall(device->dcd, 0);
+ break;
+ }
+ }
+ else
+ {
+ rt_kprintf("request direction error\n");
+ dcd_ep_stall(device->dcd, 0);
+ }
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle get_interface request.
+ *
+ * @param device the usb device object.
+ * @param setup the setup request.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _get_interface(struct udevice* device, ureq_t setup)
+{
+ rt_uint8_t value;
+ uintf_t intf;
+
+ /* parameter check */
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(setup != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_interface\n"));
+
+ /* find the specified interface and its alternate setting */
+ intf = rt_usbd_find_interface(device, setup->index & 0xFF, RT_NULL);
+ value = intf->curr_setting->intf_desc->bAlternateSetting;
+
+ /* send the interface alternate setting to endpoint 0*/
+ dcd_ep_write(device->dcd, 0, &value, 1);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle set_interface request.
+ *
+ * @param device the usb device object.
+ * @param setup the setup request.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _set_interface(struct udevice* device, ureq_t setup)
+{
+ uintf_t intf;
+ uep_t ep;
+ struct rt_list_node* i;
+ ualtsetting_t setting;
+
+ /* parameter check */
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(setup != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_set_interface\n"));
+
+ /* find the specified interface */
+ intf = rt_usbd_find_interface(device, setup->index & 0xFF, RT_NULL);
+
+ /* set alternate setting to the interface */
+ rt_usbd_set_altsetting(intf, setup->value & 0xFF);
+ 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)
+ {
+ ep = (uep_t)rt_list_entry(i, struct uendpoint, list);
+ dcd_ep_stop(device->dcd, ep);
+ dcd_ep_run(device->dcd, ep);
+ }
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle get_config request.
+ *
+ * @param device the usb device object.
+ * @param setup the setup request.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _get_config(struct udevice* device, ureq_t setup)
+{
+ rt_uint8_t value;
+
+ /* parameter check */
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(setup != RT_NULL);
+ RT_ASSERT(device->curr_cfg != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_config\n"));
+
+ /* get current configuration */
+ value = device->curr_cfg->cfg_desc.bConfigurationValue;
+
+ /* write the current configuration to endpoint 0 */
+ dcd_ep_write(device->dcd, 0, &value, 1);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle set_config request.
+ *
+ * @param device the usb device object.
+ * @param setup the setup request.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _set_config(struct udevice* device, ureq_t setup)
+{
+ struct rt_list_node *i, *j, *k;
+ uconfig_t cfg;
+ uintf_t intf;
+ ualtsetting_t setting;
+ uep_t ep;
+
+ /* parameter check */
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(setup != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_set_config\n"));
+
+ /* set current configuration */
+ rt_usbd_set_config(device, setup->value);
+ cfg = device->curr_cfg;
+
+ for (i=cfg->cls_list.next; i!=&cfg->cls_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)
+ {
+ 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)
+ {
+ 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);
+ }
+ }
+ /* after running all endpoints, then run class */
+ if(cls->ops->run != RT_NULL)
+ cls->ops->run(device, cls);
+ }
+
+ /* issue status stage */
+ rt_device_control((rt_device_t)device->dcd, CONTROL_SEND_STATUS, RT_NULL);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle set_address request.
+ *
+ * @param device the usb device object.
+ * @param setup the setup request.
+ *
+ * @return RT_EOK on successful.
+ */
+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"));
+
+ /* set address in device control driver */
+ dcd_set_address(device->dcd, setup->value);
+
+ /* issue status stage */
+ rt_device_control((rt_device_t)device->dcd, CONTROL_SEND_STATUS, RT_NULL);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle standard request.
+ *
+ * @param device the usb device object.
+ * @param setup the setup request.
+ *
+ * @return RT_EOK on successful.
+ */
+static rt_err_t _standard_request(struct udevice* device, ureq_t setup)
+{
+ udcd_t dcd;
+ rt_uint16_t value = 0;
+
+ /* parameter check */
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(setup != RT_NULL);
+
+ dcd = device->dcd;
+
+ switch(setup->request_type & USB_REQ_TYPE_RECIPIENT_MASK)
+ {
+ case USB_REQ_TYPE_DEVICE:
+ switch(setup->request)
+ {
+ case USB_REQ_GET_STATUS:
+ dcd_ep_write(device->dcd, 0, &value, 2);
+ break;
+ case USB_REQ_CLEAR_FEATURE:
+ dcd_clear_feature(dcd, setup->value);
+ break;
+ case USB_REQ_SET_FEATURE:
+ dcd_set_feature(dcd, setup->value);
+ break;
+ case USB_REQ_SET_ADDRESS:
+ _set_address(device, setup);
+ break;
+ case USB_REQ_GET_DESCRIPTOR:
+ _get_descriptor(device, setup);
+ break;
+ case USB_REQ_SET_DESCRIPTOR:
+ dcd_ep_stall(dcd, 0);
+ break;
+ case USB_REQ_GET_CONFIGURATION:
+ _get_config(device, setup);
+ break;
+ case USB_REQ_SET_CONFIGURATION:
+ _set_config(device, setup);
+ break;
+ default:
+ rt_kprintf("unknown device request\n");
+ dcd_ep_stall(device->dcd, 0);
+ break;
+ }
+ break;
+ case USB_REQ_TYPE_INTERFACE:
+ switch(setup->request)
+ {
+ case USB_REQ_GET_INTERFACE:
+ _get_interface(device, setup);
+ break;
+ case USB_REQ_SET_INTERFACE:
+ _set_interface(device, setup);
+ break;
+ default:
+ rt_kprintf("unknown interface request\n");
+ dcd_ep_stall(device->dcd, 0);
+ break;
+ }
+ break;
+ case USB_REQ_TYPE_ENDPOINT:
+ switch(setup->request)
+ {
+ case USB_REQ_GET_STATUS:
+ /* TODO */
+ dcd_ep_write(dcd, 0, &value, 2);
+ break;
+ case USB_REQ_CLEAR_FEATURE:
+ dcd_clear_feature(dcd, setup->value);
+ break;
+ case USB_REQ_SET_FEATURE:
+ dcd_set_feature(dcd, setup->value);
+ break;
+ case USB_REQ_SYNCH_FRAME:
+ break;
+ default:
+ rt_kprintf("unknown endpoint request\n");
+ dcd_ep_stall(device->dcd, 0);
+ break;
+ }
+ break;
+ case USB_REQ_TYPE_OTHER:
+ rt_kprintf("unknown other type request\n");
+ dcd_ep_stall(device->dcd, 0);
+ break;
+ default:
+ rt_kprintf("unknown type request\n");
+ dcd_ep_stall(device->dcd, 0);
+ break;
+ }
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle class 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)
+{
+ uintf_t intf;
+ uclass_t cls;
+
+ /* parameter check */
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(setup != RT_NULL);
+
+ /* verify request value */
+ if(setup->index > device->curr_cfg->cfg_desc.bNumInterfaces)
+ {
+ dcd_ep_stall(device->dcd, 0);
+ return -RT_ERROR;
+ }
+
+ 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);
+ break;
+ case USB_REQ_TYPE_ENDPOINT:
+ break;
+ default:
+ rt_kprintf("unknown class request type\n");
+ dcd_ep_stall(device->dcd, 0);
+ break;
+ }
+
+ return RT_EOK;
+}
+
+/**
+ * This function will handle setup 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 _setup_request(udevice_t device, ureq_t setup)
+{
+ /* parameter check */
+ 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"));
+
+ 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);
+ 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);
+ return -RT_ERROR;
+ }
+
+ return RT_EOK;
+}
+
+/**
+ * This function will notity sof event to all of class.
+ *
+ * @param device the usb device object.
+ *
+ * @return RT_EOK.
+ */
+rt_err_t _sof_notify(udevice_t device)
+{
+ struct rt_list_node *i;
+ uclass_t cls;
+
+ RT_ASSERT(device != RT_NULL);
+
+ /* to notity every class that sof event comes */
+ for (i=device->curr_cfg->cls_list.next;
+ i!=&device->curr_cfg->cls_list; i=i->next)
+ {
+ cls = (uclass_t)rt_list_entry(i, struct uclass, list);
+ if(cls->ops->sof_handler != RT_NULL)
+ cls->ops->sof_handler(device, cls);
+ }
+
+ return RT_EOK;
+}
+
+/**
+ * This function will create an usb device object.
+ *
+ * @param ustring the usb string array to contain string descriptor.
+ *
+ * @return an usb device object on success, RT_NULL on fail.
+ */
+udevice_t rt_usbd_device_create(const char** ustring)
+{
+ udevice_t udevice;
+
+ /* parameter check */
+ RT_ASSERT(ustring != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_device_create\n"));
+
+ /* allocate memory for the object */
+ udevice = rt_malloc(sizeof(struct udevice));
+ if(udevice == RT_NULL)
+ {
+ rt_kprintf("alloc memery failed\n");
+ return RT_NULL;
+ }
+ rt_memset(udevice, 0, sizeof(struct udevice));
+
+ /* set string descriptor array to the device object */
+ udevice->str = ustring;
+
+ /* to initialize configuration list */
+ rt_list_init(&udevice->cfg_list);
+
+ /* insert the device object to device list */
+ rt_list_insert_after(&device_list, &udevice->list);
+
+ return udevice;
+}
+
+/**
+ * This function will set an usb controller driver to a device.
+ *
+ * @param device the usb device object.
+ * @param dcd the usb device controller driver.
+ *
+ * @return RT_EOK on successful.
+ */
+rt_err_t rt_usbd_device_set_controller(udevice_t device, udcd_t dcd)
+{
+ /* parameter check */
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(dcd != RT_NULL);
+
+ /* set usb device controller driver to the device */
+ device->dcd = dcd;
+
+ return RT_EOK;
+}
+
+/**
+ * This function will set an usb device descriptor to a device.
+ *
+ * @param device the usb device object.
+ * @param dev_desc the usb device descriptor.
+ *
+ * @return RT_EOK on successful.
+ */
+rt_err_t rt_usbd_device_set_descriptor(udevice_t device, udev_desc_t dev_desc)
+{
+ /* parameter check */
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(dev_desc != RT_NULL);
+
+ /* copy the usb device descriptor to the device */
+ rt_memcpy((void *)&device->dev_desc, (void *)dev_desc, USB_DESC_LENGTH_DEVICE);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will create an usb configuration object.
+ *
+ * @param none.
+ *
+ * @return an usb configuration object.
+ */
+uconfig_t rt_usbd_config_create(void)
+{
+ uconfig_t cfg;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_config_create\n"));
+
+ /* allocate memory for the object */
+ cfg = rt_malloc(sizeof(struct uconfig));
+ 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.wTotalLength = USB_DESC_LENGTH_CONFIG;
+ cfg->cfg_desc.bmAttributes = 0xC0;
+ cfg->cfg_desc.MaxPower = 0x32;
+
+ /* to initialize class object list */
+ rt_list_init(&cfg->cls_list);
+
+ return cfg;
+}
+
+/**
+ * This function will create an usb interface object.
+ *
+ * @param device the usb device object.
+ * @handler the callback handler of object
+ *
+ * @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 intf;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_interface_create\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)
+ {
+ rt_kprintf("alloc memery failed\n");
+ return RT_NULL;
+ }
+ intf->intf_num = device->nr_intf;
+ device->nr_intf++;
+ intf->handler = handler;
+ intf->curr_setting = RT_NULL;
+
+ /* to initialize the alternate setting object list */
+ rt_list_init(&intf->setting_list);
+
+ return intf;
+}
+
+/**
+ * This function will create an usb alternate setting object.
+ *
+ * @param intf_desc the interface descriptor.
+ * @desc_size the size of the interface descriptor.
+ *
+ * @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 setting;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_altsetting_create\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)
+ {
+ rt_kprintf("alloc memery failed\n");
+ return RT_NULL;
+ }
+ /* allocate memory for the desc */
+ setting->desc = rt_malloc(desc_size);
+ if (setting->desc == RT_NULL)
+ {
+ rt_kprintf("alloc desc memery failed\n");
+ rt_free(setting);
+ return RT_NULL;
+ }
+
+ setting->desc_size = desc_size;
+ setting->intf_desc = RT_NULL;
+
+ /* to initialize endpoint list */
+ rt_list_init(&setting->ep_list);
+
+ return setting;
+}
+
+/**
+ * This function will config an desc in alternate setting object.
+ *
+ * @param setting the altsetting to be config.
+ * @param desc use it to init desc in setting.
+ * @param intf_pos the offset of interface descriptor in desc.
+ *
+ * @return RT_EOK.
+ */
+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);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will create an usb class 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.
+ */
+uclass_t rt_usbd_class_create(udevice_t device, udev_desc_t dev_desc,
+ uclass_ops_t ops)
+{
+ uclass_t cls;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_class_create\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)
+ {
+ rt_kprintf("alloc memery failed\n");
+ return RT_NULL;
+ }
+ cls->dev_desc = dev_desc;
+ cls->ops = ops;
+ cls->device = device;
+
+ /* to initialize interface list */
+ rt_list_init(&cls->intf_list);
+
+ return cls;
+}
+
+/**
+ * This function will create an usb endpoint object.
+ *
+ * @param ep_desc the endpoint descriptor.
+ * @handler the callback handler of object
+ *
+ * @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 ep;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_endpoint_create\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)
+ {
+ rt_kprintf("alloc memery failed\n");
+ return RT_NULL;
+ }
+ ep->ep_desc = ep_desc;
+ ep->handler = handler;
+ ep->buffer = RT_NULL;
+
+ return ep;
+}
+
+/**
+ * This function will find an usb device object.
+ *
+ * @dcd usd device controller driver.
+ *
+ * @return an usb device object on found or RT_NULL on not found.
+ */
+udevice_t rt_usbd_find_device(udcd_t dcd)
+{
+ struct rt_list_node* node;
+ udevice_t device;
+
+ /* parameter check */
+ RT_ASSERT(dcd != RT_NULL);
+
+ /* search a device in the the device list */
+ 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;
+ }
+
+ rt_kprintf("can't find device\n");
+ return RT_NULL;
+}
+
+/**
+ * This function will find an usb configuration object.
+ *
+ * @param device the usb device object.
+ * @param value the configuration number.
+ *
+ * @return an usb configuration object on found or RT_NULL on not found.
+ */
+uconfig_t rt_usbd_find_config(udevice_t device, rt_uint8_t value)
+{
+ struct rt_list_node* node;
+ uconfig_t cfg = RT_NULL;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_find_config\n"));
+
+ /* parameter check */
+ RT_ASSERT(device != RT_NULL);
+ 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)
+ {
+ cfg = (uconfig_t)rt_list_entry(node, struct udevice, list);
+ if(cfg->cfg_desc.bConfigurationValue == value) return cfg;
+ }
+
+ rt_kprintf("can't find configuration %d\n", value);
+ return RT_NULL;
+}
+
+/**
+ * This function will find an usb interface object.
+ *
+ * @param device the usb device object.
+ * @param value the interface number.
+ *
+ * @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)
+{
+ struct rt_list_node *i, *j;
+ uclass_t cls;
+ uintf_t intf;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_find_interface\n"));
+
+ /* parameter check */
+ RT_ASSERT(device != RT_NULL);
+ 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)
+ {
+ cls = (uclass_t)rt_list_entry(i, struct uclass, list);
+ for(j=cls->intf_list.next; j!=&cls->intf_list; j=j->next)
+ {
+ intf = (uintf_t)rt_list_entry(j, struct uinterface, list);
+ if(intf->intf_num == value)
+ {
+ if (pcls != RT_NULL)
+ *pcls = cls;
+ return intf;
+ }
+ }
+ }
+
+ rt_kprintf("can't find interface %d\n", value);
+ return RT_NULL;
+}
+
+/**
+ * This function will find an usb interface alternate setting object.
+ *
+ * @param device the usb device object.
+ * @param value the alternate setting number.
+ *
+ * @return an usb interface alternate setting object on found or RT_NULL on not found.
+ */
+ualtsetting_t rt_usbd_find_altsetting(uintf_t intf, rt_uint8_t value)
+{
+ struct rt_list_node *i;
+ ualtsetting_t setting;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_find_altsetting\n"));
+
+ /* parameter check */
+ RT_ASSERT(intf != 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)
+ 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)
+ {
+ setting =(ualtsetting_t)rt_list_entry(i, struct ualtsetting, list);
+ if(setting->intf_desc->bAlternateSetting == value)
+ return setting;
+ }
+
+ rt_kprintf("can't find alternate setting %d\n", value);
+ return RT_NULL;
+}
+
+/**
+ * This function will find an usb endpoint object.
+ *
+ * @param device the usb device object.
+ * @param ep_addr endpoint address.
+ *
+ * @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 ep;
+ struct rt_list_node *i, *j, *k;
+ uclass_t cls;
+ 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)
+ {
+ cls = (uclass_t)rt_list_entry(i, struct uclass, list);
+ for(j=cls->intf_list.next; j!=&cls->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)
+ {
+ ep = (uep_t)rt_list_entry(k, struct uendpoint, list);
+ if(ep->ep_desc->bEndpointAddress == ep_addr)
+ {
+ if (pcls != RT_NULL)
+ *pcls = cls;
+ return ep;
+ }
+ }
+ }
+ }
+
+ rt_kprintf("can't find endpoint 0x%x\n", ep_addr);
+ return RT_NULL;
+}
+
+/**
+ * This function will add a configuration to an usb device.
+ *
+ * @param device the usb device object.
+ * @param cfg the configuration object.
+ *
+ * @return RT_EOK.
+ */
+rt_err_t rt_usbd_device_add_config(udevice_t device, uconfig_t cfg)
+{
+ struct rt_list_node *i, *j, *k;
+ uclass_t cls;
+ uintf_t intf;
+ uep_t ep;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_device_add_config\n"));
+
+ /* parameter check */
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(cfg != RT_NULL);
+
+ /* set configuration number to the configuration descriptor */
+ 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)
+ {
+ cls = (uclass_t)rt_list_entry(i, struct uclass, list);
+
+ for(j=cls->intf_list.next; j!=&cls->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)
+ {
+ ep = (uep_t)rt_list_entry(k, struct uendpoint, list);
+ dcd_ep_alloc(device->dcd, ep);
+ }
+
+ /* 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);
+ cfg->cfg_desc.wTotalLength += intf->curr_setting->desc_size;
+ }
+ }
+
+ /* insert the configuration to the list */
+ rt_list_insert_after(&device->cfg_list, &cfg->list);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will add a class to a configuration.
+ *
+ * @param cfg the configuration object.
+ * @param cls the class object.
+ *
+ * @return RT_EOK.
+ */
+rt_err_t rt_usbd_config_add_class(uconfig_t cfg, uclass_t cls)
+{
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_config_add_class\n"));
+
+ /* parameter check */
+ RT_ASSERT(cfg != RT_NULL);
+ RT_ASSERT(cls != RT_NULL);
+
+ /* insert the class to the list */
+ rt_list_insert_after(&cfg->cls_list, &cls->list);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will add an interface to a class.
+ *
+ * @param cls the class object.
+ * @param intf the interface object.
+ *
+ * @return RT_EOK.
+ */
+rt_err_t rt_usbd_class_add_interface(uclass_t cls, uintf_t intf)
+{
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_class_add_interface\n"));
+
+ /* parameter check */
+ RT_ASSERT(cls != RT_NULL);
+ RT_ASSERT(intf != RT_NULL);
+
+ /* insert the interface to the list */
+ rt_list_insert_after(&cls->intf_list, &intf->list);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will add an alternate setting to an interface.
+ *
+ * @param intf the interface object.
+ * @param setting the alternate setting object.
+ *
+ * @return RT_EOK.
+ */
+rt_err_t rt_usbd_interface_add_altsetting(uintf_t intf, ualtsetting_t setting)
+{
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_interface_add_altsetting\n"));
+
+ /* parameter check */
+ RT_ASSERT(intf != RT_NULL);
+ RT_ASSERT(setting != RT_NULL);
+
+ setting->intf_desc->bInterfaceNumber = intf->intf_num;
+
+ /* insert the alternate setting to the list */
+ rt_list_insert_after(&intf->setting_list, &setting->list);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will add an endpoint to an alternate setting.
+ *
+ * @param setting the alternate setting object.
+ * @param ep the endpoint object.
+ *
+ * @return RT_EOK.
+ */
+rt_err_t rt_usbd_altsetting_add_endpoint(ualtsetting_t setting, uep_t ep)
+{
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_altsetting_add_endpoint\n"));
+
+ /* parameter check */
+ RT_ASSERT(setting != RT_NULL);
+ RT_ASSERT(ep != RT_NULL);
+
+ /* insert the endpoint to the list */
+ rt_list_insert_after(&setting->ep_list, &ep->list);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will set an alternate setting for an interface.
+ *
+ * @param intf_desc the interface descriptor.
+ * @param value the alternate setting number.
+ *
+ * @return RT_EOK.
+ */
+rt_err_t rt_usbd_set_altsetting(uintf_t intf, rt_uint8_t value)
+{
+ ualtsetting_t setting;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_set_altsetting\n"));
+
+ /* parameter check */
+ RT_ASSERT(intf != RT_NULL);
+ RT_ASSERT(setting != RT_NULL);
+
+ /* find an alternate setting */
+ setting = rt_usbd_find_altsetting(intf, value);
+
+ /* set as current alternate setting */
+ intf->curr_setting = setting;
+
+ return RT_EOK;
+}
+
+/**
+ * This function will set a configuration for an usb device.
+ *
+ * @param device the usb device object.
+ * @param value the configuration number.
+ *
+ * @return RT_EOK.
+ */
+rt_err_t rt_usbd_set_config(udevice_t device, rt_uint8_t value)
+{
+ uconfig_t cfg;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_set_config\n"));
+
+ /* parameter check */
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(value <= device->dev_desc.bNumConfigurations);
+
+ /* find a configuration */
+ cfg = rt_usbd_find_config(device, value);
+
+ /* set as current configuration */
+ device->curr_cfg = cfg;
+
+ return RT_TRUE;
+}
+
+static struct rt_messagequeue *usb_mq;
+
+/**
+ * This function is the main entry of usb device thread, it is in charge of
+ * processing all messages received from the usb message buffer.
+ *
+ * @param parameter the parameter of the usb device thread.
+ *
+ * @return none.
+ */
+static void rt_usbd_thread_entry(void* parameter)
+{
+ 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 ) continue;
+
+ switch (msg.type)
+ {
+ case USB_MSG_SETUP_NOTIFY:
+ device = rt_usbd_find_device(msg.dcd);
+ if(device != RT_NULL)
+ _setup_request(device, (ureq_t)msg.content.setup_msg.packet);
+ else
+ rt_kprintf("invalid usb device\n");
+ break;
+ case USB_MSG_DATA_NOTIFY:
+ 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");
+ break;
+ case USB_MSG_SOF:
+ device = rt_usbd_find_device(msg.dcd);
+ if(device != RT_NULL)
+ _sof_notify(device);
+ else
+ rt_kprintf("invalid usb device\n");
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/**
+ * This function will post an message to usb message queue,
+ *
+ * @param msg the message to be posted
+ * @param size the size of the message .
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usbd_post_event(struct udev_msg* msg, rt_size_t size)
+{
+ RT_ASSERT(msg != RT_NULL);
+
+ /* send message to usb message queue */
+ return rt_mq_send(usb_mq, (void*)msg, size);
+}
+
+/**
+ * This function will initialize usb device thread.
+ *
+ * @return none.
+ *
+ */
+rt_err_t rt_usbd_core_init(void)
+{
+ rt_thread_t thread;
+
+ rt_list_init(&device_list);
+
+ /* create an usb message queue */
+ usb_mq = rt_mq_create("usbd", 32, 16, RT_IPC_FLAG_FIFO);
+
+ /* create usb device thread */
+ thread = rt_thread_create("usbd", rt_usbd_thread_entry, RT_NULL,
+ 2048, 8, 20);
+ if(thread != RT_NULL)
+ {
+ /* startup usb device thread */
+ rt_thread_startup(thread);
+ }
+
+ return RT_EOK;
+}
+
diff --git a/components/drivers/usb/usbdevice/core/usbdevice.c b/components/drivers/usb/usbdevice/core/usbdevice.c
index 42e8664738..328fd6c686 100644
--- a/components/drivers/usb/usbdevice/core/usbdevice.c
+++ b/components/drivers/usb/usbdevice/core/usbdevice.c
@@ -1,117 +1,117 @@
-/*
- * File : usbdevice.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2012, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2012-10-02 Yi Qiu first version
- */
-
-#include <rtthread.h>
-#include <rtdevice.h>
-#include <rtservice.h>
-
-const static char* ustring[] =
-{
- "Language",
- "RT-Thread Team.",
- "RT-Thread Device",
- "1.1.0",
- "Configuration",
- "Interface",
-};
-
-#ifdef RT_USB_DEVICE_COMPOSITE
-static struct udevice_descriptor compsit_desc =
-{
- USB_DESC_LENGTH_DEVICE, //bLength;
- USB_DESC_TYPE_DEVICE, //type;
- USB_BCD_VERSION, //bcdUSB;
- USB_CLASS_MISC, //bDeviceClass;
- 0x02, //bDeviceSubClass;
- 0x01, //bDeviceProtocol;
- 0x40, //bMaxPacketSize0;
- USB_VENDOR_ID, //idVendor;
- 0xbacf, //idProduct;
- USB_BCD_DEVICE, //bcdDevice;
- USB_STRING_MANU_INDEX, //iManufacturer;
- USB_STRING_PRODUCT_INDEX, //iProduct;
- USB_STRING_SERIAL_INDEX, //iSerialNumber;
- USB_DYNAMIC, //bNumConfigurations;
-};
-#endif
-
-rt_err_t rt_usb_device_init(const char* udc_name)
-{
- rt_device_t udc;
- udevice_t udevice;
- uconfig_t cfg;
- uclass_t cls;
-
- RT_ASSERT(udc_name != RT_NULL);
-
- udc = rt_device_find(udc_name);
- if(udc == RT_NULL)
- {
- rt_kprintf("can't find usb device controller %s\n", udc_name);
- return -RT_ERROR;
- }
-
- /* create and startup usb device thread */
- rt_usbd_core_init();
-
- /* create a device object */
- udevice = rt_usbd_device_create(ustring);
-
- /* 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();
-
-#ifdef RT_USB_DEVICE_MSTORAGE
- /* create a mass storage class object */
- cls = rt_usbd_class_mstorage_create(udevice);
-
- /* add the class to the configuration */
- rt_usbd_config_add_class(cfg, cls);
-#endif
-#ifdef RT_USB_DEVICE_CDC
- /* create a cdc class object */
- cls = rt_usbd_class_cdc_create(udevice);
-
- /* add the class to the configuration */
- rt_usbd_config_add_class(cfg, cls);
-#endif
-#ifdef RT_USB_DEVICE_RNDIS
- /* create a rndis class object */
- cls = rt_usbd_class_rndis_create(udevice);
-
- /* add the class to the configuration */
- rt_usbd_config_add_class(cfg, cls);
-#endif
-
- /* set device descriptor to the device */
-#ifdef RT_USB_DEVICE_COMPOSITE
- rt_usbd_device_set_descriptor(udevice, &compsit_desc);
-#else
- rt_usbd_device_set_descriptor(udevice, cls->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);
-
- return RT_EOK;
-}
-
+/*
+ * File : usbdevice.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2012, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2012-10-02 Yi Qiu first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <rtservice.h>
+
+const static char* ustring[] =
+{
+ "Language",
+ "RT-Thread Team.",
+ "RT-Thread Device",
+ "1.1.0",
+ "Configuration",
+ "Interface",
+};
+
+#ifdef RT_USB_DEVICE_COMPOSITE
+static struct udevice_descriptor compsit_desc =
+{
+ USB_DESC_LENGTH_DEVICE, //bLength;
+ USB_DESC_TYPE_DEVICE, //type;
+ USB_BCD_VERSION, //bcdUSB;
+ USB_CLASS_MISC, //bDeviceClass;
+ 0x02, //bDeviceSubClass;
+ 0x01, //bDeviceProtocol;
+ 0x40, //bMaxPacketSize0;
+ USB_VENDOR_ID, //idVendor;
+ 0xbacf, //idProduct;
+ USB_BCD_DEVICE, //bcdDevice;
+ USB_STRING_MANU_INDEX, //iManufacturer;
+ USB_STRING_PRODUCT_INDEX, //iProduct;
+ USB_STRING_SERIAL_INDEX, //iSerialNumber;
+ USB_DYNAMIC, //bNumConfigurations;
+};
+#endif
+
+rt_err_t rt_usb_device_init(const char* udc_name)
+{
+ rt_device_t udc;
+ udevice_t udevice;
+ uconfig_t cfg;
+ uclass_t cls;
+
+ RT_ASSERT(udc_name != RT_NULL);
+
+ udc = rt_device_find(udc_name);
+ if(udc == RT_NULL)
+ {
+ rt_kprintf("can't find usb device controller %s\n", udc_name);
+ return -RT_ERROR;
+ }
+
+ /* create and startup usb device thread */
+ rt_usbd_core_init();
+
+ /* create a device object */
+ udevice = rt_usbd_device_create(ustring);
+
+ /* 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();
+
+#ifdef RT_USB_DEVICE_MSTORAGE
+ /* create a mass storage class object */
+ cls = rt_usbd_class_mstorage_create(udevice);
+
+ /* add the class to the configuration */
+ rt_usbd_config_add_class(cfg, cls);
+#endif
+#ifdef RT_USB_DEVICE_CDC
+ /* create a cdc class object */
+ cls = rt_usbd_class_cdc_create(udevice);
+
+ /* add the class to the configuration */
+ rt_usbd_config_add_class(cfg, cls);
+#endif
+#ifdef RT_USB_DEVICE_RNDIS
+ /* create a rndis class object */
+ cls = rt_usbd_class_rndis_create(udevice);
+
+ /* add the class to the configuration */
+ rt_usbd_config_add_class(cfg, cls);
+#endif
+
+ /* set device descriptor to the device */
+#ifdef RT_USB_DEVICE_COMPOSITE
+ rt_usbd_device_set_descriptor(udevice, &compsit_desc);
+#else
+ rt_usbd_device_set_descriptor(udevice, cls->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);
+
+ return RT_EOK;
+}
+
diff --git a/components/drivers/usb/usbhost/SConscript b/components/drivers/usb/usbhost/SConscript
index 8da2dc4fb9..02e09f75df 100644
--- a/components/drivers/usb/usbhost/SConscript
+++ b/components/drivers/usb/usbhost/SConscript
@@ -1,34 +1,34 @@
-Import('RTT_ROOT')
-from building import *
-
-cwd = GetCurrentDir()
-src = Split("""
-core/core.c
-core/driver.c
-core/usbhost.c
-core/hub.c
-""")
-
-if GetDepend('RT_USB_CLASS_ADK'):
- src += Glob('class/adk.c')
- src += Glob('udev/adkapp.c')
-
-if GetDepend('RT_USB_CLASS_MASS_STORAGE'):
- src += Glob('class/mass.c')
- src += Glob('udev/udisk.c')
-
-if GetDepend('RT_USB_CLASS_HID'):
- src += Glob('class/hid.c')
-
-if GetDepend('RT_USB_HID_MOUSE'):
- src += Glob('udev/umouse.c')
-
-if GetDepend('RT_USB_HID_KEYBOARD'):
- src += Glob('udev/ukbd.c')
-
-CPPPATH = [cwd, cwd + '/class', cwd + '/core', \
- cwd + '/include', cwd + '../../../include']
-
-group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_USB_HOST'], CPPPATH = CPPPATH)
-
-Return('group')
+Import('RTT_ROOT')
+from building import *
+
+cwd = GetCurrentDir()
+src = Split("""
+core/core.c
+core/driver.c
+core/usbhost.c
+core/hub.c
+""")
+
+if GetDepend('RT_USB_CLASS_ADK'):
+ src += Glob('class/adk.c')
+ src += Glob('udev/adkapp.c')
+
+if GetDepend('RT_USB_CLASS_MASS_STORAGE'):
+ src += Glob('class/mass.c')
+ src += Glob('udev/udisk.c')
+
+if GetDepend('RT_USB_CLASS_HID'):
+ src += Glob('class/hid.c')
+
+if GetDepend('RT_USB_HID_MOUSE'):
+ src += Glob('udev/umouse.c')
+
+if GetDepend('RT_USB_HID_KEYBOARD'):
+ src += Glob('udev/ukbd.c')
+
+CPPPATH = [cwd, cwd + '/class', cwd + '/core', \
+ cwd + '/include', cwd + '../../../include']
+
+group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_USB_HOST'], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/components/drivers/usb/usbhost/class/adk.c b/components/drivers/usb/usbhost/class/adk.c
index 0f1d409793..ff9bef92dd 100644
--- a/components/drivers/usb/usbhost/class/adk.c
+++ b/components/drivers/usb/usbhost/class/adk.c
@@ -1,407 +1,407 @@
-/*
- * File : adk.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2011, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2011-12-12 Yi Qiu first version
- */
-
-#include <rtthread.h>
-#include <drivers/usb_host.h>
-#include "adk.h"
-
-#ifdef RT_USB_CLASS_ADK
-
-static struct uclass_driver adk_driver;
-static const char* _adk_manufacturer = RT_NULL;
-static const char* _adk_model = RT_NULL;
-static const char* _adk_description = RT_NULL;
-static const char* _adk_version = RT_NULL;
-static const char* _adk_uri = RT_NULL;
-static const char* _adk_serial = RT_NULL;
-
-rt_err_t rt_usb_adk_set_string(const char* manufacturer, const char* model,
- const char* description, const char* _version, const char* uri,
- const char* serial)
-{
- _adk_manufacturer = manufacturer;
- _adk_model = model;
- _adk_description = description;
- _adk_version = _version;
- _adk_uri = uri;
- _adk_serial = serial;
-
- return RT_EOK;
-}
-
-#ifdef RT_USING_MODULE
-#include <rtm.h>
-
-RTM_EXPORT(rt_usb_adk_set_string);
-#endif
-
-/**
- * This function will do USB_REQ_GET_PROTOCOL request to set idle period to the usb adk device
- *
- * @param ifinst the interface instance.
- * @duration the idle period of requesting data.
- * @report_id the report id
- *
- * @return the error code, RT_EOK on successfully.
-*/
-static rt_err_t rt_usb_adk_get_protocol(uifinst_t ifinst, rt_uint16_t *protocol)
-{
- struct ureqest setup;
- uinst_t uinst;
- int timeout = 100;
-
- /* parameter check */
- RT_ASSERT(ifinst != RT_NULL);
- RT_ASSERT(ifinst->uinst != RT_NULL);
-
- uinst = ifinst->uinst;
-
- setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_VENDOR |
- USB_REQ_TYPE_DEVICE;
- setup.request = USB_REQ_GET_PROTOCOL;
- setup.index = 0;
- setup.length = 2;
- setup.value = 0;
-
- if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, (void*)protocol, 2,
- timeout) == 0) return RT_EOK;
- else return -RT_FALSE;
-}
-
-/**
- * This function will do USB_REQ_SEND_STRING request to set idle period to the usb adk device
- *
- * @param ifinst the interface instance.
- * @duration the idle period of requesting data.
- * @report_id the report id
- *
- * @return the error code, RT_EOK on successfully.
-*/
-static rt_err_t rt_usb_adk_send_string(uifinst_t ifinst, rt_uint16_t index,
- const char* str)
-{
- struct ureqest setup;
- uinst_t uinst;
- int timeout = 100;
-
- /* parameter check */
- RT_ASSERT(ifinst != RT_NULL);
- RT_ASSERT(ifinst->uinst != RT_NULL);
-
- uinst = ifinst->uinst;
-
- setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_VENDOR |
- USB_REQ_TYPE_DEVICE;
- setup.request = USB_REQ_SEND_STRING;
- setup.index = index;
- setup.length = rt_strlen(str) + 1;
- setup.value = 0;
-
- if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, (void*)str,
- rt_strlen(str) + 1, timeout) == 0) return RT_EOK;
- else return -RT_FALSE;
-}
-
-/**
- * This function will do USB_REQ_START request to set idle period to the usb adk device
- *
- * @param ifinst the interface instance.
- * @duration the idle period of requesting data.
- * @report_id the report id
- *
- * @return the error code, RT_EOK on successfully.
-*/
-static rt_err_t rt_usb_adk_start(uifinst_t ifinst)
-{
- struct ureqest setup;
- uinst_t uinst;
- int timeout = 100;
-
- /* parameter check */
- RT_ASSERT(ifinst != RT_NULL);
- RT_ASSERT(ifinst->uinst != RT_NULL);
-
- uinst = ifinst->uinst;
-
- setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_VENDOR |
- USB_REQ_TYPE_DEVICE;
- setup.request = USB_REQ_START;
- setup.index = 0;
- setup.length = 0;
- setup.value = 0;
-
- if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0,
- timeout) == 0) return RT_EOK;
- else return -RT_FALSE;
-}
-
-/**
- * This function will read data from usb adk device
- *
- * @param ifinst the interface instance.
- *
- * @return the error code, RT_EOK on successfully.
-*/
-static rt_size_t rt_usb_adk_read(rt_device_t device, rt_off_t pos, void* buffer,
- rt_size_t size)
-{
- uadkinst_t adkinst;
- rt_size_t length;
- uifinst_t ifinst;
-
- /* check parameter */
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(buffer != RT_NULL);
-
- ifinst = (uifinst_t)device->user_data;
- adkinst = (uadkinst_t)ifinst->user_data;
-
- length = rt_usb_hcd_bulk_xfer(ifinst->uinst->hcd, adkinst->pipe_in,
- buffer, size, 300);
-
- return length;
-
-}
-
-/**
- * This function will write data to usb adk device
- *
- * @param ifinst the interface instance.
- *
- * @return the error code, RT_EOK on successfully.
-*/
-static rt_size_t rt_usb_adk_write (rt_device_t device, rt_off_t pos, const void* buffer,
- rt_size_t size)
-{
- uadkinst_t adkinst;
- rt_size_t length;
- uifinst_t ifinst;
-
- RT_ASSERT(buffer != RT_NULL);
-
- ifinst = (uifinst_t)device->user_data;
- adkinst = (uadkinst_t)ifinst->user_data;
-
- length = rt_usb_hcd_bulk_xfer(ifinst->uinst->hcd, adkinst->pipe_out,
- (void*)buffer, size, 300);
-
- return length;
-}
-
-/**
- * This function will run adk class driver when usb device is detected and identified
- * as a adk class device, it will continue the enumulate process.
- *
- * @param arg the argument.
- *
- * @return the error code, RT_EOK on successfully.
- */
-static rt_err_t rt_usb_adk_run(void* arg)
-{
- int i = 0;
- uadkinst_t adkinst;
- uifinst_t ifinst = (uifinst_t)arg;
- udev_desc_t dev_desc;
- rt_uint16_t protocol;
- rt_err_t ret;
-
- /* parameter check */
- if(ifinst == RT_NULL)
- {
- rt_kprintf("the interface is not available\n");
- return -RT_EIO;
- }
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_adk_run\n"));
-
- dev_desc = &ifinst->uinst->dev_desc;
- if(dev_desc->idVendor == USB_ACCESSORY_VENDOR_ID &&
- (dev_desc->idProduct == USB_ACCESSORY_PRODUCT_ID ||
- dev_desc->idProduct == USB_ACCESSORY_ADB_PRODUCT_ID))
- {
- if(ifinst->intf_desc->bInterfaceSubClass != 0xFF) return -RT_ERROR;
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("found android accessory device\n"));
- }
- else
- {
- RT_DEBUG_LOG(RT_DEBUG_USB, ("switch device\n"));
-
- if((ret = rt_usb_adk_get_protocol(ifinst, &protocol)) != RT_EOK)
- {
- rt_kprintf("rt_usb_adk_get_protocol failed\n");
- return ret;
- }
-
- if(protocol != 1)
- {
- rt_kprintf("read protocol failed\n");
- return -RT_ERROR;
- }
-
- rt_usb_adk_send_string(ifinst,
- ACCESSORY_STRING_MANUFACTURER, _adk_manufacturer);
- rt_usb_adk_send_string(ifinst,
- ACCESSORY_STRING_MODEL, _adk_model);
- rt_usb_adk_send_string(ifinst,
- ACCESSORY_STRING_DESCRIPTION, _adk_description);
- rt_usb_adk_send_string(ifinst,
- ACCESSORY_STRING_VERSION, _adk_version);
- rt_usb_adk_send_string(ifinst,
- ACCESSORY_STRING_URI, _adk_uri);
- rt_usb_adk_send_string(ifinst,
- ACCESSORY_STRING_SERIAL, _adk_serial);
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("manufacturer %s\n", _adk_manufacturer));
- RT_DEBUG_LOG(RT_DEBUG_USB, ("model %s\n", _adk_model));
- RT_DEBUG_LOG(RT_DEBUG_USB, ("description %s\n", _adk_description));
- RT_DEBUG_LOG(RT_DEBUG_USB, ("version %s\n", _adk_version));
- RT_DEBUG_LOG(RT_DEBUG_USB, ("uri %s\n", _adk_uri));
- RT_DEBUG_LOG(RT_DEBUG_USB, ("serial %s\n", _adk_serial));
-
- if((ret = rt_usb_adk_start(ifinst)) != RT_EOK)
- {
- rt_kprintf("rt_usb_adk_start failed\n");
- return ret;
- }
-
- return RT_EOK;
- }
-
- adkinst = rt_malloc(sizeof(struct uadkinst));
- RT_ASSERT(adkinst != RT_NULL);
-
- /* initilize the data structure */
- rt_memset(adkinst, 0, sizeof(struct uadkinst));
- ifinst->user_data = (void*)adkinst;
-
- for(i=0; i<ifinst->intf_desc->bNumEndpoints; i++)
- {
- uep_desc_t ep_desc;
-
- /* get endpoint descriptor from interface descriptor */
- rt_usb_get_endpoint_descriptor(ifinst->intf_desc, i, &ep_desc);
- if(ep_desc == RT_NULL)
- {
- rt_kprintf("rt_usb_get_endpoint_descriptor error\n");
- return -RT_ERROR;
- }
-
- /* the endpoint type of adk class should be BULK */
- if((ep_desc->bmAttributes & USB_EP_ATTR_TYPE_MASK) != USB_EP_ATTR_BULK)
- continue;
-
- /* allocate pipes according to the endpoint type */
- if(ep_desc->bEndpointAddress & USB_DIR_IN)
- {
- /* allocate an in pipe for the adk instance */
- ret = rt_usb_hcd_alloc_pipe(ifinst->uinst->hcd, &adkinst->pipe_in,
- ifinst, ep_desc, RT_NULL);
- if(ret != RT_EOK) return ret;
- }
- else
- {
- /* allocate an output pipe for the adk instance */
- ret = rt_usb_hcd_alloc_pipe(ifinst->uinst->hcd, &adkinst->pipe_out,
- ifinst, ep_desc, RT_NULL);
- if(ret != RT_EOK) return ret;
- }
- }
-
- /* check pipes infomation */
- if(adkinst->pipe_in == RT_NULL || adkinst->pipe_out == RT_NULL)
- {
- rt_kprintf("pipe error, unsupported device\n");
- return -RT_ERROR;
- }
-
- /* set configuration */
- ret = rt_usb_set_configure(ifinst->uinst, 1);
- if(ret != RT_EOK) return ret;
-
- /* register adk device */
- adkinst->device.type = RT_Device_Class_Char;
- adkinst->device.init = RT_NULL;
- adkinst->device.open = RT_NULL;
- adkinst->device.close = RT_NULL;
- adkinst->device.read = rt_usb_adk_read;
- adkinst->device.write = rt_usb_adk_write;
- adkinst->device.control = RT_NULL;
- adkinst->device.user_data = (void*)ifinst;
-
- rt_device_register(&adkinst->device, "adkdev", RT_DEVICE_FLAG_RDWR);
-
- return RT_EOK;
-}
-
-/**
- * This function will be invoked when usb device plug out is detected and it would clean
- * and release all hub class related resources.
- *
- * @param arg the argument.
- *
- * @return the error code, RT_EOK on successfully.
- */
-static rt_err_t rt_usb_adk_stop(void* arg)
-{
- uadkinst_t adkinst;
- uifinst_t ifinst = (uifinst_t)arg;
-
- RT_ASSERT(ifinst != RT_NULL);
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_adk_stop\n"));
-
- adkinst = (uadkinst_t)ifinst->user_data;
- if(adkinst == RT_NULL)
- {
- rt_free(ifinst);
- return RT_EOK;
- }
-
- if(adkinst->pipe_in != RT_NULL)
- rt_usb_hcd_free_pipe(ifinst->uinst->hcd, adkinst->pipe_in);
-
- if(adkinst->pipe_out != RT_NULL)
- rt_usb_hcd_free_pipe(ifinst->uinst->hcd, adkinst->pipe_out);
-
- /* unregister adk device */
- rt_device_unregister(&adkinst->device);
-
- /* free adk instance */
- if(adkinst != RT_NULL) rt_free(adkinst);
-
- /* free interface instance */
- rt_free(ifinst);
-
- return RT_EOK;
-}
-
-/**
- * This function will register adk class driver to the usb class driver manager.
- * and it should be invoked in the usb system initialization.
- *
- * @return the error code, RT_EOK on successfully.
- */
-ucd_t rt_usb_class_driver_adk(void)
-{
- adk_driver.class_code = USB_CLASS_ADK;
-
- adk_driver.run = rt_usb_adk_run;
- adk_driver.stop = rt_usb_adk_stop;
-
- return &adk_driver;
-}
-
-#endif
-
+/*
+ * File : adk.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2011, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2011-12-12 Yi Qiu first version
+ */
+
+#include <rtthread.h>
+#include <drivers/usb_host.h>
+#include "adk.h"
+
+#ifdef RT_USB_CLASS_ADK
+
+static struct uclass_driver adk_driver;
+static const char* _adk_manufacturer = RT_NULL;
+static const char* _adk_model = RT_NULL;
+static const char* _adk_description = RT_NULL;
+static const char* _adk_version = RT_NULL;
+static const char* _adk_uri = RT_NULL;
+static const char* _adk_serial = RT_NULL;
+
+rt_err_t rt_usb_adk_set_string(const char* manufacturer, const char* model,
+ const char* description, const char* _version, const char* uri,
+ const char* serial)
+{
+ _adk_manufacturer = manufacturer;
+ _adk_model = model;
+ _adk_description = description;
+ _adk_version = _version;
+ _adk_uri = uri;
+ _adk_serial = serial;
+
+ return RT_EOK;
+}
+
+#ifdef RT_USING_MODULE
+#include <rtm.h>
+
+RTM_EXPORT(rt_usb_adk_set_string);
+#endif
+
+/**
+ * This function will do USB_REQ_GET_PROTOCOL request to set idle period to the usb adk device
+ *
+ * @param ifinst the interface instance.
+ * @duration the idle period of requesting data.
+ * @report_id the report id
+ *
+ * @return the error code, RT_EOK on successfully.
+*/
+static rt_err_t rt_usb_adk_get_protocol(uifinst_t ifinst, rt_uint16_t *protocol)
+{
+ struct ureqest setup;
+ uinst_t uinst;
+ int timeout = 100;
+
+ /* parameter check */
+ RT_ASSERT(ifinst != RT_NULL);
+ RT_ASSERT(ifinst->uinst != RT_NULL);
+
+ uinst = ifinst->uinst;
+
+ setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_VENDOR |
+ USB_REQ_TYPE_DEVICE;
+ setup.request = USB_REQ_GET_PROTOCOL;
+ setup.index = 0;
+ setup.length = 2;
+ setup.value = 0;
+
+ if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, (void*)protocol, 2,
+ timeout) == 0) return RT_EOK;
+ else return -RT_FALSE;
+}
+
+/**
+ * This function will do USB_REQ_SEND_STRING request to set idle period to the usb adk device
+ *
+ * @param ifinst the interface instance.
+ * @duration the idle period of requesting data.
+ * @report_id the report id
+ *
+ * @return the error code, RT_EOK on successfully.
+*/
+static rt_err_t rt_usb_adk_send_string(uifinst_t ifinst, rt_uint16_t index,
+ const char* str)
+{
+ struct ureqest setup;
+ uinst_t uinst;
+ int timeout = 100;
+
+ /* parameter check */
+ RT_ASSERT(ifinst != RT_NULL);
+ RT_ASSERT(ifinst->uinst != RT_NULL);
+
+ uinst = ifinst->uinst;
+
+ setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_VENDOR |
+ USB_REQ_TYPE_DEVICE;
+ setup.request = USB_REQ_SEND_STRING;
+ setup.index = index;
+ setup.length = rt_strlen(str) + 1;
+ setup.value = 0;
+
+ if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, (void*)str,
+ rt_strlen(str) + 1, timeout) == 0) return RT_EOK;
+ else return -RT_FALSE;
+}
+
+/**
+ * This function will do USB_REQ_START request to set idle period to the usb adk device
+ *
+ * @param ifinst the interface instance.
+ * @duration the idle period of requesting data.
+ * @report_id the report id
+ *
+ * @return the error code, RT_EOK on successfully.
+*/
+static rt_err_t rt_usb_adk_start(uifinst_t ifinst)
+{
+ struct ureqest setup;
+ uinst_t uinst;
+ int timeout = 100;
+
+ /* parameter check */
+ RT_ASSERT(ifinst != RT_NULL);
+ RT_ASSERT(ifinst->uinst != RT_NULL);
+
+ uinst = ifinst->uinst;
+
+ setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_VENDOR |
+ USB_REQ_TYPE_DEVICE;
+ setup.request = USB_REQ_START;
+ setup.index = 0;
+ setup.length = 0;
+ setup.value = 0;
+
+ if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0,
+ timeout) == 0) return RT_EOK;
+ else return -RT_FALSE;
+}
+
+/**
+ * This function will read data from usb adk device
+ *
+ * @param ifinst the interface instance.
+ *
+ * @return the error code, RT_EOK on successfully.
+*/
+static rt_size_t rt_usb_adk_read(rt_device_t device, rt_off_t pos, void* buffer,
+ rt_size_t size)
+{
+ uadkinst_t adkinst;
+ rt_size_t length;
+ uifinst_t ifinst;
+
+ /* check parameter */
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(buffer != RT_NULL);
+
+ ifinst = (uifinst_t)device->user_data;
+ adkinst = (uadkinst_t)ifinst->user_data;
+
+ length = rt_usb_hcd_bulk_xfer(ifinst->uinst->hcd, adkinst->pipe_in,
+ buffer, size, 300);
+
+ return length;
+
+}
+
+/**
+ * This function will write data to usb adk device
+ *
+ * @param ifinst the interface instance.
+ *
+ * @return the error code, RT_EOK on successfully.
+*/
+static rt_size_t rt_usb_adk_write (rt_device_t device, rt_off_t pos, const void* buffer,
+ rt_size_t size)
+{
+ uadkinst_t adkinst;
+ rt_size_t length;
+ uifinst_t ifinst;
+
+ RT_ASSERT(buffer != RT_NULL);
+
+ ifinst = (uifinst_t)device->user_data;
+ adkinst = (uadkinst_t)ifinst->user_data;
+
+ length = rt_usb_hcd_bulk_xfer(ifinst->uinst->hcd, adkinst->pipe_out,
+ (void*)buffer, size, 300);
+
+ return length;
+}
+
+/**
+ * This function will run adk class driver when usb device is detected and identified
+ * as a adk class device, it will continue the enumulate process.
+ *
+ * @param arg the argument.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+static rt_err_t rt_usb_adk_run(void* arg)
+{
+ int i = 0;
+ uadkinst_t adkinst;
+ uifinst_t ifinst = (uifinst_t)arg;
+ udev_desc_t dev_desc;
+ rt_uint16_t protocol;
+ rt_err_t ret;
+
+ /* parameter check */
+ if(ifinst == RT_NULL)
+ {
+ rt_kprintf("the interface is not available\n");
+ return -RT_EIO;
+ }
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_adk_run\n"));
+
+ dev_desc = &ifinst->uinst->dev_desc;
+ if(dev_desc->idVendor == USB_ACCESSORY_VENDOR_ID &&
+ (dev_desc->idProduct == USB_ACCESSORY_PRODUCT_ID ||
+ dev_desc->idProduct == USB_ACCESSORY_ADB_PRODUCT_ID))
+ {
+ if(ifinst->intf_desc->bInterfaceSubClass != 0xFF) return -RT_ERROR;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("found android accessory device\n"));
+ }
+ else
+ {
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("switch device\n"));
+
+ if((ret = rt_usb_adk_get_protocol(ifinst, &protocol)) != RT_EOK)
+ {
+ rt_kprintf("rt_usb_adk_get_protocol failed\n");
+ return ret;
+ }
+
+ if(protocol != 1)
+ {
+ rt_kprintf("read protocol failed\n");
+ return -RT_ERROR;
+ }
+
+ rt_usb_adk_send_string(ifinst,
+ ACCESSORY_STRING_MANUFACTURER, _adk_manufacturer);
+ rt_usb_adk_send_string(ifinst,
+ ACCESSORY_STRING_MODEL, _adk_model);
+ rt_usb_adk_send_string(ifinst,
+ ACCESSORY_STRING_DESCRIPTION, _adk_description);
+ rt_usb_adk_send_string(ifinst,
+ ACCESSORY_STRING_VERSION, _adk_version);
+ rt_usb_adk_send_string(ifinst,
+ ACCESSORY_STRING_URI, _adk_uri);
+ rt_usb_adk_send_string(ifinst,
+ ACCESSORY_STRING_SERIAL, _adk_serial);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("manufacturer %s\n", _adk_manufacturer));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("model %s\n", _adk_model));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("description %s\n", _adk_description));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("version %s\n", _adk_version));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("uri %s\n", _adk_uri));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("serial %s\n", _adk_serial));
+
+ if((ret = rt_usb_adk_start(ifinst)) != RT_EOK)
+ {
+ rt_kprintf("rt_usb_adk_start failed\n");
+ return ret;
+ }
+
+ return RT_EOK;
+ }
+
+ adkinst = rt_malloc(sizeof(struct uadkinst));
+ RT_ASSERT(adkinst != RT_NULL);
+
+ /* initilize the data structure */
+ rt_memset(adkinst, 0, sizeof(struct uadkinst));
+ ifinst->user_data = (void*)adkinst;
+
+ for(i=0; i<ifinst->intf_desc->bNumEndpoints; i++)
+ {
+ uep_desc_t ep_desc;
+
+ /* get endpoint descriptor from interface descriptor */
+ rt_usb_get_endpoint_descriptor(ifinst->intf_desc, i, &ep_desc);
+ if(ep_desc == RT_NULL)
+ {
+ rt_kprintf("rt_usb_get_endpoint_descriptor error\n");
+ return -RT_ERROR;
+ }
+
+ /* the endpoint type of adk class should be BULK */
+ if((ep_desc->bmAttributes & USB_EP_ATTR_TYPE_MASK) != USB_EP_ATTR_BULK)
+ continue;
+
+ /* allocate pipes according to the endpoint type */
+ if(ep_desc->bEndpointAddress & USB_DIR_IN)
+ {
+ /* allocate an in pipe for the adk instance */
+ ret = rt_usb_hcd_alloc_pipe(ifinst->uinst->hcd, &adkinst->pipe_in,
+ ifinst, ep_desc, RT_NULL);
+ if(ret != RT_EOK) return ret;
+ }
+ else
+ {
+ /* allocate an output pipe for the adk instance */
+ ret = rt_usb_hcd_alloc_pipe(ifinst->uinst->hcd, &adkinst->pipe_out,
+ ifinst, ep_desc, RT_NULL);
+ if(ret != RT_EOK) return ret;
+ }
+ }
+
+ /* check pipes infomation */
+ if(adkinst->pipe_in == RT_NULL || adkinst->pipe_out == RT_NULL)
+ {
+ rt_kprintf("pipe error, unsupported device\n");
+ return -RT_ERROR;
+ }
+
+ /* set configuration */
+ ret = rt_usb_set_configure(ifinst->uinst, 1);
+ if(ret != RT_EOK) return ret;
+
+ /* register adk device */
+ adkinst->device.type = RT_Device_Class_Char;
+ adkinst->device.init = RT_NULL;
+ adkinst->device.open = RT_NULL;
+ adkinst->device.close = RT_NULL;
+ adkinst->device.read = rt_usb_adk_read;
+ adkinst->device.write = rt_usb_adk_write;
+ adkinst->device.control = RT_NULL;
+ adkinst->device.user_data = (void*)ifinst;
+
+ rt_device_register(&adkinst->device, "adkdev", RT_DEVICE_FLAG_RDWR);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will be invoked when usb device plug out is detected and it would clean
+ * and release all hub class related resources.
+ *
+ * @param arg the argument.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+static rt_err_t rt_usb_adk_stop(void* arg)
+{
+ uadkinst_t adkinst;
+ uifinst_t ifinst = (uifinst_t)arg;
+
+ RT_ASSERT(ifinst != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_adk_stop\n"));
+
+ adkinst = (uadkinst_t)ifinst->user_data;
+ if(adkinst == RT_NULL)
+ {
+ rt_free(ifinst);
+ return RT_EOK;
+ }
+
+ if(adkinst->pipe_in != RT_NULL)
+ rt_usb_hcd_free_pipe(ifinst->uinst->hcd, adkinst->pipe_in);
+
+ if(adkinst->pipe_out != RT_NULL)
+ rt_usb_hcd_free_pipe(ifinst->uinst->hcd, adkinst->pipe_out);
+
+ /* unregister adk device */
+ rt_device_unregister(&adkinst->device);
+
+ /* free adk instance */
+ if(adkinst != RT_NULL) rt_free(adkinst);
+
+ /* free interface instance */
+ rt_free(ifinst);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will register adk class driver to the usb class driver manager.
+ * and it should be invoked in the usb system initialization.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+ucd_t rt_usb_class_driver_adk(void)
+{
+ adk_driver.class_code = USB_CLASS_ADK;
+
+ adk_driver.run = rt_usb_adk_run;
+ adk_driver.stop = rt_usb_adk_stop;
+
+ return &adk_driver;
+}
+
+#endif
+
diff --git a/components/drivers/usb/usbhost/class/adk.h b/components/drivers/usb/usbhost/class/adk.h
index dd7606fbec..ef18ab2714 100644
--- a/components/drivers/usb/usbhost/class/adk.h
+++ b/components/drivers/usb/usbhost/class/adk.h
@@ -1,47 +1,47 @@
-/*
- * File : adk.h
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2011, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2011-12-12 Yi Qiu first version
- */
-
-#ifndef __HID_H__
-#define __HID_H__
-
-#include <rtthread.h>
-
-struct uadkinst
-{
- upipe_t pipe_in;
- upipe_t pipe_out;
-
- struct rt_device device;
-};
-typedef struct uadkinst* uadkinst_t;
-
-#define USB_ACCESSORY_VENDOR_ID 0x18D1
-#define USB_ACCESSORY_PRODUCT_ID 0x2D00
-#define USB_ACCESSORY_ADB_PRODUCT_ID 0x2D01
-
-#define ACCESSORY_STRING_MANUFACTURER 0
-#define ACCESSORY_STRING_MODEL 1
-#define ACCESSORY_STRING_DESCRIPTION 2
-#define ACCESSORY_STRING_VERSION 3
-#define ACCESSORY_STRING_URI 4
-#define ACCESSORY_STRING_SERIAL 5
-
-#define USB_REQ_GET_PROTOCOL 51
-#define USB_REQ_SEND_STRING 52
-#define USB_REQ_START 53
-
-#define USB_CLASS_ADK 0xff
-
-#endif
-
+/*
+ * File : adk.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2011, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2011-12-12 Yi Qiu first version
+ */
+
+#ifndef __HID_H__
+#define __HID_H__
+
+#include <rtthread.h>
+
+struct uadkinst
+{
+ upipe_t pipe_in;
+ upipe_t pipe_out;
+
+ struct rt_device device;
+};
+typedef struct uadkinst* uadkinst_t;
+
+#define USB_ACCESSORY_VENDOR_ID 0x18D1
+#define USB_ACCESSORY_PRODUCT_ID 0x2D00
+#define USB_ACCESSORY_ADB_PRODUCT_ID 0x2D01
+
+#define ACCESSORY_STRING_MANUFACTURER 0
+#define ACCESSORY_STRING_MODEL 1
+#define ACCESSORY_STRING_DESCRIPTION 2
+#define ACCESSORY_STRING_VERSION 3
+#define ACCESSORY_STRING_URI 4
+#define ACCESSORY_STRING_SERIAL 5
+
+#define USB_REQ_GET_PROTOCOL 51
+#define USB_REQ_SEND_STRING 52
+#define USB_REQ_START 53
+
+#define USB_CLASS_ADK 0xff
+
+#endif
+
diff --git a/components/drivers/usb/usbhost/core/core.c b/components/drivers/usb/usbhost/core/core.c
index 956f283b95..d689f7a249 100644
--- a/components/drivers/usb/usbhost/core/core.c
+++ b/components/drivers/usb/usbhost/core/core.c
@@ -1,469 +1,469 @@
-/*
- * File : core.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2011, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2011-12-12 Yi Qiu first version
- */
-
-#include <rtthread.h>
-#include <drivers/usb_host.h>
-
-static struct uinstance uinst[USB_MAX_DEVICE];
-
-/**
- * This function will allocate an usb device instance from system.
- *
- * @param parent the hub instance to which the new allocated device attached.
- * @param port the hub port.
- *
- * @return the allocate instance on successful, or RT_NULL on failure.
- */
-uinst_t rt_usb_alloc_instance(void)
-{
- int i;
-
- /* lock scheduler */
- rt_enter_critical();
-
- for(i=0; i<USB_MAX_DEVICE; i++)
- {
- /* to find an idle instance handle */
- if(uinst[i].status != UINST_STATUS_IDLE) continue;
-
- /* initialize the usb device instance */
- rt_memset(&uinst[i], 0, sizeof(struct uinstance));
-
- uinst[i].status = UINST_STATUS_BUSY;
- uinst[i].index = i + 1;
- uinst[i].address = 0;
- uinst[i].max_packet_size = 0x8;
-
- /* unlock scheduler */
- rt_exit_critical();
- return &uinst[i];
- }
-
- /* unlock scheduler */
- rt_exit_critical();
-
- return RT_NULL;
-}
-
-/**
- * This function will attatch an usb device instance to a host controller,
- * and do device enumunation process.
- *
- * @param hcd the host controller driver.
- * @param uinst the usb device instance.
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_attatch_instance(uinst_t uinst)
-{
- int i = 0;
- rt_err_t ret = RT_EOK;
- struct uconfig_descriptor cfg_desc;
- udev_desc_t dev_desc;
- uintf_desc_t intf_desc;
- ucd_t drv;
-
- RT_ASSERT(uinst != RT_NULL);
-
- rt_memset(&cfg_desc, 0, sizeof(struct uconfig_descriptor));
- dev_desc = &uinst->dev_desc;
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("start enumnation\n"));
-
- /* get device descriptor head */
- ret = rt_usb_get_descriptor(uinst, USB_DESC_TYPE_DEVICE, (void*)dev_desc, 8);
- if(ret != RT_EOK)
- {
- rt_kprintf("get device descriptor head failed\n");
- return ret;
- }
-
- /* set device address */
- ret = rt_usb_set_address(uinst);
- if(ret != RT_EOK)
- {
- rt_kprintf("set device address failed\n");
- return ret;
- }
-
- /* set device max packet size */
- uinst->max_packet_size = uinst->dev_desc.bMaxPacketSize0;
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("get device descriptor length %d\n",
- dev_desc->bLength));
-
- /* get full device descriptor again */
- ret = rt_usb_get_descriptor
- (uinst, USB_DESC_TYPE_DEVICE, (void*)dev_desc, dev_desc->bLength);
- if(ret != RT_EOK)
- {
- rt_kprintf("get full device descriptor failed\n");
- return ret;
- }
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("Vendor ID 0x%x\n", dev_desc->idVendor));
- RT_DEBUG_LOG(RT_DEBUG_USB, ("Product ID 0x%x\n", dev_desc->idProduct));
-
- /* get configuration descriptor head */
- ret = rt_usb_get_descriptor(uinst, USB_DESC_TYPE_CONFIGURATION, &cfg_desc,
- sizeof(struct uconfig_descriptor));
- if(ret != RT_EOK)
- {
- rt_kprintf("get configuration descriptor head failed\n");
- return ret;
- }
-
- /* alloc memory for configuration descriptor */
- uinst->cfg_desc = (ucfg_desc_t)rt_malloc(cfg_desc.wTotalLength);
- rt_memset(uinst->cfg_desc, 0, cfg_desc.wTotalLength);
-
- /* get full configuration descriptor */
- ret = rt_usb_get_descriptor(uinst, USB_DESC_TYPE_CONFIGURATION,
- uinst->cfg_desc, cfg_desc.wTotalLength);
- if(ret != RT_EOK)
- {
- rt_kprintf("get full configuration descriptor failed\n");
- return ret;
- }
-
- /* set configuration */
- ret = rt_usb_set_configure(uinst, 1);
- if(ret != RT_EOK) return ret;
-
- for(i=0; i<uinst->cfg_desc->bNumInterfaces; i++)
- {
- /* get interface descriptor through configuration descriptor */
- ret = rt_usb_get_interface_descriptor(uinst->cfg_desc, i, &intf_desc);
- if(ret != RT_EOK)
- {
- rt_kprintf("rt_usb_get_interface_descriptor error\n");
- return -RT_ERROR;
- }
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("interface class 0x%x, subclass 0x%x\n",
- intf_desc->bInterfaceClass,
- intf_desc->bInterfaceSubClass));
-
- /* find driver by class code found in interface descriptor */
- drv = rt_usb_class_driver_find(intf_desc->bInterfaceClass,
- intf_desc->bInterfaceSubClass);
-
- if(drv != RT_NULL)
- {
- /* allocate memory for interface uinst */
- uinst->ifinst[i] =
- (uifinst_t)rt_malloc(sizeof(struct uifinst));
-
- uinst->ifinst[i]->drv = drv;
- uinst->ifinst[i]->uinst = uinst;
- uinst->ifinst[i]->intf_desc = intf_desc;
- uinst->ifinst[i]->user_data = RT_NULL;
-
- /* open usb class driver */
- ret = rt_usb_class_driver_run(drv, (void*)uinst->ifinst[i]);
- if(ret != RT_EOK)
- {
- rt_kprintf("interface %d run class driver error\n", i);
- }
- }
- else
- {
- rt_kprintf("find usb device driver failed\n");
- continue;
- }
- }
-
- return RT_EOK;
-}
-
-/**
- * This function will detach an usb device instance from its host controller,
- * and release all resource.
- *
- * @param uinst the usb device instance.
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_detach_instance(uinst_t uinst)
-{
- int i = 0;
-
- if(uinst == RT_NULL)
- {
- rt_kprintf("no usb instance to detach\n");
- return -RT_ERROR;
- }
-
- /* free configration descriptor */
- if(uinst->cfg_desc) rt_free(uinst->cfg_desc);
-
- for(i=0; i<uinst->cfg_desc->bNumInterfaces; i++)
- {
- if(uinst->ifinst[i] == RT_NULL) continue;
- if(uinst->ifinst[i]->drv == RT_NULL) continue;
-
- RT_ASSERT(uinst->ifinst[i]->uinst == uinst);
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("free interface instance %d\n", i));
- rt_usb_class_driver_stop(uinst->ifinst[i]->drv, (void*)uinst->ifinst[i]);
- }
-
- rt_memset(uinst, 0, sizeof(struct uinstance));
-
- return RT_EOK;
-}
-
-/**
- * This function will do USB_REQ_GET_DESCRIPTO' request for the usb device instance,
- *
- * @param uinst the usb device instance.
- * @param type the type of descriptor request.
- * @param buffer the data buffer to save requested data
- * @param nbytes the size of buffer
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_get_descriptor(uinst_t uinst, rt_uint8_t type, void* buffer,
- int nbytes)
-{
- struct ureqest setup;
- int timeout = 100;
-
- RT_ASSERT(uinst != RT_NULL);
-
- setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_STANDARD |
- USB_REQ_TYPE_DEVICE;
- setup.request = USB_REQ_GET_DESCRIPTOR;
- setup.index = 0;
- setup.length = nbytes;
- setup.value = type << 8;
-
- if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, buffer, nbytes,
- timeout) != nbytes) return -RT_EIO;
- else return RT_EOK;
-}
-
-/**
- * This function will set an address to the usb device.
- *
- * @param uinst the usb device instance.
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_set_address(uinst_t uinst)
-{
- struct ureqest setup;
- int timeout = 100;
-
- RT_ASSERT(uinst != RT_NULL);
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_set_address\n"));
-
- setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD |
- USB_REQ_TYPE_DEVICE;
- setup.request = USB_REQ_SET_ADDRESS;
- setup.index = 0;
- setup.length = 0;
- setup.value = uinst->index;
-
- if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0,
- timeout) != 0) return -RT_EIO;
-
- rt_thread_delay(50);
-
- uinst->address = uinst->index;
-
- return RT_EOK;
-}
-
-/**
- * This function will set a configuration to the usb device.
- *
- * @param uinst the usb device instance.
- * @param config the configuration number.
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_set_configure(uinst_t uinst, int config)
-{
- struct ureqest setup;
- int timeout = 100;
-
- /* check parameter */
- RT_ASSERT(uinst != RT_NULL);
-
- setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD |
- USB_REQ_TYPE_DEVICE;
- setup.request = USB_REQ_SET_CONFIGURATION;
- setup.index = 0;
- setup.length = 0;
- setup.value = config;
-
- if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0,
- timeout) != 0) return -RT_EIO;
-
- return RT_EOK;
-}
-
-/**
- * This function will set an interface to the usb device.
- *
- * @param uinst the usb device instance.
- * @param intf the interface number.
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_set_interface(uinst_t uinst, int intf)
-{
- struct ureqest setup;
- int timeout = 100;
-
- /* check parameter */
- RT_ASSERT(uinst != RT_NULL);
-
- setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD |
- USB_REQ_TYPE_INTERFACE;
- setup.request = USB_REQ_SET_INTERFACE;
- setup.index = 0;
- setup.length = 0;
- setup.value = intf;
-
- if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0,
- timeout) != 0) return -RT_EIO;
-
- return RT_EOK;
-}
-
-/**
- * This function will clear feature for the endpoint of the usb device.
- *
- * @param uinst the usb device instance.
- * @param endpoint the endpoint number of the usb device.
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_clear_feature(uinst_t uinst, int endpoint, int feature)
-{
- struct ureqest setup;
- int timeout = 100;
-
- /* check parameter */
- RT_ASSERT(uinst != RT_NULL);
-
- setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD |
- USB_REQ_TYPE_ENDPOINT;
- setup.request = USB_REQ_CLEAR_FEATURE;
- setup.index = endpoint;
- setup.length = 0;
- setup.value = feature;
-
- if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0,
- timeout) != 0) return -RT_EIO;
-
- return RT_EOK;
-}
-
-/**
- * This function will get an interface descriptor from the configuration descriptor.
- *
- * @param cfg_desc the point of configuration descriptor structure.
- * @param num the number of interface descriptor.
- * @intf_desc the point of interface descriptor point.
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_get_interface_descriptor(ucfg_desc_t cfg_desc, int num,
- uintf_desc_t* intf_desc)
-{
- rt_uint32_t ptr, depth = 0;
- udesc_t desc;
-
- /* check parameter */
- RT_ASSERT(cfg_desc != RT_NULL);
-
- ptr = (rt_uint32_t)cfg_desc + cfg_desc->bLength;
- while(ptr < (rt_uint32_t)cfg_desc + cfg_desc->wTotalLength)
- {
- if(depth++ > 0x20)
- {
- *intf_desc = RT_NULL;
- return -RT_EIO;
- }
- desc = (udesc_t)ptr;
- if(desc->type == USB_DESC_TYPE_INTERFACE)
- {
- if(((uintf_desc_t)desc)->bInterfaceNumber == num)
- {
- *intf_desc = (uintf_desc_t)desc;
-
- RT_DEBUG_LOG(RT_DEBUG_USB,
- ("rt_usb_get_interface_descriptor: %d\n", num));
- return RT_EOK;
- }
- }
- ptr = (rt_uint32_t)desc + desc->bLength;
- }
-
- rt_kprintf("rt_usb_get_interface_descriptor %d failed\n", num);
- return -RT_EIO;
-}
-
-/**
- * This function will get an endpoint descriptor from the interface descriptor.
- *
- * @param intf_desc the point of interface descriptor structure.
- * @param num the number of endpoint descriptor.
- * @param ep_desc the point of endpoint descriptor point.
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_get_endpoint_descriptor(uintf_desc_t intf_desc, int num,
- uep_desc_t* ep_desc)
-{
- int count = 0, depth = 0;
- rt_uint32_t ptr;
- udesc_t desc;
-
- /* check parameter */
- RT_ASSERT(intf_desc != RT_NULL);
- RT_ASSERT(num < intf_desc->bNumEndpoints);
-
- ptr = (rt_uint32_t)intf_desc + intf_desc->bLength;
- while(count < intf_desc->bNumEndpoints)
- {
- if(depth++ > 0x20)
- {
- *ep_desc = RT_NULL;
- return -RT_EIO;
- }
- desc = (udesc_t)ptr;
- if(desc->type == USB_DESC_TYPE_ENDPOINT)
- {
- if(num == count)
- {
- *ep_desc = (uep_desc_t)desc;
-
- RT_DEBUG_LOG(RT_DEBUG_USB,
- ("rt_usb_get_endpoint_descriptor: %d\n", num));
- return RT_EOK;
- }
- else count++;
- }
- ptr = (rt_uint32_t)desc + desc->bLength;
- }
-
- rt_kprintf("rt_usb_get_endpoint_descriptor %d failed\n", num);
- return -RT_EIO;
-}
-
+/*
+ * File : core.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2011, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2011-12-12 Yi Qiu first version
+ */
+
+#include <rtthread.h>
+#include <drivers/usb_host.h>
+
+static struct uinstance uinst[USB_MAX_DEVICE];
+
+/**
+ * This function will allocate an usb device instance from system.
+ *
+ * @param parent the hub instance to which the new allocated device attached.
+ * @param port the hub port.
+ *
+ * @return the allocate instance on successful, or RT_NULL on failure.
+ */
+uinst_t rt_usb_alloc_instance(void)
+{
+ int i;
+
+ /* lock scheduler */
+ rt_enter_critical();
+
+ for(i=0; i<USB_MAX_DEVICE; i++)
+ {
+ /* to find an idle instance handle */
+ if(uinst[i].status != UINST_STATUS_IDLE) continue;
+
+ /* initialize the usb device instance */
+ rt_memset(&uinst[i], 0, sizeof(struct uinstance));
+
+ uinst[i].status = UINST_STATUS_BUSY;
+ uinst[i].index = i + 1;
+ uinst[i].address = 0;
+ uinst[i].max_packet_size = 0x8;
+
+ /* unlock scheduler */
+ rt_exit_critical();
+ return &uinst[i];
+ }
+
+ /* unlock scheduler */
+ rt_exit_critical();
+
+ return RT_NULL;
+}
+
+/**
+ * This function will attatch an usb device instance to a host controller,
+ * and do device enumunation process.
+ *
+ * @param hcd the host controller driver.
+ * @param uinst the usb device instance.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usb_attatch_instance(uinst_t uinst)
+{
+ int i = 0;
+ rt_err_t ret = RT_EOK;
+ struct uconfig_descriptor cfg_desc;
+ udev_desc_t dev_desc;
+ uintf_desc_t intf_desc;
+ ucd_t drv;
+
+ RT_ASSERT(uinst != RT_NULL);
+
+ rt_memset(&cfg_desc, 0, sizeof(struct uconfig_descriptor));
+ dev_desc = &uinst->dev_desc;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("start enumnation\n"));
+
+ /* get device descriptor head */
+ ret = rt_usb_get_descriptor(uinst, USB_DESC_TYPE_DEVICE, (void*)dev_desc, 8);
+ if(ret != RT_EOK)
+ {
+ rt_kprintf("get device descriptor head failed\n");
+ return ret;
+ }
+
+ /* set device address */
+ ret = rt_usb_set_address(uinst);
+ if(ret != RT_EOK)
+ {
+ rt_kprintf("set device address failed\n");
+ return ret;
+ }
+
+ /* set device max packet size */
+ uinst->max_packet_size = uinst->dev_desc.bMaxPacketSize0;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("get device descriptor length %d\n",
+ dev_desc->bLength));
+
+ /* get full device descriptor again */
+ ret = rt_usb_get_descriptor
+ (uinst, USB_DESC_TYPE_DEVICE, (void*)dev_desc, dev_desc->bLength);
+ if(ret != RT_EOK)
+ {
+ rt_kprintf("get full device descriptor failed\n");
+ return ret;
+ }
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("Vendor ID 0x%x\n", dev_desc->idVendor));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("Product ID 0x%x\n", dev_desc->idProduct));
+
+ /* get configuration descriptor head */
+ ret = rt_usb_get_descriptor(uinst, USB_DESC_TYPE_CONFIGURATION, &cfg_desc,
+ sizeof(struct uconfig_descriptor));
+ if(ret != RT_EOK)
+ {
+ rt_kprintf("get configuration descriptor head failed\n");
+ return ret;
+ }
+
+ /* alloc memory for configuration descriptor */
+ uinst->cfg_desc = (ucfg_desc_t)rt_malloc(cfg_desc.wTotalLength);
+ rt_memset(uinst->cfg_desc, 0, cfg_desc.wTotalLength);
+
+ /* get full configuration descriptor */
+ ret = rt_usb_get_descriptor(uinst, USB_DESC_TYPE_CONFIGURATION,
+ uinst->cfg_desc, cfg_desc.wTotalLength);
+ if(ret != RT_EOK)
+ {
+ rt_kprintf("get full configuration descriptor failed\n");
+ return ret;
+ }
+
+ /* set configuration */
+ ret = rt_usb_set_configure(uinst, 1);
+ if(ret != RT_EOK) return ret;
+
+ for(i=0; i<uinst->cfg_desc->bNumInterfaces; i++)
+ {
+ /* get interface descriptor through configuration descriptor */
+ ret = rt_usb_get_interface_descriptor(uinst->cfg_desc, i, &intf_desc);
+ if(ret != RT_EOK)
+ {
+ rt_kprintf("rt_usb_get_interface_descriptor error\n");
+ return -RT_ERROR;
+ }
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("interface class 0x%x, subclass 0x%x\n",
+ intf_desc->bInterfaceClass,
+ intf_desc->bInterfaceSubClass));
+
+ /* find driver by class code found in interface descriptor */
+ drv = rt_usb_class_driver_find(intf_desc->bInterfaceClass,
+ intf_desc->bInterfaceSubClass);
+
+ if(drv != RT_NULL)
+ {
+ /* allocate memory for interface uinst */
+ uinst->ifinst[i] =
+ (uifinst_t)rt_malloc(sizeof(struct uifinst));
+
+ uinst->ifinst[i]->drv = drv;
+ uinst->ifinst[i]->uinst = uinst;
+ uinst->ifinst[i]->intf_desc = intf_desc;
+ uinst->ifinst[i]->user_data = RT_NULL;
+
+ /* open usb class driver */
+ ret = rt_usb_class_driver_run(drv, (void*)uinst->ifinst[i]);
+ if(ret != RT_EOK)
+ {
+ rt_kprintf("interface %d run class driver error\n", i);
+ }
+ }
+ else
+ {
+ rt_kprintf("find usb device driver failed\n");
+ continue;
+ }
+ }
+
+ return RT_EOK;
+}
+
+/**
+ * This function will detach an usb device instance from its host controller,
+ * and release all resource.
+ *
+ * @param uinst the usb device instance.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usb_detach_instance(uinst_t uinst)
+{
+ int i = 0;
+
+ if(uinst == RT_NULL)
+ {
+ rt_kprintf("no usb instance to detach\n");
+ return -RT_ERROR;
+ }
+
+ /* free configration descriptor */
+ if(uinst->cfg_desc) rt_free(uinst->cfg_desc);
+
+ for(i=0; i<uinst->cfg_desc->bNumInterfaces; i++)
+ {
+ if(uinst->ifinst[i] == RT_NULL) continue;
+ if(uinst->ifinst[i]->drv == RT_NULL) continue;
+
+ RT_ASSERT(uinst->ifinst[i]->uinst == uinst);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("free interface instance %d\n", i));
+ rt_usb_class_driver_stop(uinst->ifinst[i]->drv, (void*)uinst->ifinst[i]);
+ }
+
+ rt_memset(uinst, 0, sizeof(struct uinstance));
+
+ return RT_EOK;
+}
+
+/**
+ * This function will do USB_REQ_GET_DESCRIPTO' request for the usb device instance,
+ *
+ * @param uinst the usb device instance.
+ * @param type the type of descriptor request.
+ * @param buffer the data buffer to save requested data
+ * @param nbytes the size of buffer
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usb_get_descriptor(uinst_t uinst, rt_uint8_t type, void* buffer,
+ int nbytes)
+{
+ struct ureqest setup;
+ int timeout = 100;
+
+ RT_ASSERT(uinst != RT_NULL);
+
+ setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_STANDARD |
+ USB_REQ_TYPE_DEVICE;
+ setup.request = USB_REQ_GET_DESCRIPTOR;
+ setup.index = 0;
+ setup.length = nbytes;
+ setup.value = type << 8;
+
+ if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, buffer, nbytes,
+ timeout) != nbytes) return -RT_EIO;
+ else return RT_EOK;
+}
+
+/**
+ * This function will set an address to the usb device.
+ *
+ * @param uinst the usb device instance.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usb_set_address(uinst_t uinst)
+{
+ struct ureqest setup;
+ int timeout = 100;
+
+ RT_ASSERT(uinst != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_set_address\n"));
+
+ setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD |
+ USB_REQ_TYPE_DEVICE;
+ setup.request = USB_REQ_SET_ADDRESS;
+ setup.index = 0;
+ setup.length = 0;
+ setup.value = uinst->index;
+
+ if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0,
+ timeout) != 0) return -RT_EIO;
+
+ rt_thread_delay(50);
+
+ uinst->address = uinst->index;
+
+ return RT_EOK;
+}
+
+/**
+ * This function will set a configuration to the usb device.
+ *
+ * @param uinst the usb device instance.
+ * @param config the configuration number.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usb_set_configure(uinst_t uinst, int config)
+{
+ struct ureqest setup;
+ int timeout = 100;
+
+ /* check parameter */
+ RT_ASSERT(uinst != RT_NULL);
+
+ setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD |
+ USB_REQ_TYPE_DEVICE;
+ setup.request = USB_REQ_SET_CONFIGURATION;
+ setup.index = 0;
+ setup.length = 0;
+ setup.value = config;
+
+ if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0,
+ timeout) != 0) return -RT_EIO;
+
+ return RT_EOK;
+}
+
+/**
+ * This function will set an interface to the usb device.
+ *
+ * @param uinst the usb device instance.
+ * @param intf the interface number.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usb_set_interface(uinst_t uinst, int intf)
+{
+ struct ureqest setup;
+ int timeout = 100;
+
+ /* check parameter */
+ RT_ASSERT(uinst != RT_NULL);
+
+ setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD |
+ USB_REQ_TYPE_INTERFACE;
+ setup.request = USB_REQ_SET_INTERFACE;
+ setup.index = 0;
+ setup.length = 0;
+ setup.value = intf;
+
+ if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0,
+ timeout) != 0) return -RT_EIO;
+
+ return RT_EOK;
+}
+
+/**
+ * This function will clear feature for the endpoint of the usb device.
+ *
+ * @param uinst the usb device instance.
+ * @param endpoint the endpoint number of the usb device.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usb_clear_feature(uinst_t uinst, int endpoint, int feature)
+{
+ struct ureqest setup;
+ int timeout = 100;
+
+ /* check parameter */
+ RT_ASSERT(uinst != RT_NULL);
+
+ setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD |
+ USB_REQ_TYPE_ENDPOINT;
+ setup.request = USB_REQ_CLEAR_FEATURE;
+ setup.index = endpoint;
+ setup.length = 0;
+ setup.value = feature;
+
+ if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0,
+ timeout) != 0) return -RT_EIO;
+
+ return RT_EOK;
+}
+
+/**
+ * This function will get an interface descriptor from the configuration descriptor.
+ *
+ * @param cfg_desc the point of configuration descriptor structure.
+ * @param num the number of interface descriptor.
+ * @intf_desc the point of interface descriptor point.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usb_get_interface_descriptor(ucfg_desc_t cfg_desc, int num,
+ uintf_desc_t* intf_desc)
+{
+ rt_uint32_t ptr, depth = 0;
+ udesc_t desc;
+
+ /* check parameter */
+ RT_ASSERT(cfg_desc != RT_NULL);
+
+ ptr = (rt_uint32_t)cfg_desc + cfg_desc->bLength;
+ while(ptr < (rt_uint32_t)cfg_desc + cfg_desc->wTotalLength)
+ {
+ if(depth++ > 0x20)
+ {
+ *intf_desc = RT_NULL;
+ return -RT_EIO;
+ }
+ desc = (udesc_t)ptr;
+ if(desc->type == USB_DESC_TYPE_INTERFACE)
+ {
+ if(((uintf_desc_t)desc)->bInterfaceNumber == num)
+ {
+ *intf_desc = (uintf_desc_t)desc;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB,
+ ("rt_usb_get_interface_descriptor: %d\n", num));
+ return RT_EOK;
+ }
+ }
+ ptr = (rt_uint32_t)desc + desc->bLength;
+ }
+
+ rt_kprintf("rt_usb_get_interface_descriptor %d failed\n", num);
+ return -RT_EIO;
+}
+
+/**
+ * This function will get an endpoint descriptor from the interface descriptor.
+ *
+ * @param intf_desc the point of interface descriptor structure.
+ * @param num the number of endpoint descriptor.
+ * @param ep_desc the point of endpoint descriptor point.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usb_get_endpoint_descriptor(uintf_desc_t intf_desc, int num,
+ uep_desc_t* ep_desc)
+{
+ int count = 0, depth = 0;
+ rt_uint32_t ptr;
+ udesc_t desc;
+
+ /* check parameter */
+ RT_ASSERT(intf_desc != RT_NULL);
+ RT_ASSERT(num < intf_desc->bNumEndpoints);
+
+ ptr = (rt_uint32_t)intf_desc + intf_desc->bLength;
+ while(count < intf_desc->bNumEndpoints)
+ {
+ if(depth++ > 0x20)
+ {
+ *ep_desc = RT_NULL;
+ return -RT_EIO;
+ }
+ desc = (udesc_t)ptr;
+ if(desc->type == USB_DESC_TYPE_ENDPOINT)
+ {
+ if(num == count)
+ {
+ *ep_desc = (uep_desc_t)desc;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB,
+ ("rt_usb_get_endpoint_descriptor: %d\n", num));
+ return RT_EOK;
+ }
+ else count++;
+ }
+ ptr = (rt_uint32_t)desc + desc->bLength;
+ }
+
+ rt_kprintf("rt_usb_get_endpoint_descriptor %d failed\n", num);
+ return -RT_EIO;
+}
+
diff --git a/components/drivers/usb/usbhost/core/driver.c b/components/drivers/usb/usbhost/core/driver.c
index 44307ddb22..7aeb4cef58 100644
--- a/components/drivers/usb/usbhost/core/driver.c
+++ b/components/drivers/usb/usbhost/core/driver.c
@@ -1,144 +1,144 @@
-/*
- * File : driver.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2011, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2011-03-12 Yi Qiu first version
- */
-
-#include <rtthread.h>
-#include <rtservice.h>
-#include <rtdevice.h>
-
-static rt_list_t _driver_list;
-
-/**
- * This function will initilize the usb class driver related data structure,
- * and it should be invoked in the usb system initialization.
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_class_driver_init(void)
-{
- rt_list_init(&_driver_list);
-
- return RT_EOK;
-}
-
-/**
- * This function will register an usb class driver to the class driver manager.
- *
- * @param drv the pointer of the usb class driver.
- *
- * @return the error code, RT_EOK on successfully.
- */
-
-rt_err_t rt_usb_class_driver_register(ucd_t drv)
-{
- if (drv == RT_NULL) return -RT_ERROR;
-
- /* insert class driver into driver list */
- rt_list_insert_after(&_driver_list, &(drv->list));
-
- return RT_EOK;
-}
-
-/**
- * This function will removes a previously registed usb class driver.
- *
- * @param drv the pointer of the usb class driver structure.
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_class_driver_unregister(ucd_t drv)
-{
- RT_ASSERT(drv != RT_NULL);
-
- /* remove class driver from driver list */
- rt_list_remove(&(drv->list));
-
- return RT_EOK;
-}
-
-/**
- * This function will run an usb class driver.
- *
- * @param drv the pointer of usb class driver.
- * @param args the parameter of run function.
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_class_driver_run(ucd_t drv, void* args)
-{
- RT_ASSERT(drv != RT_NULL);
-
- if(drv->run != RT_NULL)
- drv->run(args);
-
- return RT_EOK;
-}
-
-/**
- * This function will stop a usb class driver.
- *
- * @param drv the pointer of usb class driver structure.
- * @param args the argument of the stop function.
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_class_driver_stop(ucd_t drv, void* args)
-{
- RT_ASSERT(drv != RT_NULL);
-
- if(drv->stop != RT_NULL)
- drv->stop(args);
-
- return RT_EOK;
-}
-
-
-/**
- * This function finds a usb class driver by specified class code and subclass code.
- *
- * @param class_code the usb class driver's class code.
- * @param subclass_code the usb class driver's sub class code.
- *
- * @return the registered usb class driver on successful, or RT_NULL on failure.
- */
-ucd_t rt_usb_class_driver_find(int class_code, int subclass_code)
-{
- struct rt_list_node *node;
-
- /* enter critical */
- if (rt_thread_self() != RT_NULL)
- rt_enter_critical();
-
- /* try to find driver object */
- for (node = _driver_list.next; node != &_driver_list; node = node->next)
- {
- ucd_t drv =
- (ucd_t)rt_list_entry(node, struct uclass_driver, list);
- if (drv->class_code == class_code)
- {
- /* leave critical */
- if (rt_thread_self() != RT_NULL)
- rt_exit_critical();
-
- return drv;
- }
- }
-
- /* leave critical */
- if (rt_thread_self() != RT_NULL)
- rt_exit_critical();
-
- /* not found */
- return RT_NULL;
-}
-
+/*
+ * File : driver.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2011, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2011-03-12 Yi Qiu first version
+ */
+
+#include <rtthread.h>
+#include <rtservice.h>
+#include <rtdevice.h>
+
+static rt_list_t _driver_list;
+
+/**
+ * This function will initilize the usb class driver related data structure,
+ * and it should be invoked in the usb system initialization.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usb_class_driver_init(void)
+{
+ rt_list_init(&_driver_list);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will register an usb class driver to the class driver manager.
+ *
+ * @param drv the pointer of the usb class driver.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+
+rt_err_t rt_usb_class_driver_register(ucd_t drv)
+{
+ if (drv == RT_NULL) return -RT_ERROR;
+
+ /* insert class driver into driver list */
+ rt_list_insert_after(&_driver_list, &(drv->list));
+
+ return RT_EOK;
+}
+
+/**
+ * This function will removes a previously registed usb class driver.
+ *
+ * @param drv the pointer of the usb class driver structure.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usb_class_driver_unregister(ucd_t drv)
+{
+ RT_ASSERT(drv != RT_NULL);
+
+ /* remove class driver from driver list */
+ rt_list_remove(&(drv->list));
+
+ return RT_EOK;
+}
+
+/**
+ * This function will run an usb class driver.
+ *
+ * @param drv the pointer of usb class driver.
+ * @param args the parameter of run function.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usb_class_driver_run(ucd_t drv, void* args)
+{
+ RT_ASSERT(drv != RT_NULL);
+
+ if(drv->run != RT_NULL)
+ drv->run(args);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will stop a usb class driver.
+ *
+ * @param drv the pointer of usb class driver structure.
+ * @param args the argument of the stop function.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usb_class_driver_stop(ucd_t drv, void* args)
+{
+ RT_ASSERT(drv != RT_NULL);
+
+ if(drv->stop != RT_NULL)
+ drv->stop(args);
+
+ return RT_EOK;
+}
+
+
+/**
+ * This function finds a usb class driver by specified class code and subclass code.
+ *
+ * @param class_code the usb class driver's class code.
+ * @param subclass_code the usb class driver's sub class code.
+ *
+ * @return the registered usb class driver on successful, or RT_NULL on failure.
+ */
+ucd_t rt_usb_class_driver_find(int class_code, int subclass_code)
+{
+ struct rt_list_node *node;
+
+ /* enter critical */
+ if (rt_thread_self() != RT_NULL)
+ rt_enter_critical();
+
+ /* try to find driver object */
+ for (node = _driver_list.next; node != &_driver_list; node = node->next)
+ {
+ ucd_t drv =
+ (ucd_t)rt_list_entry(node, struct uclass_driver, list);
+ if (drv->class_code == class_code)
+ {
+ /* leave critical */
+ if (rt_thread_self() != RT_NULL)
+ rt_exit_critical();
+
+ return drv;
+ }
+ }
+
+ /* leave critical */
+ if (rt_thread_self() != RT_NULL)
+ rt_exit_critical();
+
+ /* not found */
+ return RT_NULL;
+}
+
diff --git a/components/drivers/usb/usbhost/core/hub.c b/components/drivers/usb/usbhost/core/hub.c
index 892094fe4a..05016cb6f7 100644
--- a/components/drivers/usb/usbhost/core/hub.c
+++ b/components/drivers/usb/usbhost/core/hub.c
@@ -1,611 +1,611 @@
-/*
- * File : hub.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2011, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2011-12-12 Yi Qiu first version
- */
-
-#include <rtthread.h>
-#include <drivers/usb_host.h>
-
-#define USB_THREAD_STACK_SIZE 2048
-
-static struct rt_messagequeue *usb_mq;
-static struct uclass_driver hub_driver;
-
-/**
- * This function will do USB_REQ_GET_DESCRIPTOR request for the device instance
- * to get usb hub descriptor.
- *
- * @param ifinst the interface instance.
- * @buffer the data buffer to save usb hub descriptor.
- * @param nbytes the size of buffer
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_hub_get_descriptor(uinst_t uinst, rt_uint8_t *buffer,
- rt_size_t nbytes)
-{
- struct ureqest setup;
- int timeout = 100;
-
- /* parameter check */
- RT_ASSERT(uinst != RT_NULL);
-
- setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_CLASS |
- USB_REQ_TYPE_DEVICE;
- setup.request = USB_REQ_GET_DESCRIPTOR;
- setup.index = 0;
- setup.length = nbytes;
- setup.value = USB_DESC_TYPE_HUB << 8;
-
- if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, buffer, nbytes,
- timeout) == nbytes) return RT_EOK;
- else return -RT_FALSE;
-}
-
-/**
- * This function will do USB_REQ_GET_STATUS request for the device instance
- * to get usb hub status.
- *
- * @param ifinst the interface instance.
- * @buffer the data buffer to save usb hub status.
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_hub_get_status(uinst_t uinst, rt_uint8_t* buffer)
-{
- struct ureqest setup;
- int timeout = 100;
- int length = 4;
-
- /* parameter check */
- RT_ASSERT(uinst != RT_NULL);
-
- setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_CLASS |
- USB_REQ_TYPE_DEVICE;
- setup.request = USB_REQ_GET_STATUS;
- setup.index = 0;
- setup.length = length;
- setup.value = 0;
-
- if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, buffer, length,
- timeout) == length) return RT_EOK;
- else return -RT_FALSE;
-}
-
-/**
- * This function will do USB_REQ_GET_STATUS request for the device instance
- * to get hub port status.
- *
- * @param ifinst the interface instance.
- * @port the hub port to get status.
- * @buffer the data buffer to save usb hub status.
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_hub_get_port_status(uhubinst_t uhub, rt_uint16_t port,
- rt_uint8_t* buffer)
-{
- struct ureqest setup;
- int timeout = 100;
- int length = 4;
-
- /* parameter check */
- RT_ASSERT(uhub != RT_NULL);
-
- /* get roothub port status */
- if(uhub->is_roothub)
- {
- rt_usb_hcd_hub_control(uhub->hcd, port, RH_GET_PORT_STATUS,
- (void*)buffer);
- return RT_EOK;
- }
-
- setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_CLASS |
- USB_REQ_TYPE_OTHER;
- setup.request = USB_REQ_GET_STATUS;
- setup.index = port;
- setup.length = 4;
- setup.value = 0;
-
- if(rt_usb_hcd_control_xfer(uhub->hcd, uhub->self, &setup, buffer,
- length, timeout) == timeout) return RT_EOK;
- else return -RT_FALSE;
-}
-
-/**
- * This function will do USB_REQ_CLEAR_FEATURE request for the device instance
- * to clear feature of the hub port.
- *
- * @param ifinst the interface instance.
- * @port the hub port.
- * @feature feature to be cleared.
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_hub_clear_port_feature(uhubinst_t uhub, rt_uint16_t port,
- rt_uint16_t feature)
-{
- struct ureqest setup;
- int timeout = 100;
-
- /* parameter check */
- RT_ASSERT(uhub != RT_NULL);
-
- /* clear roothub feature */
- if(uhub->is_roothub)
- {
- rt_usb_hcd_hub_control(uhub->hcd, port, RH_CLEAR_PORT_FEATURE,
- (void*)feature);
- return RT_EOK;
- }
-
- setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_CLASS |
- USB_REQ_TYPE_OTHER;
- setup.request = USB_REQ_CLEAR_FEATURE;
- setup.index = port;
- setup.length = 0;
- setup.value = feature;
-
- if(rt_usb_hcd_control_xfer(uhub->hcd, uhub->self, &setup, RT_NULL, 0,
- timeout) == 0) return RT_EOK;
- else return -RT_FALSE;
-}
-
-/**
- * This function will do USB_REQ_SET_FEATURE request for the device instance
- * to set feature of the hub port.
- *
- * @param ifinst the interface instance.
- * @port the hub port.
- * @feature feature to be set.
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_hub_set_port_feature(uhubinst_t uhub, rt_uint16_t port,
- rt_uint16_t feature)
-{
- struct ureqest setup;
- int timeout = 100;
-
- /* parameter check */
- RT_ASSERT(uhub != RT_NULL);
-
- /* clear roothub feature */
- if(uhub->is_roothub)
- {
- rt_usb_hcd_hub_control(uhub->hcd, port, RH_SET_PORT_FEATURE,
- (void*)feature);
- return RT_EOK;
- }
-
- setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_CLASS |
- USB_REQ_TYPE_OTHER;
- setup.request = USB_REQ_SET_FEATURE;
- setup.index = port;
- setup.length = 0;
- setup.value = feature;
-
- if(rt_usb_hcd_control_xfer(uhub->hcd, uhub->self, &setup, RT_NULL, 0,
- timeout) == 0) return RT_EOK;
- else return -RT_FALSE;
-}
-
-/**
- * This function will rest hub port, it is invoked when sub device attached to the hub port.
- *
- * @param ifinst the interface instance.
- * @param port the hub port.
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_hub_reset_port(uhubinst_t uhub, rt_uint16_t port)
-{
- rt_err_t ret;
- rt_uint32_t pstatus;
-
- /* parameter check */
- RT_ASSERT(uhub != RT_NULL);
-
- rt_thread_delay(50);
-
- /* reset hub port */
- ret = rt_usb_hub_set_port_feature(uhub, port, PORT_FEAT_RESET);
- if(ret != RT_EOK) return ret;
-
- while(1)
- {
- ret = rt_usb_hub_get_port_status(uhub, port, (rt_uint8_t*)&pstatus);
- if(!(pstatus & PORT_PRS)) break;
- }
-
- /* clear port reset feature */
- ret = rt_usb_hub_clear_port_feature(uhub, port, PORT_FEAT_C_RESET);
- if(ret != RT_EOK) return ret;
-
- rt_thread_delay(50);
-
- return RT_EOK;
-}
-
-/**
- * This function will do debouce, it is invoked when sub device attached to the hub port.
- *
- * @param uinst the usb instance.
- * @param port the hub port.
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_hub_port_debounce(uhubinst_t uhub, rt_uint16_t port)
-{
- rt_err_t ret;
- int i = 0, times = 20;
- rt_uint32_t pstatus;
- rt_bool_t connect = RT_TRUE;
-
- /* parameter check */
- RT_ASSERT(uhub != RT_NULL);
-
- for(i=0; i<times; i++)
- {
- ret = rt_usb_hub_get_port_status(uhub, port, (rt_uint8_t*)&pstatus);
- if(ret != RT_EOK) return ret;
-
- if(!(pstatus & PORT_CCS))
- {
- connect = RT_FALSE;
- break;
- }
-
- rt_thread_delay(1);
- }
-
- if(connect) return RT_EOK;
- else return -RT_ERROR;
-}
-
-/**
- * This function will poll all the hub ports to detect port status, especially connect and
- * disconnect events.
- *
- * @param ifinst the interface instance.
- *
- * @return the error code, RT_EOK on successfully.
- */
-static rt_err_t rt_usb_hub_port_change(uhubinst_t uhub)
-{
- int i;
- rt_bool_t reconnect;
-
- /* parameter check */
- RT_ASSERT(uhub != RT_NULL);
-
- /* get usb device instance */
- for (i = 0; i < uhub->num_ports; i++)
- {
- rt_err_t ret;
- uinst_t uinst;
- rt_uint32_t pstatus = 0;
-
- reconnect = RT_FALSE;
-
- /* get hub port status */
- ret = rt_usb_hub_get_port_status(uhub, i + 1, (rt_uint8_t*)&pstatus);
- if(ret != RT_EOK) continue;
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("port_status 0x%x\n", pstatus));
-
- /* check port status change */
- if ((pstatus & PORT_CCSC))
- {
- /* clear port status change feature */
- rt_usb_hub_clear_port_feature(uhub, i + 1, PORT_FEAT_C_CONNECTION);
- reconnect = RT_TRUE;
- }
-
- if(pstatus & PORT_PESC)
- {
- rt_usb_hub_clear_port_feature(uhub, i + 1, PORT_FEAT_C_ENABLE);
- reconnect = RT_TRUE;
- }
-
- if(reconnect)
- {
- if(uhub->child[i]->status != UINST_STATUS_IDLE)
- rt_usb_detach_instance(uhub->child[i]);
-
- ret = rt_usb_hub_port_debounce(uhub, i + 1);
- if(ret != RT_EOK) continue;
-
- /* allocate an usb instance for new connected device */
- uinst = rt_usb_alloc_instance();
- if(uinst == RT_NULL) break;
-
- /* set usb device speed */
- uinst->speed = (pstatus & PORT_LSDA) ? 1 : 0;
- uinst->parent = uhub;
- uinst->hcd = uhub->hcd;
- uhub->child[i] = uinst;
-
- /* reset usb roothub port */
- rt_usb_hub_reset_port(uhub, i + 1);
-
- /* attatch the usb instance to the hcd */
- rt_usb_attatch_instance(uinst);
- }
- }
-
- return RT_EOK;
-}
-
-/**
- * This function is the callback function of hub's int endpoint, it is invoked when data comes.
- *
- * @param context the context of the callback function.
- *
- * @return none.
- */
-static void rt_usb_hub_irq(void* context)
-{
- upipe_t pipe;
- uifinst_t ifinst;
- uhubinst_t uhub;
- int timeout = 100;
-
- RT_ASSERT(context != RT_NULL);
-
- pipe = (upipe_t)context;
- ifinst = pipe->ifinst;
- uhub = (uhubinst_t)ifinst->user_data;
-
- if(pipe->status != UPIPE_STATUS_OK)
- {
- rt_kprintf("hub irq error\n");
- return;
- }
-
- rt_usb_hub_port_change(uhub);
-
- rt_kprintf("hub int xfer...\n");
-
- /* parameter check */
- RT_ASSERT(pipe->ifinst->uinst->hcd != RT_NULL);
-
- rt_usb_hcd_int_xfer(ifinst->uinst->hcd, pipe, uhub->buffer,
- pipe->ep.wMaxPacketSize, timeout);
-}
-
-/**
- * This function will run usb hub class driver when usb hub is detected and identified
- * as a hub class device, it will continue to do the enumulate process.
- *
- * @param arg the argument.
- *
- * @return the error code, RT_EOK on successfully.
- */
-static rt_err_t rt_usb_hub_run(void *arg)
-{
- int i = 0;
- rt_err_t ret = RT_EOK;
- uep_desc_t ep_desc;
- uhubinst_t uhub;
- uinst_t uinst;
- uifinst_t ifinst = (uifinst_t)arg;
- int timeout = 300;
-
- /* paremeter check */
- RT_ASSERT(ifinst != RT_NULL);
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_hub_run\n"));
-
- /* get usb device instance */
- uinst = ifinst->uinst;
-
- /* create a hub instance */
- uhub = rt_malloc(sizeof(struct uhubinst));
- rt_memset(uhub, 0, sizeof(struct uhubinst));
-
- /* make interface instance's user data point to hub instance */
- ifinst->user_data = (void*)uhub;
-
- /* get hub descriptor head */
- ret = rt_usb_hub_get_descriptor(uinst, (rt_uint8_t*)&uhub->hub_desc, 8);
- if(ret != RT_EOK)
- {
- rt_kprintf("get hub descriptor failed\n");
- return -RT_ERROR;
- }
-
- /* get full hub descriptor */
- ret = rt_usb_hub_get_descriptor(uinst, (rt_uint8_t*)&uhub->hub_desc,
- uhub->hub_desc.length);
- if(ret != RT_EOK)
- {
- rt_kprintf("get hub descriptor again failed\n");
- return -RT_ERROR;
- }
-
- /* get hub ports number */
- uhub->num_ports = uhub->hub_desc.num_ports;
- uhub->hcd = uinst->hcd;
- uhub->self = uinst;
-
- /* reset all hub ports */
- for (i = 0; i < uhub->num_ports; i++)
- {
- rt_usb_hub_set_port_feature(uhub, i + 1, PORT_FEAT_POWER);
- rt_thread_delay(uhub->hub_desc.pwron_to_good
- * 2 * RT_TICK_PER_SECOND / 1000 );
- }
-
- if(ifinst->intf_desc->bNumEndpoints != 1)
- return -RT_ERROR;
-
- /* get endpoint descriptor from interface descriptor */
- rt_usb_get_endpoint_descriptor(ifinst->intf_desc, 0, &ep_desc);
- if(ep_desc == RT_NULL)
- {
- rt_kprintf("rt_usb_get_endpoint_descriptor error\n");
- return -RT_ERROR;
- }
-
- /* the endpoint type of hub class should be interrupt */
- if( USB_EP_ATTR(ep_desc->bmAttributes) == USB_EP_ATTR_INT)
- {
- /* the endpoint direction of hub class should be in */
- if(ep_desc->bEndpointAddress & USB_DIR_IN)
- {
- /* allocate a pipe according to the endpoint type */
- rt_usb_hcd_alloc_pipe(uinst->hcd, &uhub->pipe_in, ifinst,
- ep_desc, rt_usb_hub_irq);
- }
- else return -RT_ERROR;
- }
-
- /* parameter check */
- RT_ASSERT(uinst->hcd != RT_NULL);
-
- rt_usb_hcd_int_xfer(uinst->hcd, uhub->pipe_in, uhub->buffer,
- uhub->pipe_in->ep.wMaxPacketSize, timeout);
-
- return RT_EOK;
-}
-
-/**
- * This function will be invoked when usb hub plug out is detected and it would clean
- * and release all hub class related resources.
- *
- * @param arg the argument.
- *
- * @return the error code, RT_EOK on successfully.
- */
-static rt_err_t rt_usb_hub_stop(void* arg)
-{
- int i;
- uhubinst_t uhub;
- uinst_t uinst;
- uifinst_t ifinst = (uifinst_t)arg;
-
- /* paremeter check */
- RT_ASSERT(ifinst != RT_NULL);
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_hub_stop\n"));
-
- uinst = ifinst->uinst;
- uhub = (uhubinst_t)ifinst->user_data;
-
- if(uhub->pipe_in != RT_NULL)
- rt_usb_hcd_free_pipe(uinst->hcd, uhub->pipe_in);
-
- for(i=0; i<uhub->num_ports; i++)
- {
- if(uhub->child[i] != RT_NULL)
- rt_usb_detach_instance(uhub->child[i]);
- }
-
- if(uhub != RT_NULL) rt_free(uhub);
- if(ifinst != RT_NULL) rt_free(ifinst);
-
- return RT_EOK;
-}
-
-/**
- * This function will register hub class driver to the usb class driver manager.
- * and it should be invoked in the usb system initialization.
- *
- * @return the error code, RT_EOK on successfully.
- */
-ucd_t rt_usb_class_driver_hub(void)
-{
- hub_driver.class_code = USB_CLASS_HUB;
-
- hub_driver.run = rt_usb_hub_run;
- hub_driver.stop = rt_usb_hub_stop;
-
- return &hub_driver;
-}
-
-/**
- * This function is the main entry of usb hub thread, it is in charge of
- * processing all messages received from the usb message buffer.
- *
- * @param parameter the parameter of the usb host thread.
- *
- * @return none.
- */
-static void rt_usb_hub_thread_entry(void* parameter)
-{
- while(1)
- {
- struct uhost_msg msg;
-
- /* receive message */
- if(rt_mq_recv(usb_mq, &msg, sizeof(struct uhost_msg), RT_WAITING_FOREVER)
- != RT_EOK ) continue;
-
- RT_DEBUG_LOG(RT_DEBUG_USB, ("msg type %d\n", msg.type));
-
- switch (msg.type)
- {
- case USB_MSG_CONNECT_CHANGE:
- rt_usb_hub_port_change(msg.content.uhub);
- break;
- case USB_MSG_CALLBACK:
- /* invoke callback */
- msg.content.cb.function(msg.content.cb.context);
- break;
- default:
- break;
- }
- }
-}
-
-/**
- * This function will post an message to the usb message queue,
- *
- * @param msg the message to be posted
- * @param size the size of the message .
- *
- * @return the error code, RT_EOK on successfully.
- */
-rt_err_t rt_usb_post_event(struct uhost_msg* msg, rt_size_t size)
-{
- RT_ASSERT(msg != RT_NULL);
-
- /* send message to usb message queue */
- rt_mq_send(usb_mq, (void*)msg, size);
-
- return RT_EOK;
-}
-
-/**
- * This function will initialize usb hub thread.
- *
- * @return none.
- *
- */
-void rt_usb_hub_thread(void)
-{
- rt_thread_t thread;
-
- /* create usb message queue */
- usb_mq = rt_mq_create("usbh", 32, 16, RT_IPC_FLAG_FIFO);
-
- /* create usb hub thread */
- thread = rt_thread_create("usbh", rt_usb_hub_thread_entry, RT_NULL,
- USB_THREAD_STACK_SIZE, 8, 20);
- if(thread != RT_NULL)
- {
- /* startup usb host thread */
- rt_thread_startup(thread);
- }
-}
-
+/*
+ * File : hub.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2011, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2011-12-12 Yi Qiu first version
+ */
+
+#include <rtthread.h>
+#include <drivers/usb_host.h>
+
+#define USB_THREAD_STACK_SIZE 2048
+
+static struct rt_messagequeue *usb_mq;
+static struct uclass_driver hub_driver;
+
+/**
+ * This function will do USB_REQ_GET_DESCRIPTOR request for the device instance
+ * to get usb hub descriptor.
+ *
+ * @param ifinst the interface instance.
+ * @buffer the data buffer to save usb hub descriptor.
+ * @param nbytes the size of buffer
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usb_hub_get_descriptor(uinst_t uinst, rt_uint8_t *buffer,
+ rt_size_t nbytes)
+{
+ struct ureqest setup;
+ int timeout = 100;
+
+ /* parameter check */
+ RT_ASSERT(uinst != RT_NULL);
+
+ setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_CLASS |
+ USB_REQ_TYPE_DEVICE;
+ setup.request = USB_REQ_GET_DESCRIPTOR;
+ setup.index = 0;
+ setup.length = nbytes;
+ setup.value = USB_DESC_TYPE_HUB << 8;
+
+ if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, buffer, nbytes,
+ timeout) == nbytes) return RT_EOK;
+ else return -RT_FALSE;
+}
+
+/**
+ * This function will do USB_REQ_GET_STATUS request for the device instance
+ * to get usb hub status.
+ *
+ * @param ifinst the interface instance.
+ * @buffer the data buffer to save usb hub status.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usb_hub_get_status(uinst_t uinst, rt_uint8_t* buffer)
+{
+ struct ureqest setup;
+ int timeout = 100;
+ int length = 4;
+
+ /* parameter check */
+ RT_ASSERT(uinst != RT_NULL);
+
+ setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_CLASS |
+ USB_REQ_TYPE_DEVICE;
+ setup.request = USB_REQ_GET_STATUS;
+ setup.index = 0;
+ setup.length = length;
+ setup.value = 0;
+
+ if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, buffer, length,
+ timeout) == length) return RT_EOK;
+ else return -RT_FALSE;
+}
+
+/**
+ * This function will do USB_REQ_GET_STATUS request for the device instance
+ * to get hub port status.
+ *
+ * @param ifinst the interface instance.
+ * @port the hub port to get status.
+ * @buffer the data buffer to save usb hub status.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usb_hub_get_port_status(uhubinst_t uhub, rt_uint16_t port,
+ rt_uint8_t* buffer)
+{
+ struct ureqest setup;
+ int timeout = 100;
+ int length = 4;
+
+ /* parameter check */
+ RT_ASSERT(uhub != RT_NULL);
+
+ /* get roothub port status */
+ if(uhub->is_roothub)
+ {
+ rt_usb_hcd_hub_control(uhub->hcd, port, RH_GET_PORT_STATUS,
+ (void*)buffer);
+ return RT_EOK;
+ }
+
+ setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_CLASS |
+ USB_REQ_TYPE_OTHER;
+ setup.request = USB_REQ_GET_STATUS;
+ setup.index = port;
+ setup.length = 4;
+ setup.value = 0;
+
+ if(rt_usb_hcd_control_xfer(uhub->hcd, uhub->self, &setup, buffer,
+ length, timeout) == timeout) return RT_EOK;
+ else return -RT_FALSE;
+}
+
+/**
+ * This function will do USB_REQ_CLEAR_FEATURE request for the device instance
+ * to clear feature of the hub port.
+ *
+ * @param ifinst the interface instance.
+ * @port the hub port.
+ * @feature feature to be cleared.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usb_hub_clear_port_feature(uhubinst_t uhub, rt_uint16_t port,
+ rt_uint16_t feature)
+{
+ struct ureqest setup;
+ int timeout = 100;
+
+ /* parameter check */
+ RT_ASSERT(uhub != RT_NULL);
+
+ /* clear roothub feature */
+ if(uhub->is_roothub)
+ {
+ rt_usb_hcd_hub_control(uhub->hcd, port, RH_CLEAR_PORT_FEATURE,
+ (void*)feature);
+ return RT_EOK;
+ }
+
+ setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_CLASS |
+ USB_REQ_TYPE_OTHER;
+ setup.request = USB_REQ_CLEAR_FEATURE;
+ setup.index = port;
+ setup.length = 0;
+ setup.value = feature;
+
+ if(rt_usb_hcd_control_xfer(uhub->hcd, uhub->self, &setup, RT_NULL, 0,
+ timeout) == 0) return RT_EOK;
+ else return -RT_FALSE;
+}
+
+/**
+ * This function will do USB_REQ_SET_FEATURE request for the device instance
+ * to set feature of the hub port.
+ *
+ * @param ifinst the interface instance.
+ * @port the hub port.
+ * @feature feature to be set.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usb_hub_set_port_feature(uhubinst_t uhub, rt_uint16_t port,
+ rt_uint16_t feature)
+{
+ struct ureqest setup;
+ int timeout = 100;
+
+ /* parameter check */
+ RT_ASSERT(uhub != RT_NULL);
+
+ /* clear roothub feature */
+ if(uhub->is_roothub)
+ {
+ rt_usb_hcd_hub_control(uhub->hcd, port, RH_SET_PORT_FEATURE,
+ (void*)feature);
+ return RT_EOK;
+ }
+
+ setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_CLASS |
+ USB_REQ_TYPE_OTHER;
+ setup.request = USB_REQ_SET_FEATURE;
+ setup.index = port;
+ setup.length = 0;
+ setup.value = feature;
+
+ if(rt_usb_hcd_control_xfer(uhub->hcd, uhub->self, &setup, RT_NULL, 0,
+ timeout) == 0) return RT_EOK;
+ else return -RT_FALSE;
+}
+
+/**
+ * This function will rest hub port, it is invoked when sub device attached to the hub port.
+ *
+ * @param ifinst the interface instance.
+ * @param port the hub port.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usb_hub_reset_port(uhubinst_t uhub, rt_uint16_t port)
+{
+ rt_err_t ret;
+ rt_uint32_t pstatus;
+
+ /* parameter check */
+ RT_ASSERT(uhub != RT_NULL);
+
+ rt_thread_delay(50);
+
+ /* reset hub port */
+ ret = rt_usb_hub_set_port_feature(uhub, port, PORT_FEAT_RESET);
+ if(ret != RT_EOK) return ret;
+
+ while(1)
+ {
+ ret = rt_usb_hub_get_port_status(uhub, port, (rt_uint8_t*)&pstatus);
+ if(!(pstatus & PORT_PRS)) break;
+ }
+
+ /* clear port reset feature */
+ ret = rt_usb_hub_clear_port_feature(uhub, port, PORT_FEAT_C_RESET);
+ if(ret != RT_EOK) return ret;
+
+ rt_thread_delay(50);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will do debouce, it is invoked when sub device attached to the hub port.
+ *
+ * @param uinst the usb instance.
+ * @param port the hub port.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usb_hub_port_debounce(uhubinst_t uhub, rt_uint16_t port)
+{
+ rt_err_t ret;
+ int i = 0, times = 20;
+ rt_uint32_t pstatus;
+ rt_bool_t connect = RT_TRUE;
+
+ /* parameter check */
+ RT_ASSERT(uhub != RT_NULL);
+
+ for(i=0; i<times; i++)
+ {
+ ret = rt_usb_hub_get_port_status(uhub, port, (rt_uint8_t*)&pstatus);
+ if(ret != RT_EOK) return ret;
+
+ if(!(pstatus & PORT_CCS))
+ {
+ connect = RT_FALSE;
+ break;
+ }
+
+ rt_thread_delay(1);
+ }
+
+ if(connect) return RT_EOK;
+ else return -RT_ERROR;
+}
+
+/**
+ * This function will poll all the hub ports to detect port status, especially connect and
+ * disconnect events.
+ *
+ * @param ifinst the interface instance.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+static rt_err_t rt_usb_hub_port_change(uhubinst_t uhub)
+{
+ int i;
+ rt_bool_t reconnect;
+
+ /* parameter check */
+ RT_ASSERT(uhub != RT_NULL);
+
+ /* get usb device instance */
+ for (i = 0; i < uhub->num_ports; i++)
+ {
+ rt_err_t ret;
+ uinst_t uinst;
+ rt_uint32_t pstatus = 0;
+
+ reconnect = RT_FALSE;
+
+ /* get hub port status */
+ ret = rt_usb_hub_get_port_status(uhub, i + 1, (rt_uint8_t*)&pstatus);
+ if(ret != RT_EOK) continue;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("port_status 0x%x\n", pstatus));
+
+ /* check port status change */
+ if ((pstatus & PORT_CCSC))
+ {
+ /* clear port status change feature */
+ rt_usb_hub_clear_port_feature(uhub, i + 1, PORT_FEAT_C_CONNECTION);
+ reconnect = RT_TRUE;
+ }
+
+ if(pstatus & PORT_PESC)
+ {
+ rt_usb_hub_clear_port_feature(uhub, i + 1, PORT_FEAT_C_ENABLE);
+ reconnect = RT_TRUE;
+ }
+
+ if(reconnect)
+ {
+ if(uhub->child[i]->status != UINST_STATUS_IDLE)
+ rt_usb_detach_instance(uhub->child[i]);
+
+ ret = rt_usb_hub_port_debounce(uhub, i + 1);
+ if(ret != RT_EOK) continue;
+
+ /* allocate an usb instance for new connected device */
+ uinst = rt_usb_alloc_instance();
+ if(uinst == RT_NULL) break;
+
+ /* set usb device speed */
+ uinst->speed = (pstatus & PORT_LSDA) ? 1 : 0;
+ uinst->parent = uhub;
+ uinst->hcd = uhub->hcd;
+ uhub->child[i] = uinst;
+
+ /* reset usb roothub port */
+ rt_usb_hub_reset_port(uhub, i + 1);
+
+ /* attatch the usb instance to the hcd */
+ rt_usb_attatch_instance(uinst);
+ }
+ }
+
+ return RT_EOK;
+}
+
+/**
+ * This function is the callback function of hub's int endpoint, it is invoked when data comes.
+ *
+ * @param context the context of the callback function.
+ *
+ * @return none.
+ */
+static void rt_usb_hub_irq(void* context)
+{
+ upipe_t pipe;
+ uifinst_t ifinst;
+ uhubinst_t uhub;
+ int timeout = 100;
+
+ RT_ASSERT(context != RT_NULL);
+
+ pipe = (upipe_t)context;
+ ifinst = pipe->ifinst;
+ uhub = (uhubinst_t)ifinst->user_data;
+
+ if(pipe->status != UPIPE_STATUS_OK)
+ {
+ rt_kprintf("hub irq error\n");
+ return;
+ }
+
+ rt_usb_hub_port_change(uhub);
+
+ rt_kprintf("hub int xfer...\n");
+
+ /* parameter check */
+ RT_ASSERT(pipe->ifinst->uinst->hcd != RT_NULL);
+
+ rt_usb_hcd_int_xfer(ifinst->uinst->hcd, pipe, uhub->buffer,
+ pipe->ep.wMaxPacketSize, timeout);
+}
+
+/**
+ * This function will run usb hub class driver when usb hub is detected and identified
+ * as a hub class device, it will continue to do the enumulate process.
+ *
+ * @param arg the argument.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+static rt_err_t rt_usb_hub_run(void *arg)
+{
+ int i = 0;
+ rt_err_t ret = RT_EOK;
+ uep_desc_t ep_desc;
+ uhubinst_t uhub;
+ uinst_t uinst;
+ uifinst_t ifinst = (uifinst_t)arg;
+ int timeout = 300;
+
+ /* paremeter check */
+ RT_ASSERT(ifinst != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_hub_run\n"));
+
+ /* get usb device instance */
+ uinst = ifinst->uinst;
+
+ /* create a hub instance */
+ uhub = rt_malloc(sizeof(struct uhubinst));
+ rt_memset(uhub, 0, sizeof(struct uhubinst));
+
+ /* make interface instance's user data point to hub instance */
+ ifinst->user_data = (void*)uhub;
+
+ /* get hub descriptor head */
+ ret = rt_usb_hub_get_descriptor(uinst, (rt_uint8_t*)&uhub->hub_desc, 8);
+ if(ret != RT_EOK)
+ {
+ rt_kprintf("get hub descriptor failed\n");
+ return -RT_ERROR;
+ }
+
+ /* get full hub descriptor */
+ ret = rt_usb_hub_get_descriptor(uinst, (rt_uint8_t*)&uhub->hub_desc,
+ uhub->hub_desc.length);
+ if(ret != RT_EOK)
+ {
+ rt_kprintf("get hub descriptor again failed\n");
+ return -RT_ERROR;
+ }
+
+ /* get hub ports number */
+ uhub->num_ports = uhub->hub_desc.num_ports;
+ uhub->hcd = uinst->hcd;
+ uhub->self = uinst;
+
+ /* reset all hub ports */
+ for (i = 0; i < uhub->num_ports; i++)
+ {
+ rt_usb_hub_set_port_feature(uhub, i + 1, PORT_FEAT_POWER);
+ rt_thread_delay(uhub->hub_desc.pwron_to_good
+ * 2 * RT_TICK_PER_SECOND / 1000 );
+ }
+
+ if(ifinst->intf_desc->bNumEndpoints != 1)
+ return -RT_ERROR;
+
+ /* get endpoint descriptor from interface descriptor */
+ rt_usb_get_endpoint_descriptor(ifinst->intf_desc, 0, &ep_desc);
+ if(ep_desc == RT_NULL)
+ {
+ rt_kprintf("rt_usb_get_endpoint_descriptor error\n");
+ return -RT_ERROR;
+ }
+
+ /* the endpoint type of hub class should be interrupt */
+ if( USB_EP_ATTR(ep_desc->bmAttributes) == USB_EP_ATTR_INT)
+ {
+ /* the endpoint direction of hub class should be in */
+ if(ep_desc->bEndpointAddress & USB_DIR_IN)
+ {
+ /* allocate a pipe according to the endpoint type */
+ rt_usb_hcd_alloc_pipe(uinst->hcd, &uhub->pipe_in, ifinst,
+ ep_desc, rt_usb_hub_irq);
+ }
+ else return -RT_ERROR;
+ }
+
+ /* parameter check */
+ RT_ASSERT(uinst->hcd != RT_NULL);
+
+ rt_usb_hcd_int_xfer(uinst->hcd, uhub->pipe_in, uhub->buffer,
+ uhub->pipe_in->ep.wMaxPacketSize, timeout);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will be invoked when usb hub plug out is detected and it would clean
+ * and release all hub class related resources.
+ *
+ * @param arg the argument.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+static rt_err_t rt_usb_hub_stop(void* arg)
+{
+ int i;
+ uhubinst_t uhub;
+ uinst_t uinst;
+ uifinst_t ifinst = (uifinst_t)arg;
+
+ /* paremeter check */
+ RT_ASSERT(ifinst != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_hub_stop\n"));
+
+ uinst = ifinst->uinst;
+ uhub = (uhubinst_t)ifinst->user_data;
+
+ if(uhub->pipe_in != RT_NULL)
+ rt_usb_hcd_free_pipe(uinst->hcd, uhub->pipe_in);
+
+ for(i=0; i<uhub->num_ports; i++)
+ {
+ if(uhub->child[i] != RT_NULL)
+ rt_usb_detach_instance(uhub->child[i]);
+ }
+
+ if(uhub != RT_NULL) rt_free(uhub);
+ if(ifinst != RT_NULL) rt_free(ifinst);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will register hub class driver to the usb class driver manager.
+ * and it should be invoked in the usb system initialization.
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+ucd_t rt_usb_class_driver_hub(void)
+{
+ hub_driver.class_code = USB_CLASS_HUB;
+
+ hub_driver.run = rt_usb_hub_run;
+ hub_driver.stop = rt_usb_hub_stop;
+
+ return &hub_driver;
+}
+
+/**
+ * This function is the main entry of usb hub thread, it is in charge of
+ * processing all messages received from the usb message buffer.
+ *
+ * @param parameter the parameter of the usb host thread.
+ *
+ * @return none.
+ */
+static void rt_usb_hub_thread_entry(void* parameter)
+{
+ while(1)
+ {
+ struct uhost_msg msg;
+
+ /* receive message */
+ if(rt_mq_recv(usb_mq, &msg, sizeof(struct uhost_msg), RT_WAITING_FOREVER)
+ != RT_EOK ) continue;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("msg type %d\n", msg.type));
+
+ switch (msg.type)
+ {
+ case USB_MSG_CONNECT_CHANGE:
+ rt_usb_hub_port_change(msg.content.uhub);
+ break;
+ case USB_MSG_CALLBACK:
+ /* invoke callback */
+ msg.content.cb.function(msg.content.cb.context);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/**
+ * This function will post an message to the usb message queue,
+ *
+ * @param msg the message to be posted
+ * @param size the size of the message .
+ *
+ * @return the error code, RT_EOK on successfully.
+ */
+rt_err_t rt_usb_post_event(struct uhost_msg* msg, rt_size_t size)
+{
+ RT_ASSERT(msg != RT_NULL);
+
+ /* send message to usb message queue */
+ rt_mq_send(usb_mq, (void*)msg, size);
+
+ return RT_EOK;
+}
+
+/**
+ * This function will initialize usb hub thread.
+ *
+ * @return none.
+ *
+ */
+void rt_usb_hub_thread(void)
+{
+ rt_thread_t thread;
+
+ /* create usb message queue */
+ usb_mq = rt_mq_create("usbh", 32, 16, RT_IPC_FLAG_FIFO);
+
+ /* create usb hub thread */
+ thread = rt_thread_create("usbh", rt_usb_hub_thread_entry, RT_NULL,
+ USB_THREAD_STACK_SIZE, 8, 20);
+ if(thread != RT_NULL)
+ {
+ /* startup usb host thread */
+ rt_thread_startup(thread);
+ }
+}
+
diff --git a/components/drivers/usb/usbhost/core/usbhost.c b/components/drivers/usb/usbhost/core/usbhost.c
index 0b5bd9a0d1..572da8bd67 100644
--- a/components/drivers/usb/usbhost/core/usbhost.c
+++ b/components/drivers/usb/usbhost/core/usbhost.c
@@ -1,74 +1,74 @@
-/*
- * File : usbhost.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2011, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2011-12-12 Yi Qiu first version
- */
-#include <rtthread.h>
-#include <drivers/usb_host.h>
-
-#if defined(RT_USB_HID_KEYBOARD) || defined(RT_USB_HID_MOUSE)
-#include <hid.h>
-#endif
-
-/**
- * This function will initialize the usb host stack, all the usb class driver and
- * host controller driver are also be initialized here.
- *
- * @return none.
- */
-void rt_usb_host_init(void)
-{
- ucd_t drv;
-#ifdef RT_USB_CLASS_HID
- uprotocal_t protocal;
-#endif
-
- /* initialize usb hub thread */
- rt_usb_hub_thread();
-
- /* initialize class driver */
- rt_usb_class_driver_init();
-
-#ifdef RT_USB_CLASS_MASS_STORAGE
- /* register mass storage class driver */
- drv = rt_usb_class_driver_storage();
- rt_usb_class_driver_register(drv);
-#endif
-
-#ifdef RT_USB_CLASS_HID
- /* register hid class driver */
- drv = rt_usb_class_driver_hid();
- rt_usb_class_driver_register(drv);
-
-#ifdef RT_USB_HID_KEYBOARD
- /* register hid keyboard protocal */
- protocal = rt_usb_hid_protocal_kbd();
- rt_usb_hid_protocal_register(protocal);
-#endif
-
-#ifdef RT_USB_HID_MOUSE
- /* register hid mouse protocal */
- protocal = rt_usb_hid_protocal_mouse();
- rt_usb_hid_protocal_register(protocal);
-#endif
-#endif
-
-#ifdef RT_USB_CLASS_ADK
- /* register adk class driver */
- drv = rt_usb_class_driver_adk();
- rt_usb_class_driver_register(drv);
-#endif
-
- /* register hub class driver */
- drv = rt_usb_class_driver_hub();
- rt_usb_class_driver_register(drv);
-}
-
+/*
+ * File : usbhost.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2011, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2011-12-12 Yi Qiu first version
+ */
+#include <rtthread.h>
+#include <drivers/usb_host.h>
+
+#if defined(RT_USB_HID_KEYBOARD) || defined(RT_USB_HID_MOUSE)
+#include <hid.h>
+#endif
+
+/**
+ * This function will initialize the usb host stack, all the usb class driver and
+ * host controller driver are also be initialized here.
+ *
+ * @return none.
+ */
+void rt_usb_host_init(void)
+{
+ ucd_t drv;
+#ifdef RT_USB_CLASS_HID
+ uprotocal_t protocal;
+#endif
+
+ /* initialize usb hub thread */
+ rt_usb_hub_thread();
+
+ /* initialize class driver */
+ rt_usb_class_driver_init();
+
+#ifdef RT_USB_CLASS_MASS_STORAGE
+ /* register mass storage class driver */
+ drv = rt_usb_class_driver_storage();
+ rt_usb_class_driver_register(drv);
+#endif
+
+#ifdef RT_USB_CLASS_HID
+ /* register hid class driver */
+ drv = rt_usb_class_driver_hid();
+ rt_usb_class_driver_register(drv);
+
+#ifdef RT_USB_HID_KEYBOARD
+ /* register hid keyboard protocal */
+ protocal = rt_usb_hid_protocal_kbd();
+ rt_usb_hid_protocal_register(protocal);
+#endif
+
+#ifdef RT_USB_HID_MOUSE
+ /* register hid mouse protocal */
+ protocal = rt_usb_hid_protocal_mouse();
+ rt_usb_hid_protocal_register(protocal);
+#endif
+#endif
+
+#ifdef RT_USB_CLASS_ADK
+ /* register adk class driver */
+ drv = rt_usb_class_driver_adk();
+ rt_usb_class_driver_register(drv);
+#endif
+
+ /* register hub class driver */
+ drv = rt_usb_class_driver_hub();
+ rt_usb_class_driver_register(drv);
+}
+