Initial interrupt URBs support

This commit is contained in:
Wojciech Zajac 2014-05-30 14:58:16 +02:00 committed by Lionel Sambuc
parent efa169276f
commit fc49538d86
6 changed files with 126 additions and 74 deletions

View file

@ -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 */
hcd_completion_cb(urb->priv);
#endif
if (EXIT_SUCCESS != transfer_status)
USB_MSG("USB transfer failed");
/* Only critical failures should ever yield EXIT_FAILURE */
/* Call completion regardless of status */
hcd_completion_cb(urb->priv);
/* 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;

View file

@ -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;

View file

@ -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

View file

@ -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 *);

View file

@ -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 *
*===========================================================================*/

View file

@ -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 *);