add USB composite and mass storage class features in USB device stack

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@2447 bbd45198-f89e-11dd-88c7-29a3b14d5316
This commit is contained in:
qiuyiuestc@gmail.com
2012-11-25 00:02:10 +00:00
parent 1b2d954105
commit 60c27fc4b5
8 changed files with 726 additions and 32 deletions

View File

@@ -51,6 +51,7 @@ extern "C" {
#define USB_DESC_TYPE_ENDPOINT 0x05
#define USB_DESC_TYPE_DEVICEQUALIFIER 0x06
#define USB_DESC_TYPE_OTHERSPEED 0x07
#define USB_DESC_TYPE_IAD 0x0b
#define USB_DESC_TYPE_HID 0x21
#define USB_DESC_TYPE_REPORT 0x22
#define USB_DESC_TYPE_PHYSICAL 0x23
@@ -58,6 +59,7 @@ extern "C" {
#define USB_DESC_LENGTH_DEVICE 0x12
#define USB_DESC_LENGTH_CONFIG 0x9
#define USB_DESC_LENGTH_IAD 0x8
#define USB_DESC_LENGTH_STRING 0x4
#define USB_DESC_LENGTH_INTERFACE 0x9
#define USB_DESC_LENGTH_ENDPOINT 0x7
@@ -244,7 +246,7 @@ struct uconfig_descriptor
rt_uint8_t iConfiguration;
rt_uint8_t bmAttributes;
rt_uint8_t MaxPower;
rt_uint8_t data[128];
rt_uint8_t data[256];
};
typedef struct uconfig_descriptor* ucfg_desc_t;
@@ -263,7 +265,7 @@ struct uinterface_descriptor
typedef struct uinterface_descriptor* uintf_desc_t;
/* Interface Association Descriptor (IAD) */
struct uassco_descriptor
struct uiad_descriptor
{
rt_uint8_t bLength;
rt_uint8_t bDescriptorType;
@@ -274,7 +276,7 @@ struct uassco_descriptor
rt_uint8_t bFunctionProtocol;
rt_uint8_t iFunction;
};
typedef struct uassco_descriptor* uassco_desc_t;
typedef struct uiad_descriptor* uiad_desc_t;
struct uendpoint_descriptor
{
@@ -364,6 +366,9 @@ typedef struct ustorage_csw* ustorage_csw_t;
#define USBREQ_GET_MAX_LUN 0xfe
#define USBREQ_MASS_STORAGE_RESET 0xff
#define MIN(a, b) (a < b ? a : b)
#define MAX(a, b) (a > b ? a : b)
#pragma pack()
#ifdef __cplusplus

View File

@@ -92,7 +92,9 @@ struct uclass
struct udevice* device;
udev_desc_t dev_desc;
struct uassco_descriptor* assco;
#ifdef RT_USB_DEVICE_COMPOSITE
uiad_desc_t iad_desc;
#endif
rt_list_t intf_list;
};
typedef struct uclass* uclass_t;
@@ -157,6 +159,7 @@ uep_t rt_usbd_endpoint_create(uep_desc_t ep_desc,
ualtsetting_t rt_usbd_altsetting_create(uintf_desc_t intf_desc, rt_size_t desc_size);
rt_err_t rt_usbd_core_init(void);
rt_err_t rt_usbd_post_event(struct udev_msg* msg, rt_size_t size);
rt_err_t rt_usbd_free_device(udevice_t device);
rt_err_t rt_usbd_device_set_controller(udevice_t device, udcd_t dcd);
rt_err_t rt_usbd_device_set_descriptor(udevice_t device, udev_desc_t dev_desc);
@@ -173,9 +176,13 @@ uconfig_t rt_usbd_find_config(udevice_t device, rt_uint8_t value);
uintf_t rt_usbd_find_interface(udevice_t device, rt_uint8_t value);
uep_t rt_usbd_find_endpoint(udevice_t device, rt_uint8_t ep_addr);
uclass_t rt_usbd_class_mass_create(udevice_t device);
uclass_t rt_usbd_class_mstorage_create(udevice_t device);
uclass_t rt_usbd_class_cdc_create(udevice_t device);
#ifdef RT_USB_DEVICE_COMPOSITE
rt_err_t rt_usbd_class_set_iad(uclass_t cls, uiad_desc_t iad_desc);
#endif
rt_inline rt_err_t dcd_set_address(udcd_t dcd, rt_uint8_t value)
{
RT_ASSERT(dcd != RT_NULL);

View File

@@ -5,9 +5,14 @@ cwd = GetCurrentDir()
src = Split("""
core/core.c
core/usbdevice.c
class/cdc_vcom.c
""")
if GetDepend('RT_USB_DEVICE_CDC'):
src += Glob('class/cdc_vcom.c')
if GetDepend('RT_USB_DEVICE_MSTORAGE'):
src += Glob('class/mstorage.c')
CPPPATH = [cwd]
group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_USB_DEVICE'], CPPPATH = CPPPATH)

View File

@@ -15,9 +15,10 @@
#include <rtthread.h>
#include <rtdevice.h>
#include <rthw.h>
#include "cdc.h"
#ifdef RT_USB_DEVICE_CDC
static uclass_t cdc;
static uep_t ep_in, ep_out, ep_cmd;
@@ -49,6 +50,20 @@ static struct udevice_descriptor dev_desc =
USB_DYNAMIC, //bNumConfigurations;
};
#ifdef RT_USB_DEVICE_COMPOSITE
static struct uiad_descriptor iad_desc =
{
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
/* communcation interface descriptor */
static struct ucdc_comm_descriptor comm_desc =
{
@@ -389,7 +404,10 @@ static rt_err_t _cdc_descriptor_config(rt_uint8_t comm, rt_uint8_t data)
comm_desc.call_mgmt_desc.data_interface = data;
comm_desc.union_desc.master_interface = comm;
comm_desc.union_desc.slave_interface0 = data;
#ifdef RT_USB_DEVICE_COMPOSITE
iad_desc.bFirstInterface = comm;
#endif
return RT_EOK;
}
@@ -453,7 +471,11 @@ uclass_t rt_usbd_class_cdc_create(udevice_t device)
/* add the communication interface to the cdc class */
rt_usbd_class_add_interface(cdc, intf_comm);
#ifdef RT_USB_DEVICE_COMPOSITE
rt_usbd_class_set_iad(cdc, &iad_desc);
#endif
return cdc;
}
@@ -550,3 +572,5 @@ void rt_usb_vcom_init(void)
RT_NULL);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,53 @@
/*
* 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
*/
#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;
#pragma pack()

View File

@@ -122,9 +122,13 @@ static rt_err_t _get_string_descriptor(struct udevice* device, ureq_t setup)
}
}
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,
str_desc.bLength);
dcd_ep_write(device->dcd, 0, (rt_uint8_t*)&str_desc, len);
return RT_EOK;
}
@@ -156,8 +160,11 @@ static rt_err_t _get_descriptor(struct udevice* device, ureq_t setup)
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("unknown descriptor\n");
rt_kprintf("unsupported descriptor request\n");
dcd_ep_stall(device->dcd, 0);
break;
}
@@ -768,6 +775,9 @@ uclass_t rt_usbd_class_create(udevice_t device, udev_desc_t dev_desc,
cls->dev_desc = dev_desc;
cls->ops = ops;
cls->device = device;
#ifdef RT_USB_DEVICE_COMPOSITE
cls->iad_desc = RT_NULL;
#endif
/* to initialize interface list */
rt_list_init(&cls->intf_list);
@@ -874,8 +884,7 @@ uconfig_t rt_usbd_find_config(udevice_t device, rt_uint8_t value)
* @return an usb configuration object on found or RT_NULL on not found.
*/
uintf_t rt_usbd_find_interface(udevice_t device, rt_uint8_t value)
{
uep_t ep;
{
struct rt_list_node *i, *j;
uclass_t cls;
uintf_t intf;
@@ -1008,6 +1017,16 @@ rt_err_t rt_usbd_device_add_config(udevice_t device, uconfig_t cfg)
for (i=cfg->cls_list.next; i!=&cfg->cls_list; i=i->next)
{
cls = (uclass_t)rt_list_entry(i, struct uclass, list);
#ifdef RT_USB_DEVICE_COMPOSITE
if(cls->iad_desc != RT_NULL)
{
rt_memcpy((void*)&cfg->cfg_desc.data[cfg->cfg_desc.wTotalLength -
USB_DESC_LENGTH_CONFIG], (void*)cls->iad_desc, USB_DESC_LENGTH_IAD);
cfg->cfg_desc.wTotalLength += USB_DESC_LENGTH_IAD;
}
#endif
for(j=cls->intf_list.next; j!=&cls->intf_list; j=j->next)
{
intf = (uintf_t)rt_list_entry(j, struct uinterface, list);
@@ -1020,7 +1039,7 @@ rt_err_t rt_usbd_device_add_config(udevice_t device, uconfig_t cfg)
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->intf_desc,
@@ -1080,6 +1099,19 @@ rt_err_t rt_usbd_class_add_interface(uclass_t cls, uintf_t intf)
return RT_EOK;
}
#ifdef RT_USB_DEVICE_COMPOSITE
rt_err_t rt_usbd_class_set_iad(uclass_t cls, uiad_desc_t iad_desc)
{
RT_ASSERT(cls != RT_NULL);
RT_ASSERT(iad_desc != RT_NULL);
cls->iad_desc = iad_desc;
return RT_TRUE;
}
#endif
/**
* This function will add an alternate setting to an interface.
*

View File

@@ -16,18 +16,36 @@
#include <rtdevice.h>
#include <rtservice.h>
#define RT_USB_DEVICE_CDC
const static char* ustring[] =
{
"Language",
"RT-Thread Team.",
"UDISK",
"12345678",
"Config",
"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;
@@ -56,22 +74,28 @@ rt_err_t rt_usb_device_init(const char* udc_name)
/* create a configuration object */
cfg = rt_usbd_config_create();
#if defined RT_USB_DEVICE_MASS_STORAGE
#ifdef RT_USB_DEVICE_MSTORAGE
/* create a mass storage class object */
cls = rt_usbd_class_mass_storage_create(udevice);
#elif defined RT_USB_DEVICE_CDC
/* create a cdc class object */
cls = rt_usbd_class_cdc_create(udevice);
#else
#error
#endif
/* set device descriptor to the device */
rt_usbd_device_set_descriptor(udevice, cls->dev_desc);
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
/* 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);