summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
authorBernard Xiong <[email protected]>2013-05-11 23:18:03 -0700
committerBernard Xiong <[email protected]>2013-05-11 23:18:03 -0700
commit94b7fee4d2f32210eeed80038f73eebcfa0f9ef2 (patch)
treed544c351f56f8611475fc24758f9d4df5ccc041b /components
parentc8d85a5c3551cf8f15c57cb56143d1fa26ab6a0b (diff)
parentaa179e44383a20234fd07f79805f571af9936a01 (diff)
Merge pull request #85 from grissiom/fix-usb-serial
Fix usb serial
Diffstat (limited to 'components')
-rw-r--r--components/drivers/usb/usbdevice/class/cdc_vcom.c123
-rw-r--r--components/drivers/usb/usbdevice/core/core.c36
2 files changed, 98 insertions, 61 deletions
diff --git a/components/drivers/usb/usbdevice/class/cdc_vcom.c b/components/drivers/usb/usbdevice/class/cdc_vcom.c
index 497e6e30ea..44e905f317 100644
--- a/components/drivers/usb/usbdevice/class/cdc_vcom.c
+++ b/components/drivers/usb/usbdevice/class/cdc_vcom.c
@@ -20,15 +20,24 @@
#ifdef RT_USB_DEVICE_CDC
-#define CDC_RX_BUFSIZE 64
+#define CDC_RX_BUFSIZE 2048
#define CDC_TX_BUFSIZE 2048
-static rt_uint8_t rx_pool[CDC_RX_BUFSIZE];
-static rt_uint8_t tx_pool[CDC_TX_BUFSIZE];
+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 rt_serial_device vcom_serial;
static struct serial_ringbuffer vcom_int_rx;
+
+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_bool_t vcom_connected = RT_FALSE;
+static rt_bool_t vcom_in_sending = RT_FALSE;
static struct udevice_descriptor dev_desc =
{
@@ -38,7 +47,7 @@ static struct udevice_descriptor dev_desc =
USB_CLASS_CDC, //bDeviceClass;
0x00, //bDeviceSubClass;
0x00, //bDeviceProtocol;
- 0x40, //bMaxPacketSize0;
+ CDC_MaxPacketSize, //bMaxPacketSize0;
_VENDOR_ID, //idVendor;
_PRODUCT_ID, //idProduct;
USB_BCD_DEVICE, //bcdDevice;
@@ -153,25 +162,44 @@ const static char* _ustring[] =
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;
+ rt_uint32_t remain;
cdc_eps_t eps;
- rt_size_t mps;
eps = (cdc_eps_t)cls->eps;
- mps = eps->ep_in->ep_desc->wMaxPacketSize;
- size = RT_RINGBUFFER_SIZE(&tx_ringbuffer);
- if(size == 0) return RT_EOK;
+ level = rt_hw_interrupt_disable();
+ remain = RT_RINGBUFFER_SIZE(&tx_ringbuffer);
+ if (remain != 0)
+ {
- length = size > mps ? mps : size;
+ vcom_in_sending = RT_TRUE;
+ rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, remain);
+ rt_hw_interrupt_enable(level);
- level = rt_hw_interrupt_disable();
- rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, length);
- rt_hw_interrupt_enable(level);
+ /* send data to host */
+ dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, remain);
- /* send data to host */
- dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, length);
+ return RT_EOK;
+ }
- return RT_EOK;
+ if (size != 0 &&
+ (size % CDC_MaxPacketSize) == 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);
+ return RT_EOK;
+ }
}
/**
@@ -192,6 +220,7 @@ static rt_err_t _ep_out_handler(udevice_t device, uclass_t cls, rt_size_t size)
eps = (cdc_eps_t)cls->eps;
/* receive data from USB VCOM */
level = rt_hw_interrupt_disable();
+
rt_ringbuffer_put(&rx_ringbuffer, eps->ep_out->buffer, size);
rt_hw_interrupt_enable(level);
@@ -337,8 +366,8 @@ static rt_err_t _class_run(udevice_t device, uclass_t cls)
RT_DEBUG_LOG(RT_DEBUG_USB, ("cdc class run\n"));
eps = (cdc_eps_t)cls->eps;
- eps->ep_in->buffer=tx_pool;
- eps->ep_out->buffer=rx_pool;
+ eps->ep_in->buffer = tx_buf;
+ eps->ep_out->buffer = rx_buf;
dcd_ep_read(device->dcd, eps->ep_out, eps->ep_out->buffer,
eps->ep_out->ep_desc->wMaxPacketSize);
@@ -373,31 +402,27 @@ 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;
-
- eps = (cdc_eps_t)cls->eps;
- if (frame_count ++ == 5)
- {
- rt_size_t mps = eps->ep_in->ep_desc->wMaxPacketSize;
+ if (vcom_connected != RT_TRUE)
+ return -RT_ERROR;
- /* reset the frame counter */
- frame_count = 0;
+ if (vcom_in_sending)
+ return RT_EOK;
- size = RT_RINGBUFFER_SIZE(&tx_ringbuffer);
- if(size == 0) return -RT_EFULL;
+ eps = (cdc_eps_t)cls->eps;
- size = size > mps ? mps : size;
+ size = RT_RINGBUFFER_SIZE(&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);
+ 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 */
+ vcom_in_sending = RT_TRUE;
+ dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, size);
return RT_EOK;
}
@@ -534,8 +559,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 = 500;
+
+ if (vcom_connected != RT_TRUE)
+ return 0;
- if (vcom_connected != RT_TRUE) return 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);
+ if (vcom_connected != RT_TRUE)
+ return 0;
+ }
+ if (cnt == 0)
+ return 0;
level = rt_hw_interrupt_disable();
if (RT_RINGBUFFER_EMPTY(&tx_ringbuffer))
@@ -579,8 +620,8 @@ void rt_usb_vcom_init(void)
struct serial_configure config;
/* initialize ring buffer */
- rt_ringbuffer_init(&rx_ringbuffer, rx_pool, CDC_RX_BUFSIZE);
- rt_ringbuffer_init(&tx_ringbuffer, tx_pool, CDC_TX_BUFSIZE);
+ rt_ringbuffer_init(&rx_ringbuffer, rx_rbp, CDC_RX_BUFSIZE);
+ rt_ringbuffer_init(&tx_ringbuffer, tx_rbp, CDC_TX_BUFSIZE);
config.baud_rate = BAUD_RATE_115200;
config.bit_order = BIT_ORDER_LSB;
@@ -595,7 +636,7 @@ void rt_usb_vcom_init(void)
/* register vcom device */
rt_hw_serial_register(&vcom_serial, "vcom",
- RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM,
+ RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
RT_NULL);
}
diff --git a/components/drivers/usb/usbdevice/core/core.c b/components/drivers/usb/usbdevice/core/core.c
index 2f4a21eee4..0717414635 100644
--- a/components/drivers/usb/usbdevice/core/core.c
+++ b/components/drivers/usb/usbdevice/core/core.c
@@ -1294,39 +1294,35 @@ static void rt_usbd_thread_entry(void* parameter)
uep_t ep;
/* receive message */
- if(rt_mq_recv(usb_mq, &msg, sizeof(struct udev_msg), RT_WAITING_FOREVER)
- != RT_EOK ) continue;
+ if(rt_mq_recv(usb_mq,
+ &msg, sizeof(struct udev_msg),
+ RT_WAITING_FOREVER) != RT_EOK )
+ continue;
+
+ device = rt_usbd_find_device(msg.dcd);
+ if(device == RT_NULL)
+ {
+ rt_kprintf("invalid usb device\n");
+ continue;
+ }
switch (msg.type)
{
- case USB_MSG_SETUP_NOTIFY:
- device = rt_usbd_find_device(msg.dcd);
- if(device != RT_NULL)
- _setup_request(device, (ureq_t)msg.content.setup_msg.packet);
- else
- rt_kprintf("invalid usb device\n");
+ case USB_MSG_SOF:
+ _sof_notify(device);
break;
case USB_MSG_DATA_NOTIFY:
- device = rt_usbd_find_device(msg.dcd);
- if(device == RT_NULL)
- {
- rt_kprintf("invalid usb device\n");
- break;
- }
ep = rt_usbd_find_endpoint(device, &cls, msg.content.ep_msg.ep_addr);
if(ep != RT_NULL)
ep->handler(device, cls, msg.content.ep_msg.size);
else
rt_kprintf("invalid endpoint\n");
break;
- case USB_MSG_SOF:
- device = rt_usbd_find_device(msg.dcd);
- if(device != RT_NULL)
- _sof_notify(device);
- else
- rt_kprintf("invalid usb device\n");
+ case USB_MSG_SETUP_NOTIFY:
+ _setup_request(device, (ureq_t)msg.content.setup_msg.packet);
break;
default:
+ rt_kprintf("unknown msg type\n");
break;
}
}