diff options
| author | Bernard Xiong <[email protected]> | 2013-01-08 18:13:32 -0800 |
|---|---|---|
| committer | Bernard Xiong <[email protected]> | 2013-01-08 18:13:32 -0800 |
| commit | accace98e05eda28c116eb04502eb92d01b6ef1e (patch) | |
| tree | 4a425c96e0be3980779c8205c7c3fe2f1a144630 /components/drivers/usb | |
| parent | 1fab41d48a490f6483582147500d43f4ca889a8e (diff) | |
| parent | 02b8e9366f362926799bfaecc0891830ba62f646 (diff) | |
Merge pull request #8 from mbbill/correct_crlf
Correct crlf
Diffstat (limited to 'components/drivers/usb')
| -rw-r--r-- | components/drivers/usb/SConscript | 28 | ||||
| -rw-r--r-- | components/drivers/usb/usbdevice/SConscript | 46 | ||||
| -rw-r--r-- | components/drivers/usb/usbdevice/class/cdc.h | 348 | ||||
| -rw-r--r-- | components/drivers/usb/usbdevice/class/cdc_vcom.c | 1182 | ||||
| -rw-r--r-- | components/drivers/usb/usbdevice/class/mstorage.c | 1196 | ||||
| -rw-r--r-- | components/drivers/usb/usbdevice/class/mstorage.h | 132 | ||||
| -rw-r--r-- | components/drivers/usb/usbdevice/core/core.c | 2642 | ||||
| -rw-r--r-- | components/drivers/usb/usbdevice/core/usbdevice.c | 234 | ||||
| -rw-r--r-- | components/drivers/usb/usbhost/SConscript | 68 | ||||
| -rw-r--r-- | components/drivers/usb/usbhost/class/adk.c | 814 | ||||
| -rw-r--r-- | components/drivers/usb/usbhost/class/adk.h | 94 | ||||
| -rw-r--r-- | components/drivers/usb/usbhost/core/core.c | 938 | ||||
| -rw-r--r-- | components/drivers/usb/usbhost/core/driver.c | 288 | ||||
| -rw-r--r-- | components/drivers/usb/usbhost/core/hub.c | 1222 | ||||
| -rw-r--r-- | components/drivers/usb/usbhost/core/usbhost.c | 148 |
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); +} + |
