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 *);
/*===========================================================================*
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;
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;
}
/*===========================================================================*
- * 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;
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;
}
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);
}
/* 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;
}
/* 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;
}
/*===========================================================================*
- * 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;
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,
/* Check response */
if (EXIT_SUCCESS != d->check_error(d->private_data,
- HCD_TRANSFER_BULK,
+ request->type,
HCD_DIRECTION_IN))
return EXIT_FAILURE;
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);
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;
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,
/* Check response */
if (EXIT_SUCCESS != d->check_error(d->private_data,
- HCD_TRANSFER_BULK,
+ request->type,
HCD_DIRECTION_OUT))
return EXIT_FAILURE;
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;
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;
/*===========================================================================*
- * 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
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;
/* 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
/*===========================================================================*
- * 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
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;
/* 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
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 *);
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 *
*===========================================================================*/
#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 *
*===========================================================================*/
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 *);