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:
parent
1b2d954105
commit
60c27fc4b5
|
@ -51,6 +51,7 @@ extern "C" {
|
||||||
#define USB_DESC_TYPE_ENDPOINT 0x05
|
#define USB_DESC_TYPE_ENDPOINT 0x05
|
||||||
#define USB_DESC_TYPE_DEVICEQUALIFIER 0x06
|
#define USB_DESC_TYPE_DEVICEQUALIFIER 0x06
|
||||||
#define USB_DESC_TYPE_OTHERSPEED 0x07
|
#define USB_DESC_TYPE_OTHERSPEED 0x07
|
||||||
|
#define USB_DESC_TYPE_IAD 0x0b
|
||||||
#define USB_DESC_TYPE_HID 0x21
|
#define USB_DESC_TYPE_HID 0x21
|
||||||
#define USB_DESC_TYPE_REPORT 0x22
|
#define USB_DESC_TYPE_REPORT 0x22
|
||||||
#define USB_DESC_TYPE_PHYSICAL 0x23
|
#define USB_DESC_TYPE_PHYSICAL 0x23
|
||||||
|
@ -58,6 +59,7 @@ extern "C" {
|
||||||
|
|
||||||
#define USB_DESC_LENGTH_DEVICE 0x12
|
#define USB_DESC_LENGTH_DEVICE 0x12
|
||||||
#define USB_DESC_LENGTH_CONFIG 0x9
|
#define USB_DESC_LENGTH_CONFIG 0x9
|
||||||
|
#define USB_DESC_LENGTH_IAD 0x8
|
||||||
#define USB_DESC_LENGTH_STRING 0x4
|
#define USB_DESC_LENGTH_STRING 0x4
|
||||||
#define USB_DESC_LENGTH_INTERFACE 0x9
|
#define USB_DESC_LENGTH_INTERFACE 0x9
|
||||||
#define USB_DESC_LENGTH_ENDPOINT 0x7
|
#define USB_DESC_LENGTH_ENDPOINT 0x7
|
||||||
|
@ -244,7 +246,7 @@ struct uconfig_descriptor
|
||||||
rt_uint8_t iConfiguration;
|
rt_uint8_t iConfiguration;
|
||||||
rt_uint8_t bmAttributes;
|
rt_uint8_t bmAttributes;
|
||||||
rt_uint8_t MaxPower;
|
rt_uint8_t MaxPower;
|
||||||
rt_uint8_t data[128];
|
rt_uint8_t data[256];
|
||||||
};
|
};
|
||||||
typedef struct uconfig_descriptor* ucfg_desc_t;
|
typedef struct uconfig_descriptor* ucfg_desc_t;
|
||||||
|
|
||||||
|
@ -263,7 +265,7 @@ struct uinterface_descriptor
|
||||||
typedef struct uinterface_descriptor* uintf_desc_t;
|
typedef struct uinterface_descriptor* uintf_desc_t;
|
||||||
|
|
||||||
/* Interface Association Descriptor (IAD) */
|
/* Interface Association Descriptor (IAD) */
|
||||||
struct uassco_descriptor
|
struct uiad_descriptor
|
||||||
{
|
{
|
||||||
rt_uint8_t bLength;
|
rt_uint8_t bLength;
|
||||||
rt_uint8_t bDescriptorType;
|
rt_uint8_t bDescriptorType;
|
||||||
|
@ -274,7 +276,7 @@ struct uassco_descriptor
|
||||||
rt_uint8_t bFunctionProtocol;
|
rt_uint8_t bFunctionProtocol;
|
||||||
rt_uint8_t iFunction;
|
rt_uint8_t iFunction;
|
||||||
};
|
};
|
||||||
typedef struct uassco_descriptor* uassco_desc_t;
|
typedef struct uiad_descriptor* uiad_desc_t;
|
||||||
|
|
||||||
struct uendpoint_descriptor
|
struct uendpoint_descriptor
|
||||||
{
|
{
|
||||||
|
@ -364,6 +366,9 @@ typedef struct ustorage_csw* ustorage_csw_t;
|
||||||
#define USBREQ_GET_MAX_LUN 0xfe
|
#define USBREQ_GET_MAX_LUN 0xfe
|
||||||
#define USBREQ_MASS_STORAGE_RESET 0xff
|
#define USBREQ_MASS_STORAGE_RESET 0xff
|
||||||
|
|
||||||
|
#define MIN(a, b) (a < b ? a : b)
|
||||||
|
#define MAX(a, b) (a > b ? a : b)
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -92,7 +92,9 @@ struct uclass
|
||||||
|
|
||||||
struct udevice* device;
|
struct udevice* device;
|
||||||
udev_desc_t dev_desc;
|
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;
|
rt_list_t intf_list;
|
||||||
};
|
};
|
||||||
typedef struct uclass* uclass_t;
|
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);
|
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_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_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_controller(udevice_t device, udcd_t dcd);
|
||||||
rt_err_t rt_usbd_device_set_descriptor(udevice_t device, udev_desc_t dev_desc);
|
rt_err_t rt_usbd_device_set_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);
|
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);
|
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);
|
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_inline rt_err_t dcd_set_address(udcd_t dcd, rt_uint8_t value)
|
||||||
{
|
{
|
||||||
RT_ASSERT(dcd != RT_NULL);
|
RT_ASSERT(dcd != RT_NULL);
|
||||||
|
|
|
@ -5,9 +5,14 @@ cwd = GetCurrentDir()
|
||||||
src = Split("""
|
src = Split("""
|
||||||
core/core.c
|
core/core.c
|
||||||
core/usbdevice.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]
|
CPPPATH = [cwd]
|
||||||
|
|
||||||
group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_USB_DEVICE'], CPPPATH = CPPPATH)
|
group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_USB_DEVICE'], CPPPATH = CPPPATH)
|
||||||
|
|
|
@ -15,9 +15,10 @@
|
||||||
#include <rtthread.h>
|
#include <rtthread.h>
|
||||||
#include <rtdevice.h>
|
#include <rtdevice.h>
|
||||||
#include <rthw.h>
|
#include <rthw.h>
|
||||||
|
|
||||||
#include "cdc.h"
|
#include "cdc.h"
|
||||||
|
|
||||||
|
#ifdef RT_USB_DEVICE_CDC
|
||||||
|
|
||||||
static uclass_t cdc;
|
static uclass_t cdc;
|
||||||
static uep_t ep_in, ep_out, ep_cmd;
|
static uep_t ep_in, ep_out, ep_cmd;
|
||||||
|
|
||||||
|
@ -49,6 +50,20 @@ static struct udevice_descriptor dev_desc =
|
||||||
USB_DYNAMIC, //bNumConfigurations;
|
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 */
|
/* communcation interface descriptor */
|
||||||
static struct ucdc_comm_descriptor comm_desc =
|
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.call_mgmt_desc.data_interface = data;
|
||||||
comm_desc.union_desc.master_interface = comm;
|
comm_desc.union_desc.master_interface = comm;
|
||||||
comm_desc.union_desc.slave_interface0 = data;
|
comm_desc.union_desc.slave_interface0 = data;
|
||||||
|
#ifdef RT_USB_DEVICE_COMPOSITE
|
||||||
|
iad_desc.bFirstInterface = comm;
|
||||||
|
#endif
|
||||||
|
|
||||||
return RT_EOK;
|
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 */
|
/* add the communication interface to the cdc class */
|
||||||
rt_usbd_class_add_interface(cdc, intf_comm);
|
rt_usbd_class_add_interface(cdc, intf_comm);
|
||||||
|
|
||||||
|
#ifdef RT_USB_DEVICE_COMPOSITE
|
||||||
|
rt_usbd_class_set_iad(cdc, &iad_desc);
|
||||||
|
#endif
|
||||||
|
|
||||||
return cdc;
|
return cdc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,3 +572,5 @@ void rt_usb_vcom_init(void)
|
||||||
RT_NULL);
|
RT_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,544 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
static uclass_t mstorage;
|
||||||
|
static uep_t ep_in, ep_out;
|
||||||
|
static rt_uint8_t *buffer;
|
||||||
|
static rt_uint8_t *write_ptr;
|
||||||
|
static int status = STATUS_CBW;
|
||||||
|
static struct ustorage_csw csw;
|
||||||
|
static rt_device_t disk;
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
rt_uint32_t block;
|
||||||
|
rt_uint32_t count;
|
||||||
|
|
||||||
|
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, buffer, count);
|
||||||
|
dcd_ep_write(device->dcd, ep_in, buffer, count * geometry.bytes_per_sector);
|
||||||
|
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_uint32_t _block;
|
||||||
|
static rt_uint32_t _count, _size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
write_ptr = buffer;
|
||||||
|
|
||||||
|
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, buffer, MIN(_size, 4096));
|
||||||
|
|
||||||
|
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, rt_size_t size)
|
||||||
|
{
|
||||||
|
RT_ASSERT(device != RT_NULL);
|
||||||
|
|
||||||
|
if(status == STATUS_CSW)
|
||||||
|
{
|
||||||
|
dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&csw, SIZEOF_CSW);
|
||||||
|
status = STATUS_CBW;
|
||||||
|
dcd_ep_read(device->dcd, ep_out, ep_out->buffer, SIZEOF_CBW);
|
||||||
|
}
|
||||||
|
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
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]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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, rt_size_t size)
|
||||||
|
{
|
||||||
|
RT_ASSERT(device != RT_NULL);
|
||||||
|
|
||||||
|
if(status == STATUS_CBW)
|
||||||
|
{
|
||||||
|
struct ustorage_cbw* cbw;
|
||||||
|
|
||||||
|
/* dump cbw information */
|
||||||
|
cbw = (struct ustorage_cbw*)ep_out->buffer;
|
||||||
|
|
||||||
|
if(cbw->signature == CBW_SIGNATURE)
|
||||||
|
{
|
||||||
|
csw.signature = CSW_SIGNATURE;
|
||||||
|
csw.tag = cbw->tag;
|
||||||
|
csw.data_reside = 0;
|
||||||
|
csw.status = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(cbw->cb[0])
|
||||||
|
{
|
||||||
|
case SCSI_TEST_UNIT_READY:
|
||||||
|
dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&csw, SIZEOF_CSW);
|
||||||
|
dcd_ep_read(device->dcd, ep_out, ep_out->buffer, SIZEOF_CBW);
|
||||||
|
break;
|
||||||
|
case SCSI_REQUEST_SENSE:
|
||||||
|
_request_sense(device);
|
||||||
|
status = STATUS_CSW;
|
||||||
|
break;
|
||||||
|
case SCSI_INQUIRY_CMD:
|
||||||
|
_inquiry_cmd(device);
|
||||||
|
status = STATUS_CSW;
|
||||||
|
break;
|
||||||
|
case SCSI_MODE_SENSE_6:
|
||||||
|
_mode_sense_6(device);
|
||||||
|
status = STATUS_CSW;
|
||||||
|
break;
|
||||||
|
case SCSI_ALLOW_MEDIUM_REMOVAL:
|
||||||
|
dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&csw, SIZEOF_CSW);
|
||||||
|
dcd_ep_read(device->dcd, ep_out, ep_out->buffer, SIZEOF_CBW);
|
||||||
|
break;
|
||||||
|
case SCSI_READ_CAPACITIES:
|
||||||
|
_read_capacities(device);
|
||||||
|
status = STATUS_CSW;
|
||||||
|
break;
|
||||||
|
case SCSI_READ_CAPACITY:
|
||||||
|
_read_capacity(device);
|
||||||
|
status = STATUS_CSW;
|
||||||
|
break;
|
||||||
|
case SCSI_READ_10:
|
||||||
|
_read_10(device, cbw);
|
||||||
|
status = STATUS_CSW;
|
||||||
|
break;
|
||||||
|
case SCSI_WRITE_10:
|
||||||
|
_write_10(device, cbw);
|
||||||
|
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;
|
||||||
|
write_ptr += size;
|
||||||
|
csw.data_reside -= size;
|
||||||
|
if(_size == 0)
|
||||||
|
{
|
||||||
|
rt_device_write(disk, _block, buffer, _count);
|
||||||
|
dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&csw, SIZEOF_CSW);
|
||||||
|
dcd_ep_read(device->dcd, ep_out, ep_out->buffer, SIZEOF_CBW);
|
||||||
|
status = STATUS_CBW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dcd_ep_read(device->dcd, ep_out, write_ptr, MIN(_size, 4096));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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, 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)
|
||||||
|
{
|
||||||
|
RT_ASSERT(device != RT_NULL);
|
||||||
|
|
||||||
|
RT_DEBUG_LOG(RT_DEBUG_USB, ("mass storage run\n"));
|
||||||
|
|
||||||
|
disk = rt_device_find(RT_USB_MSTORAGE_DISK_NAME);
|
||||||
|
RT_ASSERT(disk != RT_NULL);
|
||||||
|
|
||||||
|
buffer = (rt_uint8_t*)rt_malloc(RT_USB_MSTORAGE_BUFFER_SIZE);
|
||||||
|
|
||||||
|
rt_device_control(disk, RT_DEVICE_CTRL_BLK_GETGEOME, (void*)&geometry);
|
||||||
|
dcd_ep_read(device->dcd, ep_out, 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)
|
||||||
|
{
|
||||||
|
RT_ASSERT(device != RT_NULL);
|
||||||
|
|
||||||
|
RT_DEBUG_LOG(RT_DEBUG_USB, ("mass storage stop\n"));
|
||||||
|
|
||||||
|
rt_free(buffer);
|
||||||
|
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;
|
||||||
|
ualtsetting_t setting;
|
||||||
|
|
||||||
|
/* parameter check */
|
||||||
|
RT_ASSERT(device != RT_NULL);
|
||||||
|
|
||||||
|
/* create a mass storage class */
|
||||||
|
mstorage = rt_usbd_class_create(device, &dev_desc, &ops);
|
||||||
|
|
||||||
|
/* create an interface */
|
||||||
|
intf = rt_usbd_interface_create(device, _interface_handler);
|
||||||
|
|
||||||
|
/* create a bulk out and a bulk in endpoint */
|
||||||
|
ep_in = rt_usbd_endpoint_create(&mass_desc.ep_in_desc, _ep_in_handler);
|
||||||
|
ep_out = rt_usbd_endpoint_create(&mass_desc.ep_out_desc, _ep_out_handler);
|
||||||
|
|
||||||
|
/* create an alternate setting */
|
||||||
|
setting = rt_usbd_altsetting_create(&mass_desc.intf_desc,
|
||||||
|
sizeof(struct umass_descriptor));
|
||||||
|
|
||||||
|
/* add the bulk out and bulk in endpoint to the alternate setting */
|
||||||
|
rt_usbd_altsetting_add_endpoint(setting, ep_out);
|
||||||
|
rt_usbd_altsetting_add_endpoint(setting, 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
|
|
@ -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()
|
||||||
|
|
|
@ -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 */
|
/* send string descriptor to endpoint 0 */
|
||||||
dcd_ep_write(device->dcd, 0, (rt_uint8_t*)&str_desc,
|
dcd_ep_write(device->dcd, 0, (rt_uint8_t*)&str_desc, len);
|
||||||
str_desc.bLength);
|
|
||||||
|
|
||||||
return RT_EOK;
|
return RT_EOK;
|
||||||
}
|
}
|
||||||
|
@ -156,8 +160,11 @@ static rt_err_t _get_descriptor(struct udevice* device, ureq_t setup)
|
||||||
case USB_DESC_TYPE_STRING:
|
case USB_DESC_TYPE_STRING:
|
||||||
_get_string_descriptor(device, setup);
|
_get_string_descriptor(device, setup);
|
||||||
break;
|
break;
|
||||||
|
case USB_DESC_TYPE_DEVICEQUALIFIER:
|
||||||
|
dcd_ep_stall(device->dcd, 0);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
rt_kprintf("unknown descriptor\n");
|
rt_kprintf("unsupported descriptor request\n");
|
||||||
dcd_ep_stall(device->dcd, 0);
|
dcd_ep_stall(device->dcd, 0);
|
||||||
break;
|
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->dev_desc = dev_desc;
|
||||||
cls->ops = ops;
|
cls->ops = ops;
|
||||||
cls->device = device;
|
cls->device = device;
|
||||||
|
#ifdef RT_USB_DEVICE_COMPOSITE
|
||||||
|
cls->iad_desc = RT_NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* to initialize interface list */
|
/* to initialize interface list */
|
||||||
rt_list_init(&cls->intf_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.
|
* @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)
|
uintf_t rt_usbd_find_interface(udevice_t device, rt_uint8_t value)
|
||||||
{
|
{
|
||||||
uep_t ep;
|
|
||||||
struct rt_list_node *i, *j;
|
struct rt_list_node *i, *j;
|
||||||
uclass_t cls;
|
uclass_t cls;
|
||||||
uintf_t intf;
|
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)
|
for (i=cfg->cls_list.next; i!=&cfg->cls_list; i=i->next)
|
||||||
{
|
{
|
||||||
cls = (uclass_t)rt_list_entry(i, struct uclass, list);
|
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)
|
for(j=cls->intf_list.next; j!=&cls->intf_list; j=j->next)
|
||||||
{
|
{
|
||||||
intf = (uintf_t)rt_list_entry(j, struct uinterface, list);
|
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);
|
ep = (uep_t)rt_list_entry(k, struct uendpoint, list);
|
||||||
dcd_ep_alloc(device->dcd, ep);
|
dcd_ep_alloc(device->dcd, ep);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* construct complete configuration descriptor */
|
/* construct complete configuration descriptor */
|
||||||
rt_memcpy((void*)&cfg->cfg_desc.data[cfg->cfg_desc.wTotalLength -
|
rt_memcpy((void*)&cfg->cfg_desc.data[cfg->cfg_desc.wTotalLength -
|
||||||
USB_DESC_LENGTH_CONFIG], (void*)intf->curr_setting->intf_desc,
|
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;
|
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.
|
* This function will add an alternate setting to an interface.
|
||||||
*
|
*
|
||||||
|
|
|
@ -16,18 +16,36 @@
|
||||||
#include <rtdevice.h>
|
#include <rtdevice.h>
|
||||||
#include <rtservice.h>
|
#include <rtservice.h>
|
||||||
|
|
||||||
#define RT_USB_DEVICE_CDC
|
|
||||||
|
|
||||||
const static char* ustring[] =
|
const static char* ustring[] =
|
||||||
{
|
{
|
||||||
"Language",
|
"Language",
|
||||||
"RT-Thread Team.",
|
"RT-Thread Team.",
|
||||||
"UDISK",
|
"RT-Thread Device",
|
||||||
"12345678",
|
"1.1.0",
|
||||||
"Config",
|
"Configuration",
|
||||||
"Interface",
|
"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_err_t rt_usb_device_init(const char* udc_name)
|
||||||
{
|
{
|
||||||
rt_device_t udc;
|
rt_device_t udc;
|
||||||
|
@ -56,22 +74,28 @@ rt_err_t rt_usb_device_init(const char* udc_name)
|
||||||
/* create a configuration object */
|
/* create a configuration object */
|
||||||
cfg = rt_usbd_config_create();
|
cfg = rt_usbd_config_create();
|
||||||
|
|
||||||
#if defined RT_USB_DEVICE_MASS_STORAGE
|
#ifdef RT_USB_DEVICE_MSTORAGE
|
||||||
/* create a mass storage class object */
|
/* create a mass storage class object */
|
||||||
cls = rt_usbd_class_mass_storage_create(udevice);
|
cls = rt_usbd_class_mstorage_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);
|
|
||||||
|
|
||||||
/* add the class to the configuration */
|
/* add the class to the configuration */
|
||||||
rt_usbd_config_add_class(cfg, cls);
|
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 */
|
/* add the configuration to the device */
|
||||||
rt_usbd_device_add_config(udevice, cfg);
|
rt_usbd_device_add_config(udevice, cfg);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue