From fc49538d8613b15e44bea2ef1d6912837914ad2c Mon Sep 17 00:00:00 2001 From: Wojciech Zajac Date: Fri, 30 May 2014 14:58:16 +0200 Subject: [PATCH] Initial interrupt URBs support --- drivers/usbd/hcd/hcd.c | 87 ++++++++++++++---------- drivers/usbd/hcd/musb/musb_am335x.c | 8 +-- drivers/usbd/hcd/musb/musb_core.c | 60 ++++++++++++---- drivers/usbd/hcd/musb/musb_core.h | 4 +- drivers/usbd/include/usb/hcd_common.h | 35 +++++----- drivers/usbd/include/usb/hcd_interface.h | 4 +- 6 files changed, 125 insertions(+), 73 deletions(-) diff --git a/drivers/usbd/hcd/hcd.c b/drivers/usbd/hcd/hcd.c index bbb39dec9..fcb2edf24 100755 --- a/drivers/usbd/hcd/hcd.c +++ b/drivers/usbd/hcd/hcd.c @@ -30,11 +30,11 @@ static int hcd_get_descriptor_tree(hcd_device_state *); static int hcd_set_configuration(hcd_device_state *, int); static int hcd_handle_urb(hcd_device_state *); static int hcd_control_urb(hcd_device_state *); -static int hcd_bulk_urb(hcd_device_state *); +static int hcd_non_control_urb(hcd_device_state *, int); /* For internal use by more general methods */ static int hcd_setup_packet(hcd_device_state *, hcd_ctrlrequest *); -static int hcd_bulk_transfer(hcd_device_state *, hcd_bulkrequest *, int); +static int hcd_data_transfer(hcd_device_state *, hcd_datarequest *); /*===========================================================================* @@ -460,16 +460,13 @@ hcd_handle_urb(hcd_device_state * this_device) break; case USB_TRANSFER_BLK: - transfer_status = hcd_bulk_urb(this_device); - break; - case USB_TRANSFER_INT: - /* TODO: transfer */ - USB_MSG("Interrupt transfer not supported"); + transfer_status = hcd_non_control_urb(this_device, + urb->type); break; case USB_TRANSFER_ISO: - /* TODO: transfer */ + /* TODO: ISO transfer */ USB_MSG("ISO transfer not supported"); break; @@ -478,12 +475,15 @@ hcd_handle_urb(hcd_device_state * this_device) break; } -#ifndef URB_TEST - /* Call completion */ + if (EXIT_SUCCESS != transfer_status) + USB_MSG("USB transfer failed"); + + /* Call completion regardless of status */ hcd_completion_cb(urb->priv); -#endif - /* Only critical failures should ever yield EXIT_FAILURE */ + /* TODO: Only critical failures should ever yield EXIT_FAILURE, so + * return is not bound to transfer_status for now, to let device + * driver act accordingly */ return EXIT_SUCCESS; } @@ -538,13 +538,13 @@ hcd_control_urb(hcd_device_state * this_device) /*===========================================================================* - * hcd_bulk_urb * + * hcd_non_control_urb * *===========================================================================*/ static int -hcd_bulk_urb(hcd_device_state * this_device) +hcd_non_control_urb(hcd_device_state * this_device, int type) { hcd_endpoint * e; - hcd_bulkrequest request; + hcd_datarequest request; hcd_urb * urb; DEBUG_DUMP; @@ -555,7 +555,7 @@ hcd_bulk_urb(hcd_device_state * this_device) urb->status = EINVAL; if (NULL == urb->data) { - USB_MSG("No data packet in URB, for bulk transfer"); + USB_MSG("No data packet in URB"); return EXIT_FAILURE; } @@ -571,12 +571,28 @@ hcd_bulk_urb(hcd_device_state * this_device) return EXIT_FAILURE; } + /* TODO: usb.h constants to type mapping */ + switch (type) { + case USB_TRANSFER_BLK: + request.type = HCD_TRANSFER_BULK; + break; + case USB_TRANSFER_INT: + request.type = HCD_TRANSFER_INTERRUPT; + break; + default: + /* TODO: ISO transfer */ + USB_MSG("Invalid transfer type"); + return EXIT_FAILURE; + } + /* TODO: Any additional checks? (sane size?) */ - /* Assign to bulk request structure */ + /* Assign to data request structure */ request.endpoint = urb->endpoint; + request.direction = urb->direction; request.size = (int)urb->size; request.data = urb->data; + request.interval = urb->interval; /* Check if EP number is valid */ e = hcd_tree_find_ep(&(this_device->config_tree), request.endpoint); @@ -594,7 +610,7 @@ hcd_bulk_urb(hcd_device_state * this_device) } /* Check if remembered type matches */ - if (e->descriptor.bmAttributes != UE_BULK) { + if (UE_GET_XFERTYPE(e->descriptor.bmAttributes) != (int)request.type) { USB_MSG("EP type mismatch"); return EXIT_FAILURE; } @@ -605,14 +621,14 @@ hcd_bulk_urb(hcd_device_state * this_device) /* Let know how to configure EP for speed */ request.speed = this_device->speed; - /* Send bulk data */ - if (EXIT_SUCCESS != hcd_bulk_transfer(this_device, &request, - urb->direction)) { - USB_MSG("URB bulk transfer, failed"); + /* Start sending data */ + if (EXIT_SUCCESS != hcd_data_transfer(this_device, &request)) { + USB_MSG("URB non-control transfer, failed"); urb->status = EPIPE; return EXIT_FAILURE; } + /* Transfer successfully completed */ urb->status = EXIT_SUCCESS; return EXIT_SUCCESS; } @@ -743,14 +759,13 @@ hcd_setup_packet(hcd_device_state * this_device, hcd_ctrlrequest * setup) /*===========================================================================* - * hcd_bulk_transfer * + * hcd_data_transfer * *===========================================================================*/ static int -hcd_bulk_transfer(hcd_device_state * this_device, hcd_bulkrequest * request, - int direction) +hcd_data_transfer(hcd_device_state * this_device, hcd_datarequest * request) { hcd_driver_state * d; - hcd_bulkrequest temp_req; + hcd_datarequest temp_req; int transfer_len; DEBUG_DUMP; @@ -764,11 +779,11 @@ hcd_bulk_transfer(hcd_device_state * this_device, hcd_bulkrequest * request, this_device->address); /* TODO: broken USB_IN... constants */ - if (1 == direction) { + if (1 == request->direction) { do { - /* Start actual bulk transfer */ - d->bulk_in_stage(d->private_data, request); + /* Start actual data transfer */ + d->rx_stage(d->private_data, request); /* Wait for response */ hcd_device_wait(this_device, HCD_EVENT_ENDPOINT, @@ -776,7 +791,7 @@ hcd_bulk_transfer(hcd_device_state * this_device, hcd_bulkrequest * request, /* Check response */ if (EXIT_SUCCESS != d->check_error(d->private_data, - HCD_TRANSFER_BULK, + request->type, HCD_DIRECTION_IN)) return EXIT_FAILURE; @@ -792,7 +807,8 @@ hcd_bulk_transfer(hcd_device_state * this_device, hcd_bulkrequest * request, USB_ASSERT(request->size >= 0, "Invalid amount of data received"); - /* TODO: REMOVEME (dumping of bulk transfer) */ +#ifdef DEBUG + /* TODO: REMOVEME (dumping of data transfer) */ { int i; USB_MSG("RECEIVED: %d", transfer_len); @@ -800,10 +816,11 @@ hcd_bulk_transfer(hcd_device_state * this_device, hcd_bulkrequest * request, USB_MSG("%c", (request->data-transfer_len)[i]); } +#endif } while (0 != request->size); - } else if (0 == direction) { + } else if (0 == request->direction) { do { temp_req = *request; @@ -820,8 +837,8 @@ hcd_bulk_transfer(hcd_device_state * this_device, hcd_bulkrequest * request, USB_ASSERT(request->size >= 0, "Invalid amount of data received"); - /* Start actual bulk transfer */ - d->bulk_out_stage(d->private_data, &temp_req); + /* Start actual data transfer */ + d->tx_stage(d->private_data, &temp_req); /* Wait for response */ hcd_device_wait(this_device, HCD_EVENT_ENDPOINT, @@ -829,7 +846,7 @@ hcd_bulk_transfer(hcd_device_state * this_device, hcd_bulkrequest * request, /* Check response */ if (EXIT_SUCCESS != d->check_error(d->private_data, - HCD_TRANSFER_BULK, + request->type, HCD_DIRECTION_OUT)) return EXIT_FAILURE; diff --git a/drivers/usbd/hcd/musb/musb_am335x.c b/drivers/usbd/hcd/musb/musb_am335x.c index f818e5f25..b60848b1e 100755 --- a/drivers/usbd/hcd/musb/musb_am335x.c +++ b/drivers/usbd/hcd/musb/musb_am335x.c @@ -339,8 +339,8 @@ musb_am335x_init(void) ctrl->driver.setup_device = musb_setup_device; ctrl->driver.reset_device = musb_reset_device; ctrl->driver.setup_stage = musb_setup_stage; - ctrl->driver.bulk_in_stage = musb_bulk_in_stage; - ctrl->driver.bulk_out_stage = musb_bulk_out_stage; + ctrl->driver.rx_stage = musb_rx_stage; + ctrl->driver.tx_stage = musb_tx_stage; ctrl->driver.in_data_stage = musb_in_data_stage; ctrl->driver.out_data_stage = musb_out_data_stage; ctrl->driver.in_status_stage = musb_in_status_stage; @@ -379,8 +379,8 @@ musb_am335x_init(void) ctrl->driver.setup_device = musb_setup_device; ctrl->driver.reset_device = musb_reset_device; ctrl->driver.setup_stage = musb_setup_stage; - ctrl->driver.bulk_in_stage = musb_bulk_in_stage; - ctrl->driver.bulk_out_stage = musb_bulk_out_stage; + ctrl->driver.rx_stage = musb_rx_stage; + ctrl->driver.tx_stage = musb_tx_stage; ctrl->driver.in_data_stage = musb_in_data_stage; ctrl->driver.out_data_stage = musb_out_data_stage; ctrl->driver.in_status_stage = musb_in_status_stage; diff --git a/drivers/usbd/hcd/musb/musb_core.c b/drivers/usbd/hcd/musb/musb_core.c index f17a0972e..0c36e6ae3 100755 --- a/drivers/usbd/hcd/musb/musb_core.c +++ b/drivers/usbd/hcd/musb/musb_core.c @@ -454,10 +454,10 @@ musb_setup_stage(void * cfg, hcd_ctrlrequest * setup) /*===========================================================================* - * musb_bulk_in_stage * + * musb_rx_stage * *===========================================================================*/ void -musb_bulk_in_stage(void * cfg, hcd_bulkrequest * request) +musb_rx_stage(void * cfg, hcd_datarequest * request) { musb_core_config * core; #if 0 @@ -472,15 +472,27 @@ musb_bulk_in_stage(void * cfg, hcd_bulkrequest * request) core = (musb_core_config *)cfg; r = core->regs; - USB_ASSERT(request->max_packet_size <= 1024, "Invalid wMaxPacketSize"); + USB_ASSERT(request->max_packet_size <= 1024, + "Invalid wMaxPacketSize"); USB_ASSERT((core->ep <= 15) && (core->ep > 0), - "Invalid bulk EP supplied"); + "Invalid bulk EP supplied"); /* Set EP and device address to be used in this command */ musb_set_state(core); /* Evaluate RXTYPE */ - host_rxtype = MUSB_VAL_HOST_XXTYPE_BULK | core->ep; + host_rxtype = core->ep; + + switch (request->type) { + case HCD_TRANSFER_BULK: + host_rxtype |= MUSB_VAL_HOST_XXTYPE_BULK; + break; + case HCD_TRANSFER_INTERRUPT: + host_rxtype |= MUSB_VAL_HOST_XXTYPE_INTERRUPT; + break; + default: + USB_ASSERT(0, "Unsupported transfer type"); + } if (HCD_SPEED_HIGH == request->speed) host_rxtype |= MUSB_VAL_HOST_XXTYPE_HIGH_SPEED; @@ -493,8 +505,12 @@ musb_bulk_in_stage(void * cfg, hcd_bulkrequest * request) /* Rewrite RXMAXP */ HCD_WR2(r, MUSB_REG_RXMAXP, request->max_packet_size); - /* Rewrite HOST_RXINTERVAL */ - HCD_WR1(r, MUSB_REG_HOST_RXINTERVAL, MUSB_VAL_HOST_XXINTERVAL_DEFAULT); + /* Set HOST_RXINTERVAL based on transfer type */ + if (HCD_TRANSFER_BULK == request->type) + HCD_WR1(r, MUSB_REG_HOST_RXINTERVAL, + MUSB_VAL_HOST_XXINTERVAL_DEFAULT); + else if (HCD_TRANSFER_INTERRUPT == request->type) + HCD_WR1(r, MUSB_REG_HOST_RXINTERVAL, request->interval); /* Not required in some MUSB implementations */ #if 0 @@ -536,10 +552,10 @@ musb_bulk_in_stage(void * cfg, hcd_bulkrequest * request) /*===========================================================================* - * musb_bulk_out_stage * + * musb_tx_stage * *===========================================================================*/ void -musb_bulk_out_stage(void * cfg, hcd_bulkrequest * request) +musb_tx_stage(void * cfg, hcd_datarequest * request) { musb_core_config * core; #if 0 @@ -554,15 +570,27 @@ musb_bulk_out_stage(void * cfg, hcd_bulkrequest * request) core = (musb_core_config *)cfg; r = core->regs; - USB_ASSERT(request->max_packet_size <= 1024, "Invalid wMaxPacketSize"); + USB_ASSERT(request->max_packet_size <= 1024, + "Invalid wMaxPacketSize"); USB_ASSERT((core->ep <= 15) && (core->ep > 0), - "Invalid bulk EP supplied"); + "Invalid bulk EP supplied"); /* Set EP and device address to be used in this command */ musb_set_state(core); /* Evaluate TXTYPE */ - host_txtype = MUSB_VAL_HOST_XXTYPE_BULK | core->ep; + host_txtype = core->ep; + + switch (request->type) { + case HCD_TRANSFER_BULK: + host_txtype |= MUSB_VAL_HOST_XXTYPE_BULK; + break; + case HCD_TRANSFER_INTERRUPT: + host_txtype |= MUSB_VAL_HOST_XXTYPE_INTERRUPT; + break; + default: + USB_ASSERT(0, "Unsupported transfer type"); + } if (HCD_SPEED_HIGH == request->speed) host_txtype |= MUSB_VAL_HOST_XXTYPE_HIGH_SPEED; @@ -575,8 +603,12 @@ musb_bulk_out_stage(void * cfg, hcd_bulkrequest * request) /* Rewrite TXMAXP */ HCD_WR2(r, MUSB_REG_TXMAXP, request->max_packet_size); - /* Rewrite HOST_TXINTERVAL */ - HCD_WR1(r, MUSB_REG_HOST_TXINTERVAL, MUSB_VAL_HOST_XXINTERVAL_DEFAULT); + /* Set HOST_TXINTERVAL based on transfer type */ + if (HCD_TRANSFER_BULK == request->type) + HCD_WR1(r, MUSB_REG_HOST_TXINTERVAL, + MUSB_VAL_HOST_XXINTERVAL_DEFAULT); + else if (HCD_TRANSFER_INTERRUPT == request->type) + HCD_WR1(r, MUSB_REG_HOST_TXINTERVAL, request->interval); /* Not required in some MUSB implementations */ #if 0 diff --git a/drivers/usbd/hcd/musb/musb_core.h b/drivers/usbd/hcd/musb/musb_core.h index e51f15988..e60713f9e 100755 --- a/drivers/usbd/hcd/musb/musb_core.h +++ b/drivers/usbd/hcd/musb/musb_core.h @@ -35,8 +35,8 @@ void musb_core_stop(void *); void musb_setup_device(void *, hcd_reg1, hcd_reg1); int musb_reset_device(void *, hcd_speed *); void musb_setup_stage(void *, hcd_ctrlrequest *); -void musb_bulk_in_stage(void *, hcd_bulkrequest *); -void musb_bulk_out_stage(void *, hcd_bulkrequest *); +void musb_rx_stage(void *, hcd_datarequest *); +void musb_tx_stage(void *, hcd_datarequest *); void musb_in_data_stage(void *); void musb_out_data_stage(void *); void musb_in_status_stage(void *); diff --git a/drivers/usbd/include/usb/hcd_common.h b/drivers/usbd/include/usb/hcd_common.h index 6df67ae52..7d3f251fb 100755 --- a/drivers/usbd/include/usb/hcd_common.h +++ b/drivers/usbd/include/usb/hcd_common.h @@ -150,22 +150,6 @@ typedef struct hcd_device_state { hcd_device_state; -/*===========================================================================* - * HCD transfer requests * - *===========================================================================*/ -struct hcd_bulkrequest { - - char * data; - int size; - int endpoint; - unsigned int max_packet_size; - hcd_speed speed; -}; - -typedef struct usb_ctrlrequest hcd_ctrlrequest; -typedef struct hcd_bulkrequest hcd_bulkrequest; - - /*===========================================================================* * HCD event handling * *===========================================================================*/ @@ -203,6 +187,25 @@ hcd_event; #define HCD_ENDPOINT_0 0 +/*===========================================================================* + * HCD transfer requests * + *===========================================================================*/ +struct hcd_datarequest { + + char * data; + int size; + int endpoint; + int direction; + unsigned int max_packet_size; + unsigned int interval; + hcd_speed speed; + hcd_transfer type; +}; + +typedef struct usb_ctrlrequest hcd_ctrlrequest; +typedef struct hcd_datarequest hcd_datarequest; + + /*===========================================================================* * Other definitions * *===========================================================================*/ diff --git a/drivers/usbd/include/usb/hcd_interface.h b/drivers/usbd/include/usb/hcd_interface.h index c59d6e62f..3d20f1c4f 100755 --- a/drivers/usbd/include/usb/hcd_interface.h +++ b/drivers/usbd/include/usb/hcd_interface.h @@ -26,8 +26,8 @@ struct hcd_driver_state { void (*setup_device) (void *, hcd_reg1, hcd_reg1); int (*reset_device) (void *, hcd_speed *); void (*setup_stage) (void *, hcd_ctrlrequest *); - void (*bulk_in_stage) (void *, hcd_bulkrequest *); - void (*bulk_out_stage) (void *, hcd_bulkrequest *); + void (*rx_stage) (void *, hcd_datarequest *); + void (*tx_stage) (void *, hcd_datarequest *); void (*in_data_stage) (void *); void (*out_data_stage) (void *); void (*in_status_stage) (void *); -- 2.44.0