diff options
Diffstat (limited to 'components/drivers/usb')
| -rw-r--r-- | components/drivers/usb/usbdevice/SConscript | 7 | ||||
| -rw-r--r-- | components/drivers/usb/usbdevice/class/cdc_vcom.c | 30 | ||||
| -rw-r--r-- | components/drivers/usb/usbdevice/class/mstorage.c | 544 | ||||
| -rw-r--r-- | components/drivers/usb/usbdevice/class/mstorage.h | 53 | ||||
| -rw-r--r-- | components/drivers/usb/usbdevice/core/core.c | 44 | ||||
| -rw-r--r-- | components/drivers/usb/usbdevice/core/usbdevice.c | 52 |
6 files changed, 706 insertions, 24 deletions
diff --git a/components/drivers/usb/usbdevice/SConscript b/components/drivers/usb/usbdevice/SConscript index 75d651f902..6cb9d0f5d9 100644 --- a/components/drivers/usb/usbdevice/SConscript +++ b/components/drivers/usb/usbdevice/SConscript @@ -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)
diff --git a/components/drivers/usb/usbdevice/class/cdc_vcom.c b/components/drivers/usb/usbdevice/class/cdc_vcom.c index 6228370e16..4276b57c4c 100644 --- a/components/drivers/usb/usbdevice/class/cdc_vcom.c +++ b/components/drivers/usb/usbdevice/class/cdc_vcom.c @@ -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
+
diff --git a/components/drivers/usb/usbdevice/class/mstorage.c b/components/drivers/usb/usbdevice/class/mstorage.c new file mode 100644 index 0000000000..a8844ddf85 --- /dev/null +++ b/components/drivers/usb/usbdevice/class/mstorage.c @@ -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
diff --git a/components/drivers/usb/usbdevice/class/mstorage.h b/components/drivers/usb/usbdevice/class/mstorage.h new file mode 100644 index 0000000000..2ff74e6494 --- /dev/null +++ b/components/drivers/usb/usbdevice/class/mstorage.h @@ -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()
+
diff --git a/components/drivers/usb/usbdevice/core/core.c b/components/drivers/usb/usbdevice/core/core.c index cfd11cd485..13da280c17 100644 --- a/components/drivers/usb/usbdevice/core/core.c +++ b/components/drivers/usb/usbdevice/core/core.c @@ -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.
*
diff --git a/components/drivers/usb/usbdevice/core/usbdevice.c b/components/drivers/usb/usbdevice/core/usbdevice.c index e2af11a3da..fb7813eeed 100644 --- a/components/drivers/usb/usbdevice/core/usbdevice.c +++ b/components/drivers/usb/usbdevice/core/usbdevice.c @@ -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
+ 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);
-#else
- #error
+ 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 class to the configuration */
- rt_usbd_config_add_class(cfg, cls);
-
/* add the configuration to the device */
rt_usbd_device_add_config(udevice, cfg);
|
