Переглянути джерело

cdc_vcom: send data as many as possible

The data filled into dcd_ep_write does not to be limited by
MaxPacketSize.
Grissiom 12 роки тому
батько
коміт
d23ee75d2e
1 змінених файлів з 35 додано та 33 видалено
  1. 35 33
      components/drivers/usb/usbdevice/class/cdc_vcom.c

+ 35 - 33
components/drivers/usb/usbdevice/class/cdc_vcom.c

@@ -21,7 +21,7 @@
 #ifdef RT_USB_DEVICE_CDC
 
 #define CDC_RX_BUFSIZE          2048
-#define CDC_TX_BUFSIZE          1024
+#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;
@@ -32,9 +32,9 @@ static struct rt_serial_device vcom_serial;
 
 #define CDC_MaxPacketSize 64
 ALIGN(RT_ALIGN_SIZE)
-static rt_uint8_t rx_buf[CDC_MaxPacketSize];
+static rt_uint8_t rx_buf[CDC_RX_BUFSIZE];
 ALIGN(RT_ALIGN_SIZE)
-static rt_uint8_t tx_buf[CDC_MaxPacketSize];
+static rt_uint8_t tx_buf[CDC_TX_BUFSIZE];
 
 static rt_bool_t vcom_connected = RT_FALSE;
 
@@ -151,6 +151,7 @@ const static char* _ustring[] =
 };
 
 static rt_bool_t _in_sending;
+
 /**
  * This function will handle cdc bulk in endpoint request.
  *
@@ -162,31 +163,33 @@ static rt_bool_t _in_sending;
 static rt_err_t _ep_in_handler(udevice_t device, uclass_t cls, rt_size_t size)
 {
     rt_uint32_t level;
-    rt_size_t length;
     cdc_eps_t eps;
-    rt_size_t mps;
 
     eps = (cdc_eps_t)cls->eps;
-    mps = eps->ep_in->ep_desc->wMaxPacketSize;
+    level = rt_hw_interrupt_disable();
     size = RT_RINGBUFFER_SIZE(&tx_ringbuffer);
     if(size == 0)
     {
         if (_in_sending)
         {
             _in_sending = RT_FALSE;
+            /* 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. */
             dcd_ep_write(device->dcd, eps->ep_in, RT_NULL, 0);
         }
+        rt_hw_interrupt_enable(level);
         return RT_EOK;
     }
+    _in_sending = RT_TRUE;
 
-    length = size > mps ? mps : size;
-
-    level = rt_hw_interrupt_disable();
-    rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, length);
+    rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, size);
     rt_hw_interrupt_enable(level);
 
     /* send data to host */
-    dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, length);
+    dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, size);
 
     return RT_EOK;
 }
@@ -391,33 +394,25 @@ static rt_err_t _class_sof_handler(udevice_t device, uclass_t cls)
 {
     rt_uint32_t level;
     rt_size_t size;
-    /*static rt_uint32_t frame_count = 0;*/
     cdc_eps_t eps;
 
-    if(vcom_connected != RT_TRUE) return -RT_ERROR;
+    if (vcom_connected != RT_TRUE)
+        return -RT_ERROR;
 
     eps = (cdc_eps_t)cls->eps;
-    /*if (frame_count ++ == 5)*/
-    {
-        rt_size_t mps = eps->ep_in->ep_desc->wMaxPacketSize;
-
-        /* reset the frame counter */
-        /*frame_count = 0;*/
 
-        size = RT_RINGBUFFER_SIZE(&tx_ringbuffer);
-        if(size == 0)
-            return -RT_EFULL;
+    size = RT_RINGBUFFER_SIZE(&tx_ringbuffer);
+    if(size == 0)
+        return -RT_EFULL;
 
-        _in_sending = RT_TRUE;
-        size = size > mps ? mps : size;
+    _in_sending = RT_TRUE;
 
-        level = rt_hw_interrupt_disable();
-        rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, size);
-        rt_hw_interrupt_enable(level);
+    level = rt_hw_interrupt_disable();
+    rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, size);
+    rt_hw_interrupt_enable(level);
 
-        /* send data to host */
-        dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, size);
-    }
+    /* send data to host */
+    dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, size);
 
     return RT_EOK;
 }
@@ -554,17 +549,24 @@ static rt_err_t _vcom_control(struct rt_serial_device *serial,
 static int _vcom_putc(struct rt_serial_device *serial, char c)
 {
     rt_uint32_t level;
-    int cnt = 0;
+    int cnt = 500;
 
     if (vcom_connected != RT_TRUE)
         return 0;
 
-    while (RT_RINGBUFFER_EMPTY(&tx_ringbuffer) == 0)
+    /* 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_EMPTY(&tx_ringbuffer) == 0 && cnt;
+         cnt--)
     {
-        rt_kprintf("wait for %d\n", cnt++);
+        rt_kprintf("wait for %d\n", cnt);
         if (vcom_connected != RT_TRUE)
             return 0;
     }
+    if (cnt == 0)
+        return 0;
 
     level = rt_hw_interrupt_disable();
     if (RT_RINGBUFFER_EMPTY(&tx_ringbuffer))