cdc_vcom: send data as many as possible

The data filled into dcd_ep_write does not to be limited by
MaxPacketSize.
This commit is contained in:
Grissiom 2013-05-10 17:50:07 +08:00
parent 5de59429fe
commit d23ee75d2e

View File

@ -21,7 +21,7 @@
#ifdef RT_USB_DEVICE_CDC #ifdef RT_USB_DEVICE_CDC
#define CDC_RX_BUFSIZE 2048 #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 rx_rbp[CDC_RX_BUFSIZE];
static rt_uint8_t tx_rbp[CDC_TX_BUFSIZE]; static rt_uint8_t tx_rbp[CDC_TX_BUFSIZE];
static struct rt_ringbuffer rx_ringbuffer; static struct rt_ringbuffer rx_ringbuffer;
@ -32,9 +32,9 @@ static struct rt_serial_device vcom_serial;
#define CDC_MaxPacketSize 64 #define CDC_MaxPacketSize 64
ALIGN(RT_ALIGN_SIZE) 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) 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; static rt_bool_t vcom_connected = RT_FALSE;
@ -151,6 +151,7 @@ const static char* _ustring[] =
}; };
static rt_bool_t _in_sending; static rt_bool_t _in_sending;
/** /**
* This function will handle cdc bulk in endpoint request. * 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) static rt_err_t _ep_in_handler(udevice_t device, uclass_t cls, rt_size_t size)
{ {
rt_uint32_t level; rt_uint32_t level;
rt_size_t length;
cdc_eps_t eps; cdc_eps_t eps;
rt_size_t mps;
eps = (cdc_eps_t)cls->eps; eps = (cdc_eps_t)cls->eps;
mps = eps->ep_in->ep_desc->wMaxPacketSize; level = rt_hw_interrupt_disable();
size = RT_RINGBUFFER_SIZE(&tx_ringbuffer); size = RT_RINGBUFFER_SIZE(&tx_ringbuffer);
if(size == 0) if(size == 0)
{ {
if (_in_sending) if (_in_sending)
{ {
_in_sending = RT_FALSE; _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); dcd_ep_write(device->dcd, eps->ep_in, RT_NULL, 0);
} }
rt_hw_interrupt_enable(level);
return RT_EOK; return RT_EOK;
} }
_in_sending = RT_TRUE;
length = size > mps ? mps : size; rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, size);
level = rt_hw_interrupt_disable();
rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, length);
rt_hw_interrupt_enable(level); rt_hw_interrupt_enable(level);
/* send data to host */ /* 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; 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_uint32_t level;
rt_size_t size; rt_size_t size;
/*static rt_uint32_t frame_count = 0;*/
cdc_eps_t eps; 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; eps = (cdc_eps_t)cls->eps;
/*if (frame_count ++ == 5)*/
{
rt_size_t mps = eps->ep_in->ep_desc->wMaxPacketSize;
/* reset the frame counter */ size = RT_RINGBUFFER_SIZE(&tx_ringbuffer);
/*frame_count = 0;*/ if(size == 0)
return -RT_EFULL;
size = RT_RINGBUFFER_SIZE(&tx_ringbuffer); _in_sending = RT_TRUE;
if(size == 0)
return -RT_EFULL;
_in_sending = RT_TRUE; level = rt_hw_interrupt_disable();
size = size > mps ? mps : size; rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, size);
rt_hw_interrupt_enable(level);
level = rt_hw_interrupt_disable(); /* send data to host */
rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, size); dcd_ep_write(device->dcd, eps->ep_in, 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);
}
return RT_EOK; 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) static int _vcom_putc(struct rt_serial_device *serial, char c)
{ {
rt_uint32_t level; rt_uint32_t level;
int cnt = 0; int cnt = 500;
if (vcom_connected != RT_TRUE) if (vcom_connected != RT_TRUE)
return 0; 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) if (vcom_connected != RT_TRUE)
return 0; return 0;
} }
if (cnt == 0)
return 0;
level = rt_hw_interrupt_disable(); level = rt_hw_interrupt_disable();
if (RT_RINGBUFFER_EMPTY(&tx_ringbuffer)) if (RT_RINGBUFFER_EMPTY(&tx_ringbuffer))