usb_cdc: Rework transfer state tracking code
Maintain the state tracking code entirely within a usb_do_xfer() method. This simplifies the callers. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
6ab16d2407
commit
be1effebc3
|
@ -290,49 +290,57 @@ static const struct descriptor_s {
|
||||||
|
|
||||||
// State tracking
|
// State tracking
|
||||||
enum {
|
enum {
|
||||||
US_READY, US_SEND, US_READ
|
UX_READ = 1<<0, UX_SEND = 1<<1
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint_fast8_t usb_state;
|
static void *usb_xfer_data;
|
||||||
static void *usb_xfer;
|
static uint8_t usb_xfer_size, usb_xfer_flags;
|
||||||
static uint_fast8_t usb_xfer_size;
|
|
||||||
|
|
||||||
|
// Set the USB "stall" condition
|
||||||
static void
|
static void
|
||||||
usb_do_stall(void)
|
usb_do_stall(void)
|
||||||
{
|
{
|
||||||
usb_stall_ep0();
|
usb_stall_ep0();
|
||||||
usb_state = US_READY;
|
usb_xfer_flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sending data from device to host
|
// Transfer data on the usb endpoint 0
|
||||||
static void
|
static void
|
||||||
usb_state_xfer(void)
|
usb_do_xfer(void *data, uint_fast8_t size, uint_fast8_t flags)
|
||||||
{
|
{
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uint_fast8_t xs = usb_xfer_size;
|
uint_fast8_t xs = size;
|
||||||
if (xs > USB_CDC_EP0_SIZE)
|
if (xs > USB_CDC_EP0_SIZE)
|
||||||
xs = USB_CDC_EP0_SIZE;
|
xs = USB_CDC_EP0_SIZE;
|
||||||
int_fast8_t ret;
|
int_fast8_t ret;
|
||||||
if (usb_state == US_SEND)
|
if (flags & UX_READ)
|
||||||
ret = usb_send_ep0(usb_xfer, xs);
|
ret = usb_read_ep0(data, xs);
|
||||||
else
|
else
|
||||||
ret = usb_read_ep0(usb_xfer, xs);
|
ret = usb_send_ep0(data, xs);
|
||||||
if (ret == xs) {
|
if (ret == xs) {
|
||||||
// Success
|
// Success
|
||||||
usb_xfer += xs;
|
data += xs;
|
||||||
usb_xfer_size -= xs;
|
size -= xs;
|
||||||
if (!usb_xfer_size && xs < USB_CDC_EP0_SIZE) {
|
if (!size && xs < USB_CDC_EP0_SIZE) {
|
||||||
// Transfer completed successfully
|
// Transfer completed successfully
|
||||||
if (usb_state == US_READ)
|
if (flags & UX_READ) {
|
||||||
usb_send_ep0(NULL, 0);
|
// Send status packet at end of read
|
||||||
usb_state = US_READY;
|
flags = UX_SEND;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
usb_xfer_flags = 0;
|
||||||
|
usb_notify_ep0();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ret == -1)
|
if (ret == -1) {
|
||||||
// Interface busy - retry later
|
// Interface busy - retry later
|
||||||
|
usb_xfer_data = data;
|
||||||
|
usb_xfer_size = size;
|
||||||
|
usb_xfer_flags = flags;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
// Error
|
// Error
|
||||||
usb_do_stall();
|
usb_do_stall();
|
||||||
return;
|
return;
|
||||||
|
@ -348,12 +356,10 @@ usb_req_get_descriptor(struct usb_ctrlrequest *req)
|
||||||
const struct descriptor_s *d = &cdc_descriptors[i];
|
const struct descriptor_s *d = &cdc_descriptors[i];
|
||||||
if (READP(d->wValue) == req->wValue
|
if (READP(d->wValue) == req->wValue
|
||||||
&& READP(d->wIndex) == req->wIndex) {
|
&& READP(d->wIndex) == req->wIndex) {
|
||||||
usb_state = US_SEND;
|
uint_fast8_t size = READP(d->size);
|
||||||
usb_xfer = (void*)READP(d->desc);
|
if (size > req->wLength)
|
||||||
usb_xfer_size = READP(d->size);
|
size = req->wLength;
|
||||||
if (usb_xfer_size > req->wLength)
|
usb_do_xfer((void*)READP(d->desc), size, UX_SEND);
|
||||||
usb_xfer_size = req->wLength;
|
|
||||||
usb_state_xfer();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -370,8 +376,8 @@ static void
|
||||||
usb_req_set_configuration(struct usb_ctrlrequest *req)
|
usb_req_set_configuration(struct usb_ctrlrequest *req)
|
||||||
{
|
{
|
||||||
usb_set_configure();
|
usb_set_configure();
|
||||||
usb_send_ep0(NULL, 0);
|
|
||||||
usb_notify_bulk_in();
|
usb_notify_bulk_in();
|
||||||
|
usb_do_xfer(NULL, 0, UX_SEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct usb_cdc_line_coding line_coding;
|
static struct usb_cdc_line_coding line_coding;
|
||||||
|
@ -379,23 +385,19 @@ static struct usb_cdc_line_coding line_coding;
|
||||||
static void
|
static void
|
||||||
usb_req_set_line_coding(struct usb_ctrlrequest *req)
|
usb_req_set_line_coding(struct usb_ctrlrequest *req)
|
||||||
{
|
{
|
||||||
usb_state = US_READ;
|
usb_do_xfer(&line_coding, sizeof(line_coding), UX_READ);
|
||||||
usb_xfer = &line_coding;
|
|
||||||
usb_xfer_size = sizeof(line_coding);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usb_req_get_line_coding(struct usb_ctrlrequest *req)
|
usb_req_get_line_coding(struct usb_ctrlrequest *req)
|
||||||
{
|
{
|
||||||
usb_state = US_SEND;
|
usb_do_xfer(&line_coding, sizeof(line_coding), UX_SEND);
|
||||||
usb_xfer = &line_coding;
|
|
||||||
usb_xfer_size = sizeof(line_coding);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usb_req_line_state(struct usb_ctrlrequest *req)
|
usb_req_set_line(struct usb_ctrlrequest *req)
|
||||||
{
|
{
|
||||||
usb_send_ep0(NULL, 0);
|
usb_do_xfer(NULL, 0, UX_SEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -412,7 +414,7 @@ usb_state_ready(void)
|
||||||
case USB_REQ_SET_CONFIGURATION: usb_req_set_configuration(&req); break;
|
case USB_REQ_SET_CONFIGURATION: usb_req_set_configuration(&req); break;
|
||||||
case USB_CDC_REQ_SET_LINE_CODING: usb_req_set_line_coding(&req); break;
|
case USB_CDC_REQ_SET_LINE_CODING: usb_req_set_line_coding(&req); break;
|
||||||
case USB_CDC_REQ_GET_LINE_CODING: usb_req_get_line_coding(&req); break;
|
case USB_CDC_REQ_GET_LINE_CODING: usb_req_get_line_coding(&req); break;
|
||||||
case USB_CDC_REQ_SET_CONTROL_LINE_STATE: usb_req_line_state(&req); break;
|
case USB_CDC_REQ_SET_CONTROL_LINE_STATE: usb_req_set_line(&req); break;
|
||||||
default: usb_do_stall(); break;
|
default: usb_do_stall(); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -431,11 +433,10 @@ usb_ep0_task(void)
|
||||||
{
|
{
|
||||||
if (!sched_check_wake(&usb_ep0_wake))
|
if (!sched_check_wake(&usb_ep0_wake))
|
||||||
return;
|
return;
|
||||||
switch (usb_state) {
|
if (usb_xfer_flags)
|
||||||
case US_READY: usb_state_ready(); break;
|
usb_do_xfer(usb_xfer_data, usb_xfer_size, usb_xfer_flags);
|
||||||
case US_SEND: usb_state_xfer(); break;
|
else
|
||||||
case US_READ: usb_state_xfer(); break;
|
usb_state_ready();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
DECL_TASK(usb_ep0_task);
|
DECL_TASK(usb_ep0_task);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue