summaryrefslogtreecommitdiff
path: root/components/drivers/usb/usbdevice/class
diff options
context:
space:
mode:
authorshaolin <[email protected]>2014-02-16 17:42:35 +0800
committershaolin <[email protected]>2014-02-16 17:42:35 +0800
commit8fd0a7f9c61dde28d90ec4c3661e9e0e8327f7fc (patch)
treeb9b8491531d8354850c598d826010491b63e86c5 /components/drivers/usb/usbdevice/class
parentdb02f56283d17125917254e470997c63492b6862 (diff)
Update USB Device Stack to support more device controllers;
Pass USB CV test verification; Code cleanup;
Diffstat (limited to 'components/drivers/usb/usbdevice/class')
-rw-r--r--components/drivers/usb/usbdevice/class/cdc_vcom.c557
-rw-r--r--components/drivers/usb/usbdevice/class/mstorage.c1031
-rw-r--r--components/drivers/usb/usbdevice/class/mstorage.h7
3 files changed, 1044 insertions, 551 deletions
diff --git a/components/drivers/usb/usbdevice/class/cdc_vcom.c b/components/drivers/usb/usbdevice/class/cdc_vcom.c
index 5f284b0294..33f9f7abef 100644
--- a/components/drivers/usb/usbdevice/class/cdc_vcom.c
+++ b/components/drivers/usb/usbdevice/class/cdc_vcom.c
@@ -20,34 +20,56 @@
* Change Logs:
* Date Author Notes
* 2012-10-02 Yi Qiu first version
- * 2012-12-12 heyuanjie87 change endpoints and class handler
+ * 2012-12-12 heyuanjie87 change endpoints and function handler
+ * 2013-06-25 heyuanjie87 remove SOF mechinism
+ * 2013-07-20 Yi Qiu do more test
*/
#include <rtthread.h>
+#include <rtservice.h>
#include <rtdevice.h>
#include <rthw.h>
#include "cdc.h"
#ifdef RT_USB_DEVICE_CDC
+#define TX_TIMEOUT 100
#define CDC_RX_BUFSIZE 2048
-#define CDC_TX_BUFSIZE 2048
-static rt_uint8_t rx_rbp[CDC_RX_BUFSIZE];
-static rt_uint8_t tx_rbp[CDC_TX_BUFSIZE];
-static struct rt_ringbuffer rx_ringbuffer;
-static struct rt_ringbuffer tx_ringbuffer;
-static struct serial_ringbuffer vcom_int_rx;
+#define CDC_MAX_PACKET_SIZE 64
+#define VCOM_DEVICE "vcom"
-static struct rt_serial_device vcom_serial;
-
-#define CDC_MaxPacketSize 64
-ALIGN(RT_ALIGN_SIZE)
-static rt_uint8_t rx_buf[CDC_RX_BUFSIZE];
ALIGN(RT_ALIGN_SIZE)
-static rt_uint8_t tx_buf[CDC_TX_BUFSIZE];
+static rt_uint8_t vcom_thread_stack[512];
+static struct rt_thread vcom_thread;
+#define VCOM_MQ_MSG_SZ 16
+#define VCOM_MQ_MAX_MSG 4
+/* internal of the message queue: every message is associated with a pointer,
+ * so in order to recveive VCOM_MQ_MAX_MSG messages, we have to allocate more
+ * than VCOM_MQ_MSG_SZ*VCOM_MQ_MAX_MSG memery. */
+static rt_uint8_t vcom_tx_thread_mq_pool[(VCOM_MQ_MSG_SZ+sizeof(void*))*VCOM_MQ_MAX_MSG];
+static struct rt_messagequeue vcom_tx_thread_mq;
+static struct ucdc_line_coding line_coding;
-volatile static rt_bool_t vcom_connected = RT_FALSE;
-volatile static rt_bool_t vcom_in_sending = RT_FALSE;
+struct vcom
+{
+ struct rt_serial_device serial;
+ uep_t ep_out;
+ uep_t ep_in;
+ uep_t ep_cmd;
+ rt_bool_t connected;
+ rt_bool_t in_sending;
+ struct rt_completion wait;
+ rt_uint8_t rx_rbp[CDC_RX_BUFSIZE];
+ struct rt_ringbuffer rx_ringbuffer;
+ struct serial_ringbuffer vcom_int_rx;
+};
+
+struct vcom_tx_msg
+{
+ struct rt_serial_device * serial;
+ const char *buf;
+ rt_size_t size;
+};
static struct udevice_descriptor dev_desc =
{
@@ -57,7 +79,7 @@ static struct udevice_descriptor dev_desc =
USB_CLASS_CDC, //bDeviceClass;
0x00, //bDeviceSubClass;
0x00, //bDeviceProtocol;
- CDC_MaxPacketSize, //bMaxPacketSize0;
+ CDC_MAX_PACKET_SIZE, //bMaxPacketSize0;
_VENDOR_ID, //idVendor;
_PRODUCT_ID, //idProduct;
USB_BCD_DEVICE, //bcdDevice;
@@ -67,6 +89,18 @@ static struct udevice_descriptor dev_desc =
USB_DYNAMIC, //bNumConfigurations;
};
+static struct usb_qualifier_descriptor dev_qualifier =
+{
+ sizeof(dev_qualifier),
+ USB_DESC_TYPE_DEVICEQUALIFIER,
+ 0x0200,
+ USB_CLASS_CDC,
+ 0x00,
+ 64,
+ 0x01,
+ 0,
+};
+
/* communcation interface descriptor */
const static struct ucdc_comm_descriptor _comm_desc =
{
@@ -85,19 +119,19 @@ const static struct ucdc_comm_descriptor _comm_desc =
USB_DESC_LENGTH_INTERFACE,
USB_DESC_TYPE_INTERFACE,
USB_DYNAMIC,
- 0x00,
+ 0x00,
0x01,
USB_CDC_CLASS_COMM,
USB_CDC_SUBCLASS_ACM,
USB_CDC_PROTOCOL_V25TER,
0x00,
- /* Header Functional Descriptor */
- 0x05,
+ /* Header Functional Descriptor */
+ 0x05,
USB_CDC_CS_INTERFACE,
USB_CDC_SCS_HEADER,
0x0110,
- /* Call Management Functional Descriptor */
- 0x05,
+ /* Call Management Functional Descriptor */
+ 0x05,
USB_CDC_CS_INTERFACE,
USB_CDC_SCS_CALL_MGMT,
0x00,
@@ -107,13 +141,13 @@ const static struct ucdc_comm_descriptor _comm_desc =
USB_CDC_CS_INTERFACE,
USB_CDC_SCS_ACM,
0x02,
- /* Union Functional Descriptor */
+ /* Union Functional Descriptor */
0x05,
USB_CDC_CS_INTERFACE,
USB_CDC_SCS_UNION,
USB_DYNAMIC,
USB_DYNAMIC,
- /* Endpoint Descriptor */
+ /* Endpoint Descriptor */
USB_DESC_LENGTH_ENDPOINT,
USB_DESC_TYPE_ENDPOINT,
USB_DYNAMIC | USB_DIR_IN,
@@ -130,23 +164,23 @@ const static struct ucdc_data_descriptor _data_desc =
USB_DESC_TYPE_INTERFACE,
USB_DYNAMIC,
0x00,
- 0x02,
+ 0x02,
USB_CDC_CLASS_DATA,
- 0x00,
- 0x00,
- 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
/* endpoint, bulk out */
- USB_DESC_LENGTH_ENDPOINT,
+ USB_DESC_LENGTH_ENDPOINT,
USB_DESC_TYPE_ENDPOINT,
USB_DYNAMIC | USB_DIR_OUT,
- USB_EP_ATTR_BULK,
+ USB_EP_ATTR_BULK,
USB_CDC_BUFSIZE,
- 0x00,
+ 0x00,
/* endpoint, bulk in */
USB_DESC_LENGTH_ENDPOINT,
USB_DESC_TYPE_ENDPOINT,
USB_DYNAMIC | USB_DIR_IN,
- USB_EP_ATTR_BULK,
+ USB_EP_ATTR_BULK,
USB_CDC_BUFSIZE,
0x00,
};
@@ -156,18 +190,24 @@ const static char* _ustring[] =
"Language",
"RT-Thread Team.",
"RTT Virtual Serial",
- "1.1.0",
+ "32021919830108",
"Configuration",
"Interface",
};
+static void rt_usb_vcom_init(struct ufunction *func);
-static void _vcom_reset_state(void)
+static void _vcom_reset_state(ufunction_t func)
{
- int lvl = rt_hw_interrupt_disable();
- tx_ringbuffer.read_mirror = tx_ringbuffer.read_index = 0;
- tx_ringbuffer.write_mirror = tx_ringbuffer.write_index = 0;
- vcom_connected = RT_FALSE;
- vcom_in_sending = RT_FALSE;
+ struct vcom* data;
+ int lvl;
+
+ RT_ASSERT(func != RT_NULL)
+
+ data = (struct vcom*)func->user_data;
+
+ lvl = rt_hw_interrupt_disable();
+ data->connected = RT_FALSE;
+ data->in_sending = RT_FALSE;
/*rt_kprintf("reset USB serial\n", cnt);*/
rt_hw_interrupt_enable(lvl);
}
@@ -175,95 +215,73 @@ static void _vcom_reset_state(void)
/**
* This function will handle cdc bulk in endpoint request.
*
- * @param device the usb device object.
+ * @param func the usb function 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)
+static rt_err_t _ep_in_handler(ufunction_t func, rt_size_t size)
{
- rt_uint32_t level;
- rt_uint32_t remain;
- cdc_eps_t eps;
-
- eps = (cdc_eps_t)cls->eps;
- level = rt_hw_interrupt_disable();
- remain = rt_ringbuffer_data_len(&tx_ringbuffer);
- if (remain != 0)
- {
- /* although vcom_in_sending is set in SOF handler in the very
- * beginning, we have to guarantee the state is right when start
- * sending. There is at least one extreme case where we have finished the
- * last IN transaction but the vcom_in_sending is RT_FALSE.
- *
- * Ok, what the extreme case is: pour data into vcom in loop. Open
- * terminal on the PC, you will see the data. Then close it. So the
- * data will be sent to the PC in the back. When the buffer of the PC
- * driver is full. It will not send IN packet to the board and you will
- * have no chance to clear vcom_in_sending in this function. The data
- * will fill into the ringbuffer until it is full, and we will reset
- * the state machine and clear vcom_in_sending. When you open the
- * terminal on the PC again. The IN packet will appear on the line and
- * we will, eventually, reach here with vcom_in_sending is clear.
- */
- vcom_in_sending = RT_TRUE;
- rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, remain);
- rt_hw_interrupt_enable(level);
+ struct vcom *data;
- /* send data to host */
- dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, remain);
+ RT_ASSERT(func != RT_NULL);
- return RT_EOK;
- }
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_in_handler %d\n", size));
- if (size != 0 &&
- (size % CDC_MaxPacketSize) == 0)
+ data = (struct vcom*)func->user_data;
+ if ((size != 0) && (size % CDC_MAX_PACKET_SIZE == 0))
{
/* don't have data right now. Send a zero-length-packet to
* terminate the transaction.
*
* FIXME: actually, this might not be the right place to send zlp.
* Only the rt_device_write could know how much data is sending. */
- vcom_in_sending = RT_TRUE;
- rt_hw_interrupt_enable(level);
- dcd_ep_write(device->dcd, eps->ep_in, RT_NULL, 0);
- return RT_EOK;
- }
- else
- {
- vcom_in_sending = RT_FALSE;
- rt_hw_interrupt_enable(level);
+ data->in_sending = RT_TRUE;
+
+ data->ep_in->request.buffer = RT_NULL;
+ data->ep_in->request.size = 0;
+ data->ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
+
return RT_EOK;
}
+
+ rt_completion_done(&data->wait);
+
+ return RT_EOK;
}
/**
* This function will handle cdc bulk out endpoint request.
*
- * @param device the usb device object.
+ * @param func the usb function 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)
+static rt_err_t _ep_out_handler(ufunction_t func, rt_size_t size)
{
rt_uint32_t level;
- cdc_eps_t eps;
+ struct vcom *data;
- RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(func != RT_NULL);
- eps = (cdc_eps_t)cls->eps;
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_out_handler %d\n", size));
+
+ data = (struct vcom*)func->user_data;
/* receive data from USB VCOM */
level = rt_hw_interrupt_disable();
- rt_ringbuffer_put(&rx_ringbuffer, eps->ep_out->buffer, size);
+ rt_ringbuffer_put(&data->rx_ringbuffer, data->ep_out->buffer, size);
rt_hw_interrupt_enable(level);
/* notify receive data */
- rt_hw_serial_isr(&vcom_serial);
+ rt_hw_serial_isr(&data->serial);
- dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer,
- eps->ep_out->ep_desc->wMaxPacketSize);
+ data->ep_out->request.buffer = data->ep_out->buffer;
+ data->ep_out->request.size = EP_MAXPACKET(data->ep_out);
+ data->ep_out->request.req_type = UIO_REQUEST_READ_BEST;
+ rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
return RT_EOK;
}
@@ -276,9 +294,9 @@ static rt_err_t _ep_out_handler(udevice_t device, uclass_t cls, rt_size_t size)
*
* @return RT_EOK.
*/
-static rt_err_t _ep_cmd_handler(udevice_t device, uclass_t cls, rt_size_t size)
+static rt_err_t _ep_cmd_handler(ufunction_t func, rt_size_t size)
{
- RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(func != RT_NULL);
RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_cmd_handler\n"));
@@ -301,14 +319,25 @@ static rt_err_t _cdc_get_line_coding(udevice_t device, ureq_t setup)
RT_ASSERT(device != RT_NULL);
RT_ASSERT(setup != RT_NULL);
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_cdc_get_line_coding\n"));
+
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);
+ rt_usbd_ep0_write(device, (void*)&data, size);
+
+ return RT_EOK;
+}
+
+static rt_err_t _cdc_set_line_coding_callback(udevice_t device, rt_size_t size)
+{
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_cdc_set_line_coding_callback\n"));
+ dcd_ep0_send_status(device->dcd);
+
return RT_EOK;
}
@@ -322,21 +351,13 @@ static rt_err_t _cdc_get_line_coding(udevice_t device, ureq_t setup)
*/
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);
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_cdc_set_line_coding\n"));
- 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");
- }
+ rt_usbd_ep0_read(device, (void*)&line_coding, sizeof(struct ucdc_line_coding),
+ _cdc_set_line_coding_callback);
return RT_EOK;
}
@@ -349,11 +370,16 @@ static rt_err_t _cdc_set_line_coding(udevice_t device, ureq_t setup)
*
* @return RT_EOK on successful.
*/
-static rt_err_t _interface_handler(udevice_t device, uclass_t cls, ureq_t setup)
+static rt_err_t _interface_handler(ufunction_t func, ureq_t setup)
{
- RT_ASSERT(device != RT_NULL);
+ struct vcom *data;
+
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
RT_ASSERT(setup != RT_NULL);
+ data = (struct vcom*)func->user_data;
+
switch(setup->request)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
@@ -367,14 +393,14 @@ static rt_err_t _interface_handler(udevice_t device, uclass_t cls, ureq_t setup)
case CDC_CLEAR_COMM_FEATURE:
break;
case CDC_SET_LINE_CODING:
- _cdc_set_line_coding(device, setup);
- vcom_connected = RT_TRUE;
+ _cdc_set_line_coding(func->device, setup);
+ data->connected = RT_TRUE;
break;
case CDC_GET_LINE_CODING:
- _cdc_get_line_coding(device, setup);
+ _cdc_get_line_coding(func->device, setup);
break;
case CDC_SET_CONTROL_LINE_STATE:
- dcd_send_status(device->dcd);
+ dcd_ep0_send_status(func->device->dcd);
break;
case CDC_SEND_BREAK:
break;
@@ -387,92 +413,66 @@ static rt_err_t _interface_handler(udevice_t device, uclass_t cls, ureq_t setup)
}
/**
- * This function will run cdc class, it will be called on handle set configuration request.
+ * This function will run cdc function, it will be called on handle set configuration request.
*
- * @param device the usb device object.
+ * @param func the usb function object.
*
* @return RT_EOK on successful.
*/
-static rt_err_t _class_run(udevice_t device, uclass_t cls)
+static rt_err_t _function_enable(ufunction_t func)
{
- 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;
+ struct vcom *data;
- eps->ep_in->buffer = tx_buf;
- eps->ep_out->buffer = rx_buf;
+ RT_ASSERT(func != RT_NULL);
- _vcom_reset_state();
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("cdc function enable\n"));
- dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer,
- eps->ep_out->ep_desc->wMaxPacketSize);
+ _vcom_reset_state(func);
+
+ data = (struct vcom*)func->user_data;
+ data->ep_out->buffer = rt_malloc(CDC_RX_BUFSIZE);
+ data->ep_out->request.buffer = data->ep_out->buffer;
+ data->ep_out->request.size = EP_MAXPACKET(data->ep_out);
+
+ data->ep_out->request.req_type = UIO_REQUEST_READ_BEST;
+ rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
+
return RT_EOK;
}
/**
- * This function will stop cdc class, it will be called on handle set configuration request.
+ * This function will stop cdc function, it will be called on handle set configuration request.
*
- * @param device the usb device object.
+ * @param func the usb function object.
*
* @return RT_EOK on successful.
*/
-static rt_err_t _class_stop(udevice_t device, uclass_t cls)
+static rt_err_t _function_disable(ufunction_t func)
{
- RT_ASSERT(device != RT_NULL);
+ struct vcom *data;
- RT_DEBUG_LOG(RT_DEBUG_USB, ("cdc class stop\n"));
+ RT_ASSERT(func != RT_NULL);
- _vcom_reset_state();
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("cdc function disable\n"));
- return RT_EOK;
-}
+ _vcom_reset_state(func);
-/**
- * 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;
- cdc_eps_t eps;
-
- if (vcom_connected != RT_TRUE)
- return -RT_ERROR;
-
- if (vcom_in_sending)
+ data = (struct vcom*)func->user_data;
+ if(data->ep_out->buffer != RT_NULL)
{
- return RT_EOK;
+ rt_free(data->ep_out->buffer);
+ data->ep_out->buffer = RT_NULL;
}
- eps = (cdc_eps_t)cls->eps;
-
- size = rt_ringbuffer_data_len(&tx_ringbuffer);
- if (size == 0)
- return -RT_EFULL;
-
- level = rt_hw_interrupt_disable();
- rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, size);
- rt_hw_interrupt_enable(level);
-
- /* send data to host */
- vcom_in_sending = RT_TRUE;
- dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, size);
-
return RT_EOK;
}
-static struct uclass_ops ops =
+static struct ufunction_ops ops =
{
- _class_run,
- _class_stop,
- _class_sof_handler,
+ _function_enable,
+ _function_disable,
+ RT_NULL,
};
/**
@@ -483,7 +483,8 @@ static struct uclass_ops ops =
*
* @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)
+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;
@@ -496,16 +497,16 @@ static rt_err_t _cdc_descriptor_config(ucdc_comm_desc_t comm, rt_uint8_t cintf_n
}
/**
- * This function will create a cdc class instance.
+ * This function will create a cdc function instance.
*
* @param device the usb device object.
*
* @return RT_EOK on successful.
*/
-uclass_t rt_usbd_class_cdc_create(udevice_t device)
+ufunction_t rt_usbd_function_cdc_create(udevice_t device)
{
- uclass_t cdc;
- cdc_eps_t eps;
+ ufunction_t func;
+ struct vcom* data;
uintf_t intf_comm, intf_data;
ualtsetting_t comm_setting, data_setting;
ucdc_data_desc_t data_desc;
@@ -516,19 +517,26 @@ uclass_t rt_usbd_class_cdc_create(udevice_t device)
/* set usb device string description */
rt_usbd_device_set_string(device, _ustring);
- /* 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 function */
+ func = rt_usbd_function_new(device, &dev_desc, &ops);
+ rt_usbd_device_set_qualifier(device, &dev_qualifier);
+
+ /* allocate memory for cdc vcom data */
+ data = (struct vcom*)rt_malloc(sizeof(struct vcom));
+ rt_memset(data, 0, sizeof(struct vcom));
+ func->user_data = (void*)data;
+
+ /* initilize vcom */
+ rt_usb_vcom_init(func);
/* 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);
+ intf_comm = rt_usbd_interface_new(device, _interface_handler);
+ intf_data = rt_usbd_interface_new(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));
+ comm_setting = rt_usbd_altsetting_new(sizeof(struct ucdc_comm_descriptor));
+ data_setting = rt_usbd_altsetting_new(sizeof(struct ucdc_data_descriptor));
/* config desc in alternate setting */
rt_usbd_altsetting_config_descriptor(comm_setting, &_comm_desc,
@@ -537,39 +545,39 @@ uclass_t rt_usbd_class_cdc_create(udevice_t device)
/* 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);
+ data->ep_cmd = rt_usbd_endpoint_new(&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);
+ rt_usbd_altsetting_add_endpoint(comm_setting, data->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);
+ /* add the communication interface to the cdc function */
+ rt_usbd_function_add_interface(func, intf_comm);
- return cdc;
+ /* create a bulk in and a bulk endpoint */
+ data_desc = (ucdc_data_desc_t)data_setting->desc;
+ data->ep_out = rt_usbd_endpoint_new(&data_desc->ep_out_desc, _ep_out_handler);
+ data->ep_in = rt_usbd_endpoint_new(&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, data->ep_in);
+ rt_usbd_altsetting_add_endpoint(data_setting, data->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 function */
+ rt_usbd_function_add_interface(func, intf_data);
+
+ return func;
}
/**
@@ -597,80 +605,106 @@ static rt_err_t _vcom_control(struct rt_serial_device *serial,
return RT_EOK;
}
-static int _vcom_putc(struct rt_serial_device *serial, char c)
+static int _vcom_getc(struct rt_serial_device *serial)
{
+ int result;
+ rt_uint8_t ch;
rt_uint32_t level;
- int cnt;
-
- if (vcom_connected != RT_TRUE)
- {
- return 0;
- }
+ struct ufunction *func;
+ struct vcom *data;
+
+ func = (struct ufunction*)serial->parent.user_data;
+ data = (struct vcom*)func->user_data;
- /* if the buffer is full, there is a chance that the host would pull some
- * data out soon. But we cannot rely on that and if we wait to long, just
- * return. */
- for (cnt = 500;
- rt_ringbuffer_space_len(&tx_ringbuffer) == 0 && cnt;
- cnt--)
- {
- /*rt_kprintf("wait for %d\n", cnt);*/
- if (vcom_connected != RT_TRUE)
- return 0;
- }
- if (cnt == 0)
- {
- /* OK, we believe that the connection is lost. So don't send any more
- * data and act as the USB cable is not plugged in. Reset the VCOM
- * state machine */
- _vcom_reset_state();
- return 0;
- }
+ result = -1;
level = rt_hw_interrupt_disable();
- if (rt_ringbuffer_space_len(&tx_ringbuffer))
+
+ if(rt_ringbuffer_getchar(&data->rx_ringbuffer, &ch) != 0)
{
- rt_ringbuffer_putchar(&tx_ringbuffer, c);
+ result = ch;
}
+
rt_hw_interrupt_enable(level);
- return 1;
+ return result;
}
-static int _vcom_getc(struct rt_serial_device *serial)
+static rt_size_t _vcom_tx(struct rt_serial_device *serial,
+ const char *buf, rt_size_t size)
{
- int result;
- rt_uint8_t ch;
- rt_uint32_t level;
+ struct vcom_tx_msg msg;
- result = -1;
+ RT_ASSERT(serial != RT_NULL);
+ RT_ASSERT(buf != RT_NULL);
- level = rt_hw_interrupt_disable();
- if (rt_ringbuffer_data_len(&rx_ringbuffer))
+ msg.buf = buf;
+ msg.serial = serial;
+ msg.size = size;
+
+ if (rt_mq_send(&vcom_tx_thread_mq, (void*)&msg,
+ sizeof(struct vcom_tx_msg)) != RT_EOK)
{
- rt_ringbuffer_getchar(&rx_ringbuffer, &ch);
- result = ch;
+ rt_kprintf("vcom send msg fail\n");
+ return 0;
}
- rt_hw_interrupt_enable(level);
-
- return result;
+
+ return size;
}
static const struct rt_uart_ops usb_vcom_ops =
{
_vcom_configure,
_vcom_control,
- _vcom_putc,
+ RT_NULL,
_vcom_getc,
+ RT_NULL,
+ //_vcom_tx,
};
-void rt_usb_vcom_init(void)
+/* Vcom Tx Thread */
+static void vcom_tx_thread_entry(void* parameter)
{
- struct serial_configure config;
+ struct vcom_tx_msg msg;
+
+ while (1)
+ {
+ if (rt_mq_recv(&vcom_tx_thread_mq, (void*)&msg,
+ sizeof(struct vcom_tx_msg), RT_WAITING_FOREVER) == RT_EOK)
+ {
+ struct ufunction *func;
+ struct vcom *data;
+
+ func = (struct ufunction*)msg.serial->parent.user_data;
+ data = (struct vcom*)func->user_data;
+ if (!data->connected)
+ {
+ continue;
+ }
+
+ rt_completion_init(&data->wait);
+ data->ep_in->request.buffer = (void*)msg.buf;
+ data->ep_in->request.size = msg.size;
+ data->ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
+
+ if (rt_completion_wait(&data->wait, TX_TIMEOUT) != RT_EOK)
+ {
+ rt_kprintf("vcom tx timeout\n");
+ }
+ }
+ }
+}
+
+static void rt_usb_vcom_init(struct ufunction *func)
+{
+ rt_err_t result = RT_EOK;
+ struct serial_configure config;
+ struct vcom *data = (struct vcom*)func->user_data;
+
/* initialize ring buffer */
- rt_ringbuffer_init(&rx_ringbuffer, rx_rbp, CDC_RX_BUFSIZE);
- rt_ringbuffer_init(&tx_ringbuffer, tx_rbp, CDC_TX_BUFSIZE);
+ rt_ringbuffer_init(&data->rx_ringbuffer, data->rx_rbp, CDC_RX_BUFSIZE);
config.baud_rate = BAUD_RATE_115200;
config.bit_order = BIT_ORDER_LSB;
@@ -679,14 +713,25 @@ void rt_usb_vcom_init(void)
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;
+ data->serial.ops = &usb_vcom_ops;
+ data->serial.int_rx = &data->vcom_int_rx;
+ data->serial.config = config;
/* register vcom device */
- rt_hw_serial_register(&vcom_serial, "vcom",
- RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
- RT_NULL);
+ rt_hw_serial_register(&data->serial, VCOM_DEVICE,
+ RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX,
+ func);
+
+ /* create an vcom message queue */
+ rt_mq_init(&vcom_tx_thread_mq, "vcomq", vcom_tx_thread_mq_pool, VCOM_MQ_MSG_SZ,
+ sizeof(vcom_tx_thread_mq_pool), RT_IPC_FLAG_FIFO);
+
+ /* init usb device thread */
+ rt_thread_init(&vcom_thread, "vcom", vcom_tx_thread_entry, RT_NULL,
+ vcom_thread_stack, 512, 8, 20);
+ result = rt_thread_startup(&vcom_thread);
+ RT_ASSERT(result == RT_EOK);
}
#endif
+
diff --git a/components/drivers/usb/usbdevice/class/mstorage.c b/components/drivers/usb/usbdevice/class/mstorage.c
index b0351f63e5..4ee45189f8 100644
--- a/components/drivers/usb/usbdevice/class/mstorage.c
+++ b/components/drivers/usb/usbdevice/class/mstorage.c
@@ -21,7 +21,8 @@
* 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
+ * 2012-12-09 Heyuanjie87 change function and endpoint handler
+ * 2013-07-25 Yi Qiu update for USB CV test
*/
#include <rtthread.h>
@@ -31,19 +32,55 @@
#ifdef RT_USB_DEVICE_MSTORAGE
-#define STATUS_CBW 0x00
-#define STATUS_CSW 0x01
-#define STATUS_RECEIVE 0x02
-#define STATUS_SEND 0x03
+enum STAT
+{
+ STAT_CBW,
+ STAT_CMD,
+ STAT_CSW,
+ STAT_RECEIVE,
+ STAT_SEND,
+};
+
+typedef enum
+{
+ FIXED,
+ COUNT,
+ BLOCK_COUNT,
+}CB_SIZE_TYPE;
-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 rt_uint32_t _removed = 0;
+typedef enum
+{
+ DIR_IN,
+ DIR_OUT,
+ DIR_NONE,
+}CB_DIR;
+
+typedef rt_size_t (*cbw_handler)(ufunction_t func, ustorage_cbw_t cbw);
+
+struct scsi_cmd
+{
+ rt_uint16_t cmd;
+ cbw_handler handler;
+ rt_size_t cmd_len;
+ CB_SIZE_TYPE type;
+ rt_size_t data_size;
+ CB_DIR dir;
+};
+
+struct mstorage
+{
+ struct ustorage_csw csw_response;
+ uep_t ep_in;
+ uep_t ep_out;
+ int status;
+ rt_uint32_t cb_data_size;
+ rt_device_t disk;
+ rt_uint32_t block;
+ rt_int32_t count;
+ rt_int32_t size;
+ struct scsi_cmd* processing;
+ struct rt_device_blk_geometry geometry;
+};
static struct udevice_descriptor dev_desc =
{
@@ -63,6 +100,18 @@ static struct udevice_descriptor dev_desc =
USB_DYNAMIC, //bNumConfigurations;
};
+static struct usb_qualifier_descriptor dev_qualifier =
+{
+ sizeof(dev_qualifier),
+ USB_DESC_TYPE_DEVICEQUALIFIER,
+ 0x0200,
+ USB_CLASS_MASS_STORAGE,
+ 0x00,
+ 64,
+ 0x01,
+ 0,
+};
+
const static struct umass_descriptor _mass_desc =
{
USB_DESC_LENGTH_INTERFACE, //bLength;
@@ -95,270 +144,489 @@ const static char* _ustring[] =
"Language",
"RT-Thread Team.",
"RTT Mass Storage",
- "1.1.0",
+ "320219198301",
"Configuration",
"Interface",
};
+static rt_size_t _test_unit_ready(ufunction_t func, ustorage_cbw_t cbw);
+static rt_size_t _request_sense(ufunction_t func, ustorage_cbw_t cbw);
+static rt_size_t _inquiry_cmd(ufunction_t func, ustorage_cbw_t cbw);
+static rt_size_t _allow_removal(ufunction_t func, ustorage_cbw_t cbw);
+static rt_size_t _start_stop(ufunction_t func, ustorage_cbw_t cbw);
+static rt_size_t _mode_sense_6(ufunction_t func, ustorage_cbw_t cbw);
+static rt_size_t _read_capacities(ufunction_t func, ustorage_cbw_t cbw);
+static rt_size_t _read_capacity(ufunction_t func, ustorage_cbw_t cbw);
+static rt_size_t _read_10(ufunction_t func, ustorage_cbw_t cbw);
+static rt_size_t _write_10(ufunction_t func, ustorage_cbw_t cbw);
+static rt_size_t _verify_10(ufunction_t func, ustorage_cbw_t cbw);
+
+static struct scsi_cmd cmd_data[] =
+{
+ {SCSI_TEST_UNIT_READY, _test_unit_ready, 6, FIXED, 0, DIR_NONE},
+ {SCSI_REQUEST_SENSE, _request_sense, 6, COUNT, 0, DIR_IN},
+ {SCSI_INQUIRY_CMD, _inquiry_cmd, 6, COUNT, 0, DIR_IN},
+ {SCSI_ALLOW_REMOVAL, _allow_removal, 6, FIXED, 0, DIR_NONE},
+ {SCSI_MODE_SENSE_6, _mode_sense_6, 6, COUNT, 0, DIR_IN},
+ {SCSI_START_STOP, _start_stop, 6, FIXED, 0, DIR_NONE},
+ {SCSI_READ_CAPACITIES, _read_capacities, 10, COUNT, 0, DIR_NONE},
+ {SCSI_READ_CAPACITY, _read_capacity, 10, FIXED, 8, DIR_IN},
+ {SCSI_READ_10, _read_10, 10, BLOCK_COUNT, 0, DIR_IN},
+ {SCSI_WRITE_10, _write_10, 10, BLOCK_COUNT, 0, DIR_OUT},
+ {SCSI_VERIFY_10, _verify_10, 10, FIXED, 0, DIR_NONE},
+};
+
+static void _send_status(ufunction_t func)
+{
+ struct mstorage *data;
+
+ RT_ASSERT(func != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_send_status\n"));
+
+ data = (struct mstorage*)func->user_data;
+ data->ep_in->request.buffer = (rt_uint8_t*)&data->csw_response;
+ data->ep_in->request.size = SIZEOF_CSW;
+ data->ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
+ data->status = STAT_CSW;
+}
+
+static rt_size_t _test_unit_ready(ufunction_t func, ustorage_cbw_t cbw)
+{
+ struct mstorage *data;
+
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_test_unit_ready\n"));
+
+ data = (struct mstorage*)func->user_data;
+ data->csw_response.status = 0;
+
+ return 0;
+}
+
+static rt_size_t _allow_removal(ufunction_t func, ustorage_cbw_t cbw)
+{
+ struct mstorage *data;
+
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_allow_removal\n"));
+
+ data = (struct mstorage*)func->user_data;
+ data->csw_response.status = 0;
+
+ return 0;
+}
+
/**
- * This function will allocate an usb device instance from system.
+ * This function will handle inquiry command request.
*
- * @param parent the hub instance to which the new allocated device attached.
- * @param port the hub port.
+ * @param func the usb function object.
+ * @param cbw the command block wrapper.
*
- * @return the allocate instance on successful, or RT_NULL on failure.
+ * @return RT_EOK on successful.
*/
-static rt_err_t _inquiry_cmd(udevice_t device, uep_t ep_in)
+
+static rt_size_t _inquiry_cmd(ufunction_t func, ustorage_cbw_t cbw)
{
- rt_uint8_t data[36];
+ struct mstorage *data;
+ rt_uint8_t *buf;
- *(rt_uint32_t*)&data[0] = 0x0 | (0x80 << 8);
- *(rt_uint32_t*)&data[4] = 31;
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
+ RT_ASSERT(cbw != RT_NULL);
- rt_memset(&data[8], 0x20, 28);
- rt_memcpy(&data[8], "RTT", 3);
- rt_memcpy(&data[16], "USB Disk", 8);
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_inquiry_cmd\n"));
- dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 36);
+ data = (struct mstorage*)func->user_data;
+ buf = data->ep_in->buffer;
- return RT_EOK;
+ *(rt_uint32_t*)&buf[0] = 0x0 | (0x80 << 8);
+ *(rt_uint32_t*)&buf[4] = 31;
+
+ rt_memset(&buf[8], 0x20, 28);
+ rt_memcpy(&buf[8], "RTT", 3);
+ rt_memcpy(&buf[16], "USB Disk", 8);
+
+ data->cb_data_size = MIN(data->cb_data_size, SIZEOF_INQUIRY_CMD);
+ data->ep_in->request.buffer = buf;
+ data->ep_in->request.size = data->cb_data_size;
+ data->ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
+ data->status = STAT_CMD;
+
+ return data->cb_data_size;
}
/**
* This function will handle sense request.
*
- * @param device the usb device object.
+ * @param func the usb function object.
+ * @param cbw the command block wrapper.
*
* @return RT_EOK on successful.
*/
-static rt_err_t _request_sense(udevice_t device, uep_t ep_in)
+static rt_size_t _request_sense(ufunction_t func, ustorage_cbw_t cbw)
{
- struct request_sense_data data;
+ struct mstorage *data;
+ struct request_sense_data *buf;
- data.ErrorCode = 0x70;
- data.Valid = 0;
- data.SenseKey = 2; //TODO
- data.Information[0] = 0;
- data.Information[1] = 0;
- data.Information[2] = 0;
- data.Information[3] = 0;
- data.AdditionalSenseLength = 0x0a;
- data.AdditionalSenseCode = 0x3a; //TODO
- data.AdditionalSenseCodeQualifier =0;
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
+ RT_ASSERT(cbw != RT_NULL);
- dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, sizeof(struct request_sense_data));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_request_sense\n"));
+
+ data = (struct mstorage*)func->user_data;
+ buf = (struct request_sense_data *)data->ep_in->buffer;
- return RT_EOK;
+ buf->ErrorCode = 0x70;
+ buf->Valid = 0;
+ buf->SenseKey = 2;
+ buf->Information[0] = 0;
+ buf->Information[1] = 0;
+ buf->Information[2] = 0;
+ buf->Information[3] = 0;
+ buf->AdditionalSenseLength = 0x0a;
+ buf->AdditionalSenseCode = 0x3a;
+ buf->AdditionalSenseCodeQualifier = 0;
+
+ data->cb_data_size = MIN(data->cb_data_size, SIZEOF_REQUEST_SENSE);
+ data->ep_in->request.buffer = (rt_uint8_t*)data->ep_in->buffer;
+ data->ep_in->request.size = data->cb_data_size;
+ data->ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
+ data->status = STAT_CMD;
+
+ return data->cb_data_size;
}
/**
* This function will handle mode_sense_6 request.
*
- * @param device the usb device object.
+ * @param func the usb function object.
+ * @param cbw the command block wrapper.
*
* @return RT_EOK on successful.
*/
-static rt_err_t _mode_sense_6(udevice_t device, uep_t ep_in)
+static rt_size_t _mode_sense_6(ufunction_t func, ustorage_cbw_t cbw)
{
- rt_uint8_t data[4];
+ struct mstorage *data;
+ rt_uint8_t *buf;
- data[0]=3;
- data[1]=0;
- data[2]=0;
- data[3]=0;
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
+ RT_ASSERT(cbw != RT_NULL);
- dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 4);
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_mode_sense_6\n"));
- return RT_EOK;
+ data = (struct mstorage*)func->user_data;
+ buf = data->ep_in->buffer;
+ buf[0] = 3;
+ buf[1] = 0;
+ buf[2] = 0;
+ buf[3] = 0;
+
+ data->cb_data_size = MIN(data->cb_data_size, SIZEOF_MODE_SENSE_6);
+ data->ep_in->request.buffer = buf;
+ data->ep_in->request.size = data->cb_data_size;
+ data->ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
+ data->status = STAT_CMD;
+
+ return data->cb_data_size;
}
/**
* This function will handle read_capacities request.
*
- * @param device the usb device object.
+ * @param func the usb function object.
+ * @param cbw the command block wrapper.
*
* @return RT_EOK on successful.
*/
-static rt_err_t _read_capacities(udevice_t device, uep_t ep_in)
+static rt_size_t _read_capacities(ufunction_t func, ustorage_cbw_t cbw)
{
- rt_uint8_t data[12];
+ struct mstorage *data;
+ rt_uint8_t *buf;
rt_uint32_t sector_count, sector_size;
- RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
+ RT_ASSERT(cbw != RT_NULL);
- sector_count = geometry.sector_count;
- sector_size = geometry.bytes_per_sector;
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_read_capacities\n"));
- *(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;
+ data = (struct mstorage*)func->user_data;
+ buf = data->ep_in->buffer;
+ sector_count = data->geometry.sector_count;
+ sector_size = data->geometry.bytes_per_sector;
- dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 12);
+ *(rt_uint32_t*)&buf[0] = 0x08000000;
+ buf[4] = sector_count >> 24;
+ buf[5] = 0xff & (sector_count >> 16);
+ buf[6] = 0xff & (sector_count >> 8);
+ buf[7] = 0xff & (sector_count);
+ buf[8] = 0x02;
+ buf[9] = 0xff & (sector_size >> 16);
+ buf[10] = 0xff & (sector_size >> 8);
+ buf[11] = 0xff & sector_size;
- return RT_EOK;
+ data->cb_data_size = MIN(data->cb_data_size, SIZEOF_READ_CAPACITIES);
+ data->ep_in->request.buffer = buf;
+ data->ep_in->request.size = data->cb_data_size;
+ data->ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
+ data->status = STAT_CMD;
+
+ return data->cb_data_size;
}
/**
* This function will handle read_capacity request.
*
- * @param device the usb device object.
+ * @param func the usb function object.
+ * @param cbw the command block wapper.
*
* @return RT_EOK on successful.
*/
-static rt_err_t _read_capacity(udevice_t device, uep_t ep_in)
+static rt_size_t _read_capacity(ufunction_t func, ustorage_cbw_t cbw)
{
- rt_uint8_t data[8];
+ struct mstorage *data;
+
+ rt_uint8_t *buf;
rt_uint32_t sector_count, sector_size;
- RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
+ RT_ASSERT(cbw != RT_NULL);
- sector_count = geometry.sector_count;
- sector_size = geometry.bytes_per_sector;
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_read_capacity\n"));
- 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;
+ data = (struct mstorage*)func->user_data;
+ buf = data->ep_in->buffer;
+ sector_count = data->geometry.sector_count;
+ sector_size = data->geometry.bytes_per_sector;
- dcd_ep_write(device->dcd, ep_in, (rt_uint8_t*)&data, 8);
+ buf[0] = sector_count >> 24;
+ buf[1] = 0xff & (sector_count >> 16);
+ buf[2] = 0xff & (sector_count >> 8);
+ buf[3] = 0xff & (sector_count);
+ buf[4] = 0x0;
+ buf[5] = 0xff & (sector_size >> 16);
+ buf[6] = 0xff & (sector_size >> 8);
+ buf[7] = 0xff & sector_size;
- return RT_EOK;
+ data->cb_data_size = MIN(data->cb_data_size, SIZEOF_READ_CAPACITY);
+ data->ep_in->request.buffer = buf;
+ data->ep_in->request.size = data->cb_data_size;
+ data->ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
+ data->status = STAT_CMD;
+
+ return data->cb_data_size;
}
/**
* This function will handle read_10 request.
*
- * @param device the usb device object.
+ * @param func the usb function 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)
+static rt_size_t _read_10(ufunction_t func, ustorage_cbw_t cbw)
{
- RT_ASSERT(device != RT_NULL);
+ struct mstorage *data;
+ rt_size_t size;
+
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->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 ;
+ data = (struct mstorage*)func->user_data;
+ data->block = cbw->cb[2]<<24 | cbw->cb[3]<<16 | cbw->cb[4]<<8 |
+ cbw->cb[5]<<0;
+ data->count = cbw->cb[7]<<8 | cbw->cb[8]<<0;
- RT_ASSERT(_count < geometry.sector_count);
+ RT_ASSERT(data->count < data->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
+ data->csw_response.data_reside = data->cb_data_size;
+ size = rt_device_read(data->disk, data->block, data->ep_in->buffer, 1);
+ if(size == 0)
{
- status = STATUS_CSW;
+ rt_kprintf("read data error\n");
}
- return RT_EOK;
+ data->ep_in->request.buffer = data->ep_in->buffer;
+ data->ep_in->request.size = data->geometry.bytes_per_sector;
+ data->ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
+ data->status = STAT_SEND;
+
+ return data->geometry.bytes_per_sector;
}
/**
* This function will handle write_10 request.
*
- * @param device the usb device object.
+ * @param func the usb function 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)
+static rt_size_t _write_10(ufunction_t func, ustorage_cbw_t cbw)
{
- RT_ASSERT(device != RT_NULL);
+ struct mstorage *data;
+
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->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;
+ data = (struct mstorage*)func->user_data;
- RT_DEBUG_LOG(RT_DEBUG_USB, ("_write_10 count 0x%x 0x%x\n",
- _count, geometry.sector_count));
+ data->block = cbw->cb[2]<<24 | cbw->cb[3]<<16 | cbw->cb[4]<<8 |
+ cbw->cb[5]<<0;
+ data->count = cbw->cb[7]<<8 | cbw->cb[8];
+ data->csw_response.data_reside = cbw->xfer_len;
+ data->size = data->count * data->geometry.bytes_per_sector;
- dcd_ep_read(device->dcd, ep_out, ep_out->buffer, geometry.bytes_per_sector);
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_write_10 count 0x%x block 0x%x 0x%x\n",
+ data->count, data->block, data->geometry.sector_count));
- return RT_EOK;
+ data->csw_response.data_reside = data->cb_data_size;
+
+ data->ep_out->request.buffer = data->ep_out->buffer;
+ data->ep_out->request.size = data->geometry.bytes_per_sector;
+ data->ep_out->request.req_type = UIO_REQUEST_READ_FULL;
+ rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
+ data->status = STAT_RECEIVE;
+
+ return data->geometry.bytes_per_sector;
}
/**
* This function will handle verify_10 request.
*
- * @param device the usb device object.
+ * @param func the usb function object.
*
* @return RT_EOK on successful.
*/
-static rt_err_t _verify_10(udevice_t device)
+static rt_size_t _verify_10(ufunction_t func, ustorage_cbw_t cbw)
{
- return RT_EOK;
-}
+ struct mstorage *data;
-static void _send_status(udevice_t device, mass_eps_t eps, ustorage_csw_t csw)
-{
- 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;
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_verify_10\n"));
+
+ data = (struct mstorage*)func->user_data;
+ data->csw_response.status = 0;
+
+ return 0;
}
-static void _start_stop(ustorage_cbw_t cbw)
+static rt_size_t _start_stop(ufunction_t func,
+ ustorage_cbw_t cbw)
{
- //TODO
- _removed = 1;
+ struct mstorage *data;
+
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_start_stop\n"));
+
+ data = (struct mstorage*)func->user_data;
+ data->csw_response.status = 0;
+
+ return 0;
}
-/**
- * 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)
+static rt_err_t _ep_in_handler(ufunction_t func, rt_size_t size)
{
- mass_eps_t eps;
- RT_ASSERT(device != RT_NULL);
+ struct mstorage *data;
+
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
- eps = cls->eps;
- if (status == STATUS_CSW)
- {
- _send_status(device, eps, &csw);
- }
- else if (status == STATUS_SEND)
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_in_handler\n"));
+
+ data = (struct mstorage*)func->user_data;
+
+ switch(data->status)
{
- 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)
+ case STAT_CSW:
+ if(data->ep_in->request.size != SIZEOF_CSW)
{
- _block ++;
- status = STATUS_SEND;
+ rt_kprintf("Size of csw command error\n");
+ rt_usbd_ep_set_stall(func->device, data->ep_in);
}
else
{
- status = STATUS_CSW;
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("return to cbw status\n"));
+ data->ep_out->request.buffer = data->ep_out->buffer;
+ data->ep_out->request.size = SIZEOF_CBW;
+ data->ep_out->request.req_type = UIO_REQUEST_READ_FULL;
+ rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
+ data->status = STAT_CBW;
}
- }
+ break;
+ case STAT_CMD:
+ if(data->csw_response.data_reside == 0xFF)
+ {
+ data->csw_response.data_reside = 0;
+ }
+ else
+ {
+ data->csw_response.data_reside -= data->ep_in->request.size;
+ if(data->csw_response.data_reside != 0)
+ {
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("data_reside %d, request %d\n",
+ data->csw_response.data_reside, data->ep_in->request.size));
+ if(data->processing->dir == DIR_OUT)
+ {
+ rt_usbd_ep_set_stall(func->device, data->ep_out);
+ }
+ else
+ {
+ rt_usbd_ep_set_stall(func->device, data->ep_in);
+ }
+ data->csw_response.data_reside = 0;
+ }
+ }
+ _send_status(func);
+ break;
+ case STAT_SEND:
+ data->csw_response.data_reside -= data->ep_in->request.size;
+ data->count--;
+ data->block++;
+ if(data->count > 0 && data->csw_response.data_reside > 0)
+ {
+ if(rt_device_read(data->disk, data->block, data->ep_in->buffer, 1) == 0)
+ {
+ rt_kprintf("disk read error\n");
+ rt_usbd_ep_set_stall(func->device, data->ep_in);
+ return -RT_ERROR;
+ }
- return RT_EOK;
+ data->ep_in->request.buffer = data->ep_in->buffer;
+ data->ep_in->request.size = data->geometry.bytes_per_sector;
+ data->ep_in->request.req_type = UIO_REQUEST_WRITE;
+ rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
+ }
+ else
+ {
+ _send_status(func);
+ }
+ break;
+ }
+
+ return RT_EOK;
}
#ifdef MASS_CBW_DUMP
@@ -376,134 +644,283 @@ static void cbw_dump(struct ustorage_cbw* cbw)
}
#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)
+static struct scsi_cmd* _find_cbw_command(rt_uint16_t cmd)
{
- mass_eps_t eps;
- RT_ASSERT(device != RT_NULL);
+ int i;
- eps = (mass_eps_t)cls->eps;
- if(status == STATUS_CBW)
+ for(i=0; i<sizeof(cmd_data)/sizeof(struct scsi_cmd); i++)
{
- struct ustorage_cbw* cbw;
+ if(cmd_data[i].cmd == cmd)
+ return &cmd_data[i];
+ }
- /* dump cbw information */
- cbw = (struct ustorage_cbw*)eps->ep_out->buffer;
+ return RT_NULL;
+}
- if(cbw->signature == CBW_SIGNATURE)
- {
- csw.signature = CSW_SIGNATURE;
- csw.tag = cbw->tag;
- csw.data_reside = 0;
- csw.status = 0;
- }
- else
- return -RT_ERROR;
+static void _cb_len_calc(ufunction_t func, struct scsi_cmd* cmd,
+ ustorage_cbw_t cbw)
+{
+ struct mstorage *data;
- switch(cbw->cb[0])
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(cmd != RT_NULL);
+ RT_ASSERT(cbw != RT_NULL);
+
+ data = (struct mstorage*)func->user_data;
+ if(cmd->cmd_len == 6)
+ {
+ switch(cmd->type)
{
- case SCSI_TEST_UNIT_READY:
- csw.status = _removed;
- _send_status(device, eps, &csw);
- break;
- case SCSI_REQUEST_SENSE:
- _request_sense(device, eps->ep_in);
- status = STATUS_CSW;
+ case COUNT:
+ data->cb_data_size = cbw->cb[4];
break;
- case SCSI_INQUIRY_CMD:
- _inquiry_cmd(device, eps->ep_in);
- status = STATUS_CSW;
+ case BLOCK_COUNT:
+ data->cb_data_size = cbw->cb[4] * data->geometry.bytes_per_sector;
break;
- case SCSI_MODE_SENSE_6:
- _mode_sense_6(device, eps->ep_in);
- status = STATUS_CSW;
+ case FIXED:
+ data->cb_data_size = cmd->data_size;
break;
- case SCSI_ALLOW_MEDIUM_REMOVAL:
- _send_status(device, eps, &csw);
+ default:
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);
+ }
+ }
+ else if(cmd->cmd_len == 10)
+ {
+ switch(cmd->type)
+ {
+ case COUNT:
+ data->cb_data_size = cbw->cb[7]<<8 | cbw->cb[8];
break;
- case SCSI_WRITE_10:
- _write_10(device, cbw, eps->ep_out);
- status = STATUS_RECEIVE;
+ case BLOCK_COUNT:
+ data->cb_data_size = (cbw->cb[7]<<8 | cbw->cb[8]) *
+ data->geometry.bytes_per_sector;
break;
- case SCSI_VERIFY_10:
- _verify_10(device);
+ case FIXED:
+ data->cb_data_size = cmd->data_size;
break;
- case SCSI_START_STOP:
- _start_stop(cbw);
- _send_status(device, eps, &csw);
+ default:
break;
}
}
- else if(status == STATUS_RECEIVE)
+ else
{
- RT_DEBUG_LOG(RT_DEBUG_USB, ("write size 0x%x block 0x%x oount 0x%x\n",
- size, _block, _size));
+ rt_kprintf("cmd_len error %d\n", cmd->cmd_len);
+ }
+}
- _size -= size;
- csw.data_reside -= size;
+static rt_bool_t _cbw_verify(ufunction_t func, struct scsi_cmd* cmd,
+ ustorage_cbw_t cbw)
+{
+ struct mstorage *data;
+
+ RT_ASSERT(cmd != RT_NULL);
+ RT_ASSERT(cbw != RT_NULL);
+ RT_ASSERT(func != RT_NULL);
- rt_device_write(disk, _block, eps->ep_in->buffer, 1);
- _block ++;
- if(_size == 0)
+ data = (struct mstorage*)func->user_data;
+ if(cmd->cmd_len != cbw->cb_len)
+ {
+ rt_kprintf("cb_len error\n");
+ cmd->cmd_len = cbw->cb_len;
+ }
+
+ if(cbw->xfer_len > 0 && data->cb_data_size == 0)
+ {
+ rt_kprintf("xfer_len > 0 && data_size == 0\n");
+ return RT_FALSE;
+ }
+
+ if(cbw->xfer_len == 0 && data->cb_data_size > 0)
+ {
+ rt_kprintf("xfer_len == 0 && data_size > 0");
+ return RT_FALSE;
+ }
+
+ if((cbw->dflags & USB_DIR_IN) && cmd->dir == DIR_OUT ||
+ !(cbw->dflags & USB_DIR_IN) && cmd->dir == DIR_IN)
+ {
+ rt_kprintf("dir error\n");
+ return RT_FALSE;
+ }
+
+ if(cbw->xfer_len > data->cb_data_size)
+ {
+ rt_kprintf("xfer_len > data_size\n");
+ return RT_FALSE;
+ }
+
+ if(cbw->xfer_len < data->cb_data_size)
+ {
+ rt_kprintf("xfer_len < data_size\n");
+ data->cb_data_size = cbw->xfer_len;
+ data->csw_response.status = 1;
+ }
+
+ return RT_TRUE;
+}
+
+static rt_size_t _cbw_handler(ufunction_t func, struct scsi_cmd* cmd,
+ ustorage_cbw_t cbw)
+{
+ struct mstorage *data;
+
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(cbw != RT_NULL);
+ RT_ASSERT(cmd->handler != RT_NULL);
+
+ data = (struct mstorage*)func->user_data;
+ data->processing = cmd;
+ return cmd->handler(func, cbw);
+}
+
+/**
+ * This function will handle mass storage bulk out endpoint request.
+ *
+ * @param func the usb function object.
+ * @param size request size.
+ *
+ * @return RT_EOK.
+ */
+static rt_err_t _ep_out_handler(ufunction_t func, rt_size_t size)
+{
+ struct mstorage *data;
+ struct scsi_cmd* cmd;
+ rt_size_t len;
+ struct ustorage_cbw* cbw;
+
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_out_handler %d\n", size));
+
+ data = (struct mstorage*)func->user_data;
+ cbw = (struct ustorage_cbw*)data->ep_out->buffer;
+ if(data->status == STAT_CBW)
+ {
+ /* dump cbw information */
+ if(cbw->signature != CBW_SIGNATURE || size != SIZEOF_CBW)
+ {
+ goto exit;
+ }
+
+ data->csw_response.signature = CSW_SIGNATURE;
+ data->csw_response.tag = cbw->tag;
+ data->csw_response.data_reside = cbw->xfer_len;
+ data->csw_response.status = 0;
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("ep_out reside %d\n", data->csw_response.data_reside));
+
+ cmd = _find_cbw_command(cbw->cb[0]);
+ if(cmd == RT_NULL)
{
- _send_status(device, eps, &csw);
+ rt_kprintf("can't find cbw command\n");
+ goto exit;
+ }
+
+ _cb_len_calc(func, cmd, cbw);
+ if(!_cbw_verify(func, cmd, cbw))
+ {
+ goto exit;
+ }
+
+ len = _cbw_handler(func, cmd, cbw);
+ if(len == 0)
+ {
+ _send_status(func);
+ }
+
+ return RT_EOK;
+ }
+ else if(data->status == STAT_RECEIVE)
+ {
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("\nwrite size %d block 0x%x oount 0x%x\n",
+ size, data->block, data->size));
+
+ data->size -= size;
+ data->csw_response.data_reside -= size;
+
+ rt_device_write(data->disk, data->block, data->ep_out->buffer, 1);
+
+ if(data->csw_response.data_reside != 0)
+ {
+ data->ep_out->request.buffer = data->ep_out->buffer;
+ data->ep_out->request.size = data->geometry.bytes_per_sector;
+ data->ep_out->request.req_type = UIO_REQUEST_READ_FULL;
+ rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
+ data->block ++;
}
else
{
- dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer,
- geometry.bytes_per_sector);
+ _send_status(func);
}
+
+ return RT_EOK;
}
- else
+
+exit:
+ if(data->csw_response.data_reside)
{
- rt_kprintf("none cbw status\n");
+ if(cbw->dflags & USB_DIR_IN)
+ {
+ rt_usbd_ep_set_stall(func->device, data->ep_in);
+ }
+ else
+ {
+ rt_usbd_ep_set_stall(func->device, data->ep_in);
+ rt_usbd_ep_set_stall(func->device, data->ep_out);
+ }
}
-
- return RT_EOK;
+ data->csw_response.status = 1;
+ _send_status(func);
+
+ return -RT_ERROR;
}
-
/**
* This function will handle mass storage interface request.
*
- * @param device the usb device object.
+ * @param func the usb function 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)
+static rt_err_t _interface_handler(ufunction_t func, ureq_t setup)
{
rt_uint8_t lun = 0;
-
- RT_ASSERT(device != RT_NULL);
+
+ RT_ASSERT(func != RT_NULL);
+ RT_ASSERT(func->device != RT_NULL);
RT_ASSERT(setup != RT_NULL);
- RT_DEBUG_LOG(RT_DEBUG_USB, ("_interface_handler\n"));
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("mstorage_interface_handler\n"));
switch(setup->request)
{
- case USBREQ_GET_MAX_LUN:
- dcd_ep_write(device->dcd, 0, &lun, 1);
+ case USBREQ_GET_MAX_LUN:
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("USBREQ_GET_MAX_LUN\n"));
+
+ if(setup->value || setup->length != 1)
+ {
+ rt_usbd_ep0_set_stall(func->device);
+ }
+ else
+ {
+ rt_usbd_ep0_write(func->device, &lun, 1);
+ }
break;
case USBREQ_MASS_STORAGE_RESET:
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("USBREQ_MASS_STORAGE_RESET\n"));
+
+ if(setup->value || setup->length != 0)
+ {
+ rt_usbd_ep0_set_stall(func->device);
+ }
+ else
+ {
+ rt_usbd_ep0_write(func->device, RT_NULL, 0);
+ }
break;
default:
rt_kprintf("unknown interface request\n");
@@ -514,81 +931,114 @@ static rt_err_t _interface_handler(udevice_t device, uclass_t cls, ureq_t setup)
}
/**
- * This function will run mass storage class, it will be called on handle set configuration request.
+ * This function will run mass storage function, it will be called on handle set configuration request.
*
- * @param device the usb device object.
+ * @param func the usb function object.
*
* @return RT_EOK on successful.
*/
-static rt_err_t _class_run(udevice_t device, uclass_t cls)
+static rt_err_t _function_enable(ufunction_t func)
{
- mass_eps_t eps;
- rt_uint8_t *buffer;
- RT_ASSERT(device != RT_NULL);
+ struct mstorage *data;
+ RT_ASSERT(func != RT_NULL);
- RT_DEBUG_LOG(RT_DEBUG_USB, ("mass storage run\n"));
- eps = (mass_eps_t)cls->eps;
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("Mass storage function enabled\n"));
+ data = (struct mstorage*)func->user_data;
- disk = rt_device_find(RT_USB_MSTORAGE_DISK_NAME);
- if(disk == RT_NULL)
+ data->disk = rt_device_find(RT_USB_MSTORAGE_DISK_NAME);
+ if(data->disk == RT_NULL)
{
- rt_kprintf("no disk named %s\n", RT_USB_MSTORAGE_DISK_NAME);
+ rt_kprintf("no data->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)
+ if(rt_device_open(data->disk, RT_DEVICE_OFLAG_RDWR) != RT_EOK)
+ {
+ rt_kprintf("disk open error\n");
+ return -RT_ERROR;
+ }
+
+ if(rt_device_control(data->disk, RT_DEVICE_CTRL_BLK_GETGEOME,
+ (void*)&data->geometry) != RT_EOK)
+ {
+ rt_kprintf("get disk info error\n");
+ return -RT_ERROR;
+ }
+
+ data->ep_in->buffer = (rt_uint8_t*)rt_malloc(data->geometry.bytes_per_sector);
+ if(data->ep_in->buffer == RT_NULL)
+ {
+ rt_kprintf("no memory\n");
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);
-
+ }
+ data->ep_out->buffer = (rt_uint8_t*)rt_malloc(data->geometry.bytes_per_sector);
+ if(data->ep_out->buffer == RT_NULL)
+ {
+ rt_free(data->ep_in->buffer);
+ rt_kprintf("no memory\n");
+ return -RT_ENOMEM;
+ }
+
+ /* prepare to read CBW request */
+ data->ep_out->request.buffer = data->ep_out->buffer;
+ data->ep_out->request.size = SIZEOF_CBW;
+ data->ep_out->request.req_type = UIO_REQUEST_READ_FULL;
+ rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
+
return RT_EOK;
}
/**
- * This function will stop mass storage class, it will be called on handle set configuration request.
+ * This function will stop mass storage function, 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)
+static rt_err_t _function_disable(ufunction_t func)
{
- mass_eps_t eps;
- RT_ASSERT(device != RT_NULL);
+ struct mstorage *data;
+ RT_ASSERT(func != RT_NULL);
+
+ RT_DEBUG_LOG(RT_DEBUG_USB, ("Mass storage function disabled\n"));
- 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;
+ data = (struct mstorage*)func->user_data;
+ if(data->ep_in->buffer != RT_NULL)
+ {
+ rt_free(data->ep_in->buffer);
+ data->ep_in->buffer = RT_NULL;
+ }
+
+ if(data->ep_out->buffer != RT_NULL)
+ {
+ rt_free(data->ep_out->buffer);
+ data->ep_out->buffer = RT_NULL;
+ }
+ data->status = STAT_CBW;
+
return RT_EOK;
}
-static struct uclass_ops ops =
+static struct ufunction_ops ops =
{
- _class_run,
- _class_stop,
+ _function_enable,
+ _function_disable,
RT_NULL,
};
/**
- * This function will create a mass storage class instance.
+ * This function will create a mass storage function instance.
*
* @param device the usb device object.
*
* @return RT_EOK on successful.
*/
-uclass_t rt_usbd_class_mstorage_create(udevice_t device)
+ufunction_t rt_usbd_function_mstorage_create(udevice_t device)
{
uintf_t intf;
- mass_eps_t eps;
- uclass_t mstorage;
+ struct mstorage *data;
+ ufunction_t func;
ualtsetting_t setting;
umass_desc_t mass_desc;
@@ -597,37 +1047,42 @@ uclass_t rt_usbd_class_mstorage_create(udevice_t device)
/* set usb device string description */
rt_usbd_device_set_string(device, _ustring);
- /* 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 a mass storage function */
+ func = rt_usbd_function_new(device, &dev_desc, &ops);
+ device->dev_qualifier = &dev_qualifier;
+
+ /* allocate memory for mass storage function data */
+ data = (struct mstorage*)rt_malloc(sizeof(struct mstorage));
+ rt_memset(data, 0, sizeof(struct mstorage));
+ func->user_data = (void*)data;
- /* create an interface */
- intf = rt_usbd_interface_create(device, _interface_handler);
+ /* create an interface object */
+ intf = rt_usbd_interface_new(device, _interface_handler);
- /* create an alternate setting */
- setting = rt_usbd_altsetting_create(sizeof(struct umass_descriptor));
+ /* create an alternate setting object */
+ setting = rt_usbd_altsetting_new(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);
+ data->ep_in = rt_usbd_endpoint_new(&mass_desc->ep_in_desc, _ep_in_handler);
+ data->ep_out = rt_usbd_endpoint_new(&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);
+ rt_usbd_altsetting_add_endpoint(setting, data->ep_out);
+ rt_usbd_altsetting_add_endpoint(setting, data->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);
+ /* add the interface to the mass storage function */
+ rt_usbd_function_add_interface(func, intf);
- return mstorage;
+ return func;
}
#endif
diff --git a/components/drivers/usb/usbdevice/class/mstorage.h b/components/drivers/usb/usbdevice/class/mstorage.h
index 4d53222a00..0f448a07d5 100644
--- a/components/drivers/usb/usbdevice/class/mstorage.h
+++ b/components/drivers/usb/usbdevice/class/mstorage.h
@@ -59,13 +59,6 @@ struct request_sense_data
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