Unification of various HCD types.

DDEKit URB's are no longer directly handled by HCD but rather translated and validated to avoid type conversion issues and illegal values.
This commit is contained in:
Wojciech Zajac 2014-06-13 12:50:13 +02:00 committed by Lionel Sambuc
parent e576602d9e
commit 1858789bf6
8 changed files with 323 additions and 229 deletions

View File

@ -9,9 +9,8 @@ SRCS= usbd.c usbd_earm.c hcd.c hcd_common.c hcd_ddekit.c musb_am335x.c musb_cor
CPPFLAGS+= -I${.CURDIR}/../../include CPPFLAGS+= -I${.CURDIR}/../../include
DPADD+= ${LIBDDEKIT} ${LIBDDEKIT_USB_SERVER} ${LIBDEVMAN} ${LIBUSB} ${LIBMINC} ${LIBCLKCONF} DPADD+= ${LIBDDEKIT} ${LIBDDEKIT_USB_SERVER} ${LIBDEVMAN} ${LIBUSB} ${LIBMINC} ${LIBCLKCONF} ${LIBSYS} ${LIBMINLIB}
LDADD+= -lddekit -lddekit_usb_server -ldevman -lusb -lminc -lclkconf LDADD+= -lddekit -lddekit_usb_server -ldevman -lusb -lminc -lclkconf -lsys -lminlib
LDADD+= -lsys -lminlib
MAN= MAN=

View File

@ -5,7 +5,6 @@
#include <string.h> /* memcpy */ #include <string.h> /* memcpy */
#include <minix/drivers.h> /* errno with sign */ #include <minix/drivers.h> /* errno with sign */
#include <minix/usb.h> /* USB_TRANSFER_CTL... */
#include <usb/hcd_common.h> #include <usb/hcd_common.h>
#include <usb/hcd_ddekit.h> #include <usb/hcd_ddekit.h>
@ -25,12 +24,12 @@ static void hcd_device_finish(hcd_device_state *, const char *);
/* Typical USD device communication procedures */ /* Typical USD device communication procedures */
static int hcd_enumerate(hcd_device_state *); static int hcd_enumerate(hcd_device_state *);
static int hcd_get_device_descriptor(hcd_device_state *); static int hcd_get_device_descriptor(hcd_device_state *);
static int hcd_set_address(hcd_device_state *, int); static int hcd_set_address(hcd_device_state *, hcd_reg1);
static int hcd_get_descriptor_tree(hcd_device_state *); static int hcd_get_descriptor_tree(hcd_device_state *);
static int hcd_set_configuration(hcd_device_state *, hcd_reg1); static int hcd_set_configuration(hcd_device_state *, hcd_reg1);
static int hcd_handle_urb(hcd_device_state *); static int hcd_handle_urb(hcd_device_state *, hcd_urb *);
static int hcd_control_urb(hcd_device_state *); static int hcd_control_urb(hcd_device_state *, hcd_urb *);
static int hcd_non_control_urb(hcd_device_state *, int); static int hcd_non_control_urb(hcd_device_state *, hcd_urb *);
/* For internal use by more general methods */ /* For internal use by more general methods */
static int hcd_setup_packet(hcd_device_state *, hcd_ctrlrequest *, hcd_reg1); static int hcd_setup_packet(hcd_device_state *, hcd_ctrlrequest *, hcd_reg1);
@ -148,13 +147,11 @@ hcd_device_thread(void * thread_args)
/* Start handling URB's */ /* Start handling URB's */
for(;;) { for(;;) {
/* No URB's yet */
this_device->urb = NULL;
/* Block and wait for something like 'submit URB' */ /* Block and wait for something like 'submit URB' */
hcd_device_wait(this_device, HCD_EVENT_URB, HCD_NO_ENDPOINT); hcd_device_wait(this_device, HCD_EVENT_URB, HCD_ANY_EP);
if (EXIT_SUCCESS != hcd_handle_urb(this_device)) if (EXIT_SUCCESS != hcd_handle_urb(this_device,
&(this_device->urb)))
hcd_device_finish(this_device, "URB handling failed"); hcd_device_finish(this_device, "URB handling failed");
} }
@ -175,7 +172,7 @@ hcd_device_finish(hcd_device_state * this_device, const char * finish_msg)
/* Lock forever */ /* Lock forever */
for (;;) { for (;;) {
hcd_device_wait(this_device, HCD_EVENT_URB, HCD_NO_ENDPOINT); hcd_device_wait(this_device, HCD_EVENT_URB, HCD_ANY_EP);
USB_MSG("Failed attempt to continue finished thread"); USB_MSG("Failed attempt to continue finished thread");
} }
} }
@ -308,13 +305,15 @@ hcd_get_device_descriptor(hcd_device_state * this_device)
* hcd_set_address * * hcd_set_address *
*===========================================================================*/ *===========================================================================*/
static int static int
hcd_set_address(hcd_device_state * this_device, int address) hcd_set_address(hcd_device_state * this_device, hcd_reg1 address)
{ {
hcd_ctrlrequest setup; hcd_ctrlrequest setup;
DEBUG_DUMP; DEBUG_DUMP;
USB_ASSERT((address > 0) && (address < 128), "Illegal address"); /* Check for legal USB device address (must be non-zero as well) */
USB_ASSERT((address > HCD_DEFAULT_ADDR) && (address <= HCD_LAST_ADDR),
"Illegal device address supplied");
/* TODO: magic numbers, no header for these */ /* TODO: magic numbers, no header for these */
setup.bRequestType = 0x00; /* OUT */ setup.bRequestType = 0x00; /* OUT */
@ -348,9 +347,9 @@ hcd_get_descriptor_tree(hcd_device_state * this_device)
{ {
hcd_config_descriptor config_descriptor; hcd_config_descriptor config_descriptor;
hcd_ctrlrequest setup; hcd_ctrlrequest setup;
hcd_reg4 total_length;
hcd_reg4 buffer_length;
int completed; int completed;
int total_length;
int buffer_length;
DEBUG_DUMP; DEBUG_DUMP;
@ -384,19 +383,16 @@ hcd_get_descriptor_tree(hcd_device_state * this_device)
sizeof(config_descriptor)); sizeof(config_descriptor));
/* Continue only if there is more data */ /* Continue only if there is more data */
total_length = config_descriptor.wTotalLength[0] + total_length = UGETW(config_descriptor.wTotalLength);
(config_descriptor.wTotalLength[1] << 8);
if (total_length < (int)sizeof(config_descriptor)) { if (total_length < sizeof(config_descriptor)) {
/* This should never happen for a fine device */ /* This should never happen for a fine device */
USB_MSG("Illegal wTotalLength value"); USB_MSG("Illegal wTotalLength value");
return EXIT_FAILURE; return EXIT_FAILURE;
} } else if (sizeof(config_descriptor) == total_length) {
else if (sizeof(config_descriptor) == total_length) {
/* Nothing more was in descriptor anyway */ /* Nothing more was in descriptor anyway */
completed = 1; completed = 1;
} } else {
else {
/* Read whatever is needed */ /* Read whatever is needed */
buffer_length = total_length; buffer_length = total_length;
} }
@ -453,48 +449,44 @@ hcd_set_configuration(hcd_device_state * this_device, hcd_reg1 configuration)
* hcd_handle_urb * * hcd_handle_urb *
*===========================================================================*/ *===========================================================================*/
static int static int
hcd_handle_urb(hcd_device_state * this_device) hcd_handle_urb(hcd_device_state * this_device, hcd_urb * urb)
{ {
hcd_urb * urb;
int transfer_status; int transfer_status;
DEBUG_DUMP; DEBUG_DUMP;
transfer_status = EXIT_FAILURE; transfer_status = EXIT_FAILURE;
urb = this_device->urb;
USB_ASSERT(NULL != urb, "NULL URB given");
/* TODO: One device only */ /* TODO: One device only */
USB_ASSERT((void *)this_device == (void *)urb->dev, USB_ASSERT(NULL != urb, "NULL URB given");
"Unknown device for URB"); USB_ASSERT(this_device == urb->target_device, "Unknown device for URB");
switch (urb->type) { switch (urb->type) {
case HCD_TRANSFER_CONTROL:
case USB_TRANSFER_CTL: transfer_status = hcd_control_urb(this_device, urb);
transfer_status = hcd_control_urb(this_device);
break; break;
case USB_TRANSFER_BLK: case HCD_TRANSFER_BULK:
case USB_TRANSFER_INT: case HCD_TRANSFER_INTERRUPT:
transfer_status = hcd_non_control_urb(this_device, transfer_status = hcd_non_control_urb(this_device, urb);
urb->type);
break; break;
case USB_TRANSFER_ISO: case HCD_TRANSFER_ISOCHRONOUS:
/* TODO: ISO transfer */ /* TODO: ISO transfer */
USB_MSG("ISO transfer not supported"); USB_MSG("ISO transfer not supported");
break; break;
default: default:
USB_MSG("Invalid transfer type 0x%X", urb->type); USB_MSG("Invalid transfer type 0x%02X", (int)urb->type);
break; break;
} }
/* In case of error, only dump message */
if (EXIT_SUCCESS != transfer_status) if (EXIT_SUCCESS != transfer_status)
USB_MSG("USB transfer failed"); USB_MSG("USB transfer failed");
/* Call completion regardless of status */ /* Call completion regardless of status */
hcd_completion_cb(urb->priv); hcd_completion_cb(urb);
/* TODO: Only critical failures should ever yield EXIT_FAILURE, so /* TODO: Only critical failures should ever yield EXIT_FAILURE, so
* return is not bound to transfer_status for now, to let device * return is not bound to transfer_status for now, to let device
@ -507,52 +499,44 @@ hcd_handle_urb(hcd_device_state * this_device)
* hcd_control_urb * * hcd_control_urb *
*===========================================================================*/ *===========================================================================*/
static int static int
hcd_control_urb(hcd_device_state * this_device) hcd_control_urb(hcd_device_state * this_device, hcd_urb * urb)
{ {
hcd_urb * urb;
hcd_ctrlrequest setup;
DEBUG_DUMP; DEBUG_DUMP;
urb = this_device->urb;
/* Assume bad values unless something different occurs later */ /* Assume bad values unless something different occurs later */
urb->status = EINVAL; urb->inout_status = EINVAL;
/* Must have setup packet */ /* Must have setup packet for control transfer */
if (NULL == urb->setup_packet) { if (NULL == urb->in_setup) {
USB_MSG("No setup packet in URB, for control transfer"); USB_MSG("No setup packet in URB, for control transfer");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
/* TODO: Only EP0 can have control transfer */ /* TODO: Only EP0 can have control transfer */
if (0 != urb->endpoint) { if (HCD_DEFAULT_EP != urb->endpoint) {
USB_MSG("Control transfer for non zero EP"); USB_MSG("Control transfer for non zero EP");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
/* Hold setup packet and analyze it */ /* Setup and URB directions should match */
memcpy(&setup, urb->setup_packet, sizeof(setup)); if (((urb->in_setup->bRequestType >> 7) & 0x01) != urb->direction) {
/* TODO: broken constants for urb->direction (USB_OUT...) */
if (((setup.bRequestType >> 7) & 0x01) != urb->direction) {
USB_MSG("URB Direction mismatch"); USB_MSG("URB Direction mismatch");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
/* Send setup packet */ /* Send setup packet */
if (EXIT_SUCCESS != hcd_setup_packet(this_device, &setup, if (EXIT_SUCCESS != hcd_setup_packet(this_device, urb->in_setup,
(hcd_reg1)urb->endpoint)) { urb->endpoint)) {
USB_MSG("Sending URB setup packet, failed"); USB_MSG("Sending URB setup packet, failed");
urb->status = EPIPE; urb->inout_status = EPIPE;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
/* TODO: Calling memcpy may be removed when writing directly to URB */ /* TODO: Calling memcpy may be removed when writing directly to URB */
/* Put what was read back into URB */ /* Put what was read back into URB */
memcpy(urb->data, this_device->buffer, this_device->data_len); memcpy(urb->inout_data, this_device->buffer, this_device->data_len);
urb->actual_length = (unsigned int)this_device->data_len; urb->out_size = this_device->data_len;
urb->status = EXIT_SUCCESS; urb->inout_status = EXIT_SUCCESS;
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
@ -562,80 +546,55 @@ hcd_control_urb(hcd_device_state * this_device)
* hcd_non_control_urb * * hcd_non_control_urb *
*===========================================================================*/ *===========================================================================*/
static int static int
hcd_non_control_urb(hcd_device_state * this_device, int type) hcd_non_control_urb(hcd_device_state * this_device, hcd_urb * urb)
{ {
hcd_endpoint * e; hcd_endpoint * e;
hcd_datarequest request; hcd_datarequest request;
hcd_urb * urb;
DEBUG_DUMP; DEBUG_DUMP;
urb = this_device->urb;
/* Assume bad values unless something different occurs later */ /* Assume bad values unless something different occurs later */
urb->status = EINVAL; urb->inout_status = EINVAL;
if (NULL == urb->data) { /* Must have data buffer to send/receive */
if (NULL == urb->inout_data) {
USB_MSG("No data packet in URB"); USB_MSG("No data packet in URB");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if ((UE_GET_ADDR(urb->endpoint) >= HCD_TOTAL_EP) || if (HCD_DEFAULT_EP == urb->endpoint) {
(UE_GET_ADDR(urb->endpoint) <= HCD_DEFAULT_EP)) { USB_MSG("Non-control transfer for EP0");
USB_MSG("Illegal EP number");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
/* TODO: broken USB_IN... constants */ /* Check if EP number is valid within remembered descriptor tree */
if ((1 != urb->direction) && (0 != urb->direction)) { e = hcd_tree_find_ep(&(this_device->config_tree), urb->endpoint);
USB_MSG("Illegal EP direction");
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 data request structure */
request.endpoint = urb->endpoint;
request.direction = urb->direction;
request.data_left = (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);
if (NULL == e) { if (NULL == e) {
USB_MSG("Invalid EP value"); USB_MSG("Invalid EP number for this device");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
/* TODO: broken constants for urb->direction (USB_OUT...) */ /* Check if remembered descriptor direction, matches the one in URB */
/* Check if remembered direction matches */
if (((e->descriptor.bEndpointAddress >> 7) & 0x01) != urb->direction) { if (((e->descriptor.bEndpointAddress >> 7) & 0x01) != urb->direction) {
USB_MSG("EP direction mismatch"); USB_MSG("EP direction mismatch");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
/* Check if remembered type matches */ /* Check if remembered type matches */
if (UE_GET_XFERTYPE(e->descriptor.bmAttributes) != (int)request.type) { if (UE_GET_XFERTYPE(e->descriptor.bmAttributes) != urb->type) {
USB_MSG("EP type mismatch"); USB_MSG("EP type mismatch");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
/* Assign URB values to data request structure */
request.type = urb->type;
request.endpoint = urb->endpoint;
request.direction = urb->direction;
request.data_left = urb->in_size;
request.data = urb->inout_data;
request.interval = urb->interval;
/* Assign to let know how much data can be transfered at a time */ /* Assign to let know how much data can be transfered at a time */
request.max_packet_size = UGETW(e->descriptor.wMaxPacketSize); request.max_packet_size = UGETW(e->descriptor.wMaxPacketSize);
@ -645,13 +604,13 @@ hcd_non_control_urb(hcd_device_state * this_device, int type)
/* Start sending data */ /* Start sending data */
if (EXIT_SUCCESS != hcd_data_transfer(this_device, &request)) { if (EXIT_SUCCESS != hcd_data_transfer(this_device, &request)) {
USB_MSG("URB non-control transfer, failed"); USB_MSG("URB non-control transfer, failed");
urb->status = EPIPE; urb->inout_status = EPIPE;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
/* Transfer successfully completed */ /* Transfer successfully completed */
urb->actual_length = urb->size - request.data_left; urb->out_size = urb->in_size - request.data_left;
urb->status = EXIT_SUCCESS; urb->inout_status = EXIT_SUCCESS;
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
@ -671,10 +630,10 @@ hcd_setup_packet(hcd_device_state * this_device, hcd_ctrlrequest * setup,
DEBUG_DUMP; DEBUG_DUMP;
/* Should have been set at enumeration or with default values */ /* Should have been set at enumeration or with default values */
USB_ASSERT(this_device->max_packet_size > 0, USB_ASSERT(this_device->max_packet_size >= HCD_LS_MAXPACKETSIZE,
"Illegal MaxPacketSize for EP0"); "Illegal MaxPacketSize");
USB_ASSERT((ep <= HCD_LAST_EP), "Invalid EP number"); USB_ASSERT(ep <= HCD_LAST_EP, "Invalid EP number");
USB_ASSERT((hcd_reg1)(this_device->address) <= HCD_LAST_ADDR, USB_ASSERT(this_device->address <= HCD_LAST_ADDR,
"Invalid device address"); "Invalid device address");
/* Initially... */ /* Initially... */
@ -683,13 +642,13 @@ hcd_setup_packet(hcd_device_state * this_device, hcd_ctrlrequest * setup,
this_device->data_len = 0; /* Nothing read yet */ this_device->data_len = 0; /* Nothing read yet */
/* Set parameters for further communication */ /* Set parameters for further communication */
d->setup_device(d->private_data, ep, (hcd_reg1)this_device->address); d->setup_device(d->private_data, ep, this_device->address);
/* Send setup packet */ /* Send setup packet */
d->setup_stage(d->private_data, setup); d->setup_stage(d->private_data, setup);
/* Wait for response */ /* Wait for response */
hcd_device_wait(this_device, HCD_EVENT_ENDPOINT, HCD_ENDPOINT_0); hcd_device_wait(this_device, HCD_EVENT_ENDPOINT, ep);
/* Check response */ /* Check response */
if (EXIT_SUCCESS != d->check_error(d->private_data, if (EXIT_SUCCESS != d->check_error(d->private_data,
@ -711,8 +670,7 @@ hcd_setup_packet(hcd_device_state * this_device, hcd_ctrlrequest * setup,
/* Wait for response */ /* Wait for response */
hcd_device_wait(this_device, hcd_device_wait(this_device,
HCD_EVENT_ENDPOINT, HCD_EVENT_ENDPOINT, ep);
HCD_ENDPOINT_0);
/* Check response */ /* Check response */
if (EXIT_SUCCESS != d->check_error( if (EXIT_SUCCESS != d->check_error(
@ -723,7 +681,7 @@ hcd_setup_packet(hcd_device_state * this_device, hcd_ctrlrequest * setup,
/* Read data received as response */ /* Read data received as response */
rx_len = d->read_data(d->private_data, rx_len = d->read_data(d->private_data,
current_byte, HCD_DEFAULT_EP); current_byte, ep);
/* Increment */ /* Increment */
current_byte += rx_len; current_byte += rx_len;
@ -763,8 +721,7 @@ hcd_setup_packet(hcd_device_state * this_device, hcd_ctrlrequest * setup,
d->out_status_stage(d->private_data); d->out_status_stage(d->private_data);
/* Wait for response */ /* Wait for response */
hcd_device_wait(this_device, HCD_EVENT_ENDPOINT, hcd_device_wait(this_device, HCD_EVENT_ENDPOINT, ep);
HCD_ENDPOINT_0);
/* Check response */ /* Check response */
if (EXIT_SUCCESS != d->check_error(d->private_data, if (EXIT_SUCCESS != d->check_error(d->private_data,
@ -778,8 +735,7 @@ hcd_setup_packet(hcd_device_state * this_device, hcd_ctrlrequest * setup,
d->in_status_stage(d->private_data); d->in_status_stage(d->private_data);
/* Wait for response */ /* Wait for response */
hcd_device_wait(this_device, HCD_EVENT_ENDPOINT, hcd_device_wait(this_device, HCD_EVENT_ENDPOINT, ep);
HCD_ENDPOINT_0);
/* Check response */ /* Check response */
if (EXIT_SUCCESS != d->check_error(d->private_data, if (EXIT_SUCCESS != d->check_error(d->private_data,
@ -788,7 +744,7 @@ hcd_setup_packet(hcd_device_state * this_device, hcd_ctrlrequest * setup,
return EXIT_FAILURE; return EXIT_FAILURE;
/* Read zero data from response to clear registers */ /* Read zero data from response to clear registers */
if (0 != d->read_data(d->private_data, NULL, HCD_DEFAULT_EP)) if (0 != d->read_data(d->private_data, NULL, ep))
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -810,7 +766,7 @@ hcd_data_transfer(hcd_device_state * this_device, hcd_datarequest * request)
USB_ASSERT((hcd_reg1)(UE_GET_ADDR(request->endpoint)) <= HCD_LAST_EP, USB_ASSERT((hcd_reg1)(UE_GET_ADDR(request->endpoint)) <= HCD_LAST_EP,
"Invalid EP number"); "Invalid EP number");
USB_ASSERT((hcd_reg1)(this_device->address) <= HCD_LAST_ADDR, USB_ASSERT(this_device->address <= HCD_LAST_ADDR,
"Invalid device address"); "Invalid device address");
/* Initially... */ /* Initially... */
@ -819,7 +775,7 @@ hcd_data_transfer(hcd_device_state * this_device, hcd_datarequest * request)
/* Set parameters for further communication */ /* Set parameters for further communication */
d->setup_device(d->private_data, d->setup_device(d->private_data,
(hcd_reg1)request->endpoint, (hcd_reg1)request->endpoint,
(hcd_reg1)this_device->address); this_device->address);
/* TODO: broken USB_IN... constants */ /* TODO: broken USB_IN... constants */
if (1 == request->direction) { if (1 == request->direction) {
@ -830,7 +786,7 @@ hcd_data_transfer(hcd_device_state * this_device, hcd_datarequest * request)
/* Wait for response */ /* Wait for response */
hcd_device_wait(this_device, HCD_EVENT_ENDPOINT, hcd_device_wait(this_device, HCD_EVENT_ENDPOINT,
request->endpoint); (hcd_reg1)request->endpoint);
/* Check response */ /* Check response */
if (EXIT_SUCCESS != d->check_error(d->private_data, if (EXIT_SUCCESS != d->check_error(d->private_data,
@ -876,7 +832,7 @@ hcd_data_transfer(hcd_device_state * this_device, hcd_datarequest * request)
/* Wait for response */ /* Wait for response */
hcd_device_wait(this_device, HCD_EVENT_ENDPOINT, hcd_device_wait(this_device, HCD_EVENT_ENDPOINT,
request->endpoint); (hcd_reg1)request->endpoint);
/* Check response */ /* Check response */
if (EXIT_SUCCESS != d->check_error(d->private_data, if (EXIT_SUCCESS != d->check_error(d->private_data,

View File

@ -240,7 +240,7 @@ hcd_disconnect_device(hcd_device_state * this_device)
* hcd_device_wait * * hcd_device_wait *
*===========================================================================*/ *===========================================================================*/
void void
hcd_device_wait(hcd_device_state * this_device, hcd_event event, int ep) hcd_device_wait(hcd_device_state * this_device, hcd_event event, hcd_reg1 ep)
{ {
hcd_driver_state * drv; hcd_driver_state * drv;
@ -401,7 +401,7 @@ hcd_tree_cleanup(hcd_configuration * c)
* hcd_tree_find_ep * * hcd_tree_find_ep *
*===========================================================================*/ *===========================================================================*/
hcd_endpoint * hcd_endpoint *
hcd_tree_find_ep(hcd_configuration * c, int ep) hcd_tree_find_ep(hcd_configuration * c, hcd_reg1 ep)
{ {
hcd_interface * i; hcd_interface * i;
hcd_endpoint * e; hcd_endpoint * e;

View File

@ -21,6 +21,11 @@ struct ddekit_usb_device_id;
struct ddekit_usb_urb; struct ddekit_usb_urb;
struct ddekit_usb_dev; struct ddekit_usb_dev;
/* Translates DDEKit UBR to one used by HCD */
static void hcd_decode_urb(hcd_urb *, struct ddekit_usb_urb *);
static void hcd_encode_urb(hcd_urb *, struct ddekit_usb_urb *);
/*===========================================================================* /*===========================================================================*
* Global definitions * * Global definitions *
*===========================================================================*/ *===========================================================================*/
@ -147,7 +152,7 @@ ddekit_usb_dev_get_data(struct ddekit_usb_dev * dev)
} }
/* TODO: This was in header file but is not used anywhere */ /* TODO: This was in 'ddekit/usb.h' header file, but is not used anywhere */
#if 0 #if 0
/*===========================================================================* /*===========================================================================*
* ddekit_usb_get_device_id * * ddekit_usb_get_device_id *
@ -171,20 +176,25 @@ ddekit_usb_get_device_id(struct ddekit_usb_dev * dev,
int int
ddekit_usb_submit_urb(struct ddekit_usb_urb * d_urb) ddekit_usb_submit_urb(struct ddekit_usb_urb * d_urb)
{ {
hcd_urb * urb;
hcd_device_state * dev; hcd_device_state * dev;
hcd_driver_state * drv; hcd_driver_state * drv;
DEBUG_DUMP; DEBUG_DUMP;
urb = (hcd_urb *)d_urb; /* Retrieve info on device/driver state from DDEKit's USB */
dev = (hcd_device_state *)(urb->dev); dev = (hcd_device_state *)(d_urb->dev);
drv = (hcd_driver_state *)(dev->driver); drv = (hcd_driver_state *)(dev->driver);
dev->urb = urb; /* Remember original URB */
drv->current_event = HCD_EVENT_URB; dev->urb.original_urb = (void *)d_urb;
/* TODO: URB's must be queued somewhere */ /* TODO: URB's should be queued somewhere if DDEKit is not changed */
/* Turn DDEKit URB format to one that is easier to handle by HCD, also
* check if URB is valid */
hcd_decode_urb(&(dev->urb), d_urb);
/* Start handling URB event */
drv->current_event = HCD_EVENT_URB;
hcd_handle_event(drv); hcd_handle_event(drv);
return EXIT_SUCCESS; return EXIT_SUCCESS;
@ -228,13 +238,14 @@ ddekit_usb_init(struct ddekit_usb_driver * drv,
/*===========================================================================* /*===========================================================================*
* hcd_connect_cb * * hcd_connect_cb *
*===========================================================================*/ *===========================================================================*/
void hcd_connect_cb(hcd_device_state * dev) void
hcd_connect_cb(hcd_device_state * dev)
{ {
unsigned int if_bitmask; unsigned int if_bitmask;
DEBUG_DUMP; DEBUG_DUMP;
/* TODO: magic numbers like in ddekit/devman */ /* TODO: Magic numbers like in ddekit/devman */
/* Each bit starting from 0, represents valid interface */ /* Each bit starting from 0, represents valid interface */
if_bitmask = 0xFFFFFFFF >> (32 - dev->config_tree.num_interfaces); if_bitmask = 0xFFFFFFFF >> (32 - dev->config_tree.num_interfaces);
@ -249,7 +260,8 @@ void hcd_connect_cb(hcd_device_state * dev)
/*===========================================================================* /*===========================================================================*
* hcd_disconnect_cb * * hcd_disconnect_cb *
*===========================================================================*/ *===========================================================================*/
void hcd_disconnect_cb(hcd_device_state * dev) void
hcd_disconnect_cb(hcd_device_state * dev)
{ {
DEBUG_DUMP; DEBUG_DUMP;
@ -260,9 +272,121 @@ void hcd_disconnect_cb(hcd_device_state * dev)
/*===========================================================================* /*===========================================================================*
* hcd_completion_cb * * hcd_completion_cb *
*===========================================================================*/ *===========================================================================*/
void hcd_completion_cb(void * priv) void
hcd_completion_cb(hcd_urb * urb)
{
struct ddekit_usb_urb * d_urb;
DEBUG_DUMP;
/* Recollect original URB */
d_urb = (struct ddekit_usb_urb *)urb->original_urb;
/* Turn HCD URB format to one handled by DDEKit */
hcd_encode_urb(urb, d_urb);
completion_cb(d_urb->priv);
}
/*===========================================================================*
* hcd_decode_urb *
*===========================================================================*/
static void
hcd_decode_urb(hcd_urb * urb, struct ddekit_usb_urb * dde_urb)
{ {
DEBUG_DUMP; DEBUG_DUMP;
completion_cb(priv); /* No UBR error initially */
urb->inout_status = EXIT_SUCCESS;
/* Check transfer direction */
switch (dde_urb->direction) {
case DDEKIT_USB_IN:
urb->direction = HCD_DIRECTION_IN;
break;
case DDEKIT_USB_OUT:
urb->direction = HCD_DIRECTION_OUT;
break;
default:
USB_MSG("URB direction error");
goto URB_ERROR;
}
/* Check transfer type */
switch (dde_urb->type) {
case DDEKIT_USB_TRANSFER_ISO:
urb->type = HCD_TRANSFER_ISOCHRONOUS;
break;
case DDEKIT_USB_TRANSFER_INT:
urb->type = HCD_TRANSFER_INTERRUPT;
break;
case DDEKIT_USB_TRANSFER_CTL:
urb->type = HCD_TRANSFER_CONTROL;
break;
case DDEKIT_USB_TRANSFER_BLK:
urb->type = HCD_TRANSFER_BULK;
break;
default:
USB_MSG("URB type error");
goto URB_ERROR;
}
/* Check transfer endpoint validity */
if ((dde_urb->endpoint <= (int)HCD_LAST_EP) &&
(dde_urb->endpoint >= (int)HCD_DEFAULT_EP))
urb->endpoint = (hcd_reg1)dde_urb->endpoint;
else {
USB_MSG("URB endpoint error");
goto URB_ERROR;
}
/* Check transfer interval validity */
if ((dde_urb->interval <= (int)HCD_HIGHEST_INTERVAL) &&
(dde_urb->interval >= (int)HCD_LOWEST_INTERVAL))
urb->interval = (hcd_reg1)dde_urb->interval;
else {
USB_MSG("URB interval error");
goto URB_ERROR;
}
/* TODO: Alignment of setup packet. Can DDE client guarantee that? */
/* Transfer data assignment */
urb->inout_data = (void *)dde_urb->data;
urb->in_setup = (hcd_ctrlrequest *)dde_urb->setup_packet;
/* TODO: Sane size check? */
urb->in_size = (hcd_reg4)dde_urb->size;
/* Buffer validity check */
if ((NULL == urb->inout_data) && (NULL == urb->in_setup)) {
USB_MSG("URB buffer error");
goto URB_ERROR;
}
/* Remember device and check for NULL */
if (NULL == (urb->target_device = (hcd_device_state *)dde_urb->dev)) {
USB_MSG("URB device pointer error");
goto URB_ERROR;
}
/* Decoding completed */
return;
URB_ERROR:
urb->inout_status = EXIT_FAILURE;
}
/*===========================================================================*
* hcd_encode_urb *
*===========================================================================*/
static void
hcd_encode_urb(hcd_urb * urb, struct ddekit_usb_urb * dde_urb)
{
DEBUG_DUMP;
/* Rewrite output for DDEKit part */
dde_urb->actual_length = urb->out_size;
dde_urb->status = urb->inout_status;
} }

View File

@ -271,7 +271,7 @@ static void musb_am335x_internal_deinit(void);
static void musb_am335x_irq_init(void *); static void musb_am335x_irq_init(void *);
static void musb_am335x_usbss_isr(void *); static void musb_am335x_usbss_isr(void *);
static void musb_am335x_usbx_isr(void *); static void musb_am335x_usbx_isr(void *);
static int musb_am335x_irqstat0_to_ep(int); static hcd_reg1 musb_am335x_irqstat0_to_ep(int);
/* Configuration helpers */ /* Configuration helpers */
static void musb_am335x_usb_reset(int); static void musb_am335x_usb_reset(int);
@ -427,7 +427,7 @@ musb_am335x_internal_init(void)
return EXIT_FAILURE; return EXIT_FAILURE;
/* Read and dump revision register */ /* Read and dump revision register */
USB_MSG("MUSB revision (REVREG): %08X", USB_MSG("MUSB revision (REVREG): 0x%08X",
(unsigned int)HCD_RD4(am335x.ss.regs, AM335X_REG_REVREG)); (unsigned int)HCD_RD4(am335x.ss.regs, AM335X_REG_REVREG));
/* Allow OS to handle previously configured USBSS interrupts */ /* Allow OS to handle previously configured USBSS interrupts */
@ -628,7 +628,7 @@ musb_am335x_usbx_isr(void * data)
/*===========================================================================* /*===========================================================================*
* musb_am335x_irqstat0_to_ep * * musb_am335x_irqstat0_to_ep *
*===========================================================================*/ *===========================================================================*/
static int static hcd_reg1
musb_am335x_irqstat0_to_ep(int irqstat0) musb_am335x_irqstat0_to_ep(int irqstat0)
{ {
hcd_reg1 ep; hcd_reg1 ep;
@ -653,7 +653,7 @@ musb_am335x_irqstat0_to_ep(int irqstat0)
"Invalid IRQSTAT0 supplied (2)"); "Invalid IRQSTAT0 supplied (2)");
} }
return (int)ep; return ep;
} }
@ -714,14 +714,6 @@ musb_am335x_otg_enable(int usb_num)
HCD_WR4(r, AM335X_REG_USBXIRQENABLESET1, intreg); HCD_WR4(r, AM335X_REG_USBXIRQENABLESET1, intreg);
/* Some MUSB implementations may not need this */
#if 0
/* Set EP0 interrupt to be enabled */
intreg = HCD_RD4(r, AM335X_REG_USBXIRQENABLESET0);
HCD_SET(intreg, AM335X_VAL_USBXIRQENABLEXXX0_EP0);
HCD_WR4(r, AM335X_REG_USBXIRQENABLESET0, intreg);
#else
/* Set all EP interrupts as enabled */ /* Set all EP interrupts as enabled */
intreg = AM335X_VAL_USBXIRQENABLEXXX0_EP0 | intreg = AM335X_VAL_USBXIRQENABLEXXX0_EP0 |
AM335X_VAL_USBXIRQENABLEXXX0_TX_EP1 | AM335X_VAL_USBXIRQENABLEXXX0_TX_EP1 |
@ -756,5 +748,4 @@ musb_am335x_otg_enable(int usb_num)
AM335X_VAL_USBXIRQENABLEXXX0_RX_EP15 ; AM335X_VAL_USBXIRQENABLEXXX0_RX_EP15 ;
HCD_WR4(r, AM335X_REG_USBXIRQENABLESET0, intreg); HCD_WR4(r, AM335X_REG_USBXIRQENABLESET0, intreg);
#endif
} }

View File

@ -10,6 +10,7 @@
#include <ddekit/semaphore.h> #include <ddekit/semaphore.h>
#include <ddekit/usb.h> #include <ddekit/usb.h>
/* TODO: usb.h is for DDEKit's IPC and should not be used here */
#include <minix/usb.h> /* for setup structures */ #include <minix/usb.h> /* for setup structures */
#include <minix/usb_ch9.h> /* for descriptor structures */ #include <minix/usb_ch9.h> /* for descriptor structures */
@ -99,60 +100,7 @@ hcd_configuration;
/*===========================================================================* /*===========================================================================*
* HCD device helper types * * HCD enumerations *
*===========================================================================*/
typedef void (*hcd_thread_function)(void *);
typedef ddekit_thread_t hcd_thread;
typedef ddekit_sem_t hcd_lock;
typedef struct hcd_driver_state hcd_driver_state;
typedef struct ddekit_usb_urb hcd_urb;
typedef enum {
HCD_STATE_DISCONNECTED = 0, /* default for initialization */
HCD_STATE_CONNECTION_PENDING,
HCD_STATE_CONNECTED
}
hcd_state;
typedef enum {
HCD_SPEED_LOW,
HCD_SPEED_FULL,
HCD_SPEED_HIGH,
}
hcd_speed;
/* Largest value that can be transfered by this driver at a time
* see MAXPAYLOAD in TXMAXP/RXMAXP */
#define MAX_WTOTALLENGTH 1024
typedef struct hcd_device_state {
hcd_driver_state * driver; /* Specific HCD driver object */
hcd_thread * thread;
hcd_lock * lock;
hcd_urb * urb;
void * data;
hcd_device_descriptor device_desc;
hcd_configuration config_tree;
hcd_reg1 max_packet_size;
hcd_speed speed;
hcd_state state;
int address;
/* Number of bytes received/transmitted in last transfer */
int data_len;
/* Word aligned buffer for each device to hold transfered data */
hcd_reg1 buffer[MAX_WTOTALLENGTH] __aligned(sizeof(hcd_reg4));
}
hcd_device_state;
/*===========================================================================*
* HCD event handling *
*===========================================================================*/ *===========================================================================*/
/* Possible USB transfer types */ /* Possible USB transfer types */
typedef enum { typedef enum {
@ -183,14 +131,44 @@ typedef enum {
} }
hcd_event; hcd_event;
/* EP event constants */ /* Possible device states */
#define HCD_NO_ENDPOINT -1 typedef enum {
#define HCD_ENDPOINT_0 0
HCD_STATE_DISCONNECTED = 0, /* default for initialization */
HCD_STATE_CONNECTION_PENDING,
HCD_STATE_CONNECTED
}
hcd_state;
/* USB speeds */
typedef enum {
HCD_SPEED_LOW,
HCD_SPEED_FULL,
HCD_SPEED_HIGH,
}
hcd_speed;
/*===========================================================================* /*===========================================================================*
* HCD transfer requests * * HCD threading/device/URB types *
*===========================================================================*/ *===========================================================================*/
typedef void (*hcd_thread_function)(void *);
typedef ddekit_thread_t hcd_thread;
typedef ddekit_sem_t hcd_lock;
typedef struct hcd_driver_state hcd_driver_state;
typedef struct usb_ctrlrequest hcd_ctrlrequest;
/* Largest value that can be transfered by this driver at a time
* see MAXPAYLOAD in TXMAXP/RXMAXP */
#define MAX_WTOTALLENGTH 1024
/* Forward declarations */
typedef struct hcd_datarequest hcd_datarequest;
typedef struct hcd_urb hcd_urb;
typedef struct hcd_device_state hcd_device_state;
/* Non-control transfer request structure */
struct hcd_datarequest { struct hcd_datarequest {
char * data; char * data;
@ -203,8 +181,49 @@ struct hcd_datarequest {
hcd_transfer type; hcd_transfer type;
}; };
typedef struct usb_ctrlrequest hcd_ctrlrequest; /* HCD's URB structure */
typedef struct hcd_datarequest hcd_datarequest; struct hcd_urb {
/* Basic */
void * original_urb;
hcd_device_state * target_device;
/* Transfer (in/out signifies what may be overwritten by HCD) */
hcd_ctrlrequest * in_setup;
void * inout_data;
hcd_reg4 in_size;
int out_size;
int inout_status; /* URB submission/validity status */
/* Transfer control */
hcd_transfer type;
hcd_direction direction;
hcd_reg1 endpoint;
hcd_reg1 interval;
};
/* Current state of attached device */
struct hcd_device_state {
hcd_driver_state * driver; /* Specific HCD driver object */
hcd_thread * thread;
hcd_lock * lock;
void * data;
hcd_urb urb;
hcd_device_descriptor device_desc;
hcd_configuration config_tree;
hcd_reg1 max_packet_size;
hcd_speed speed;
hcd_state state;
hcd_reg1 address;
/* Number of bytes received/transmitted in last transfer */
int data_len;
/* Word aligned buffer for each device to hold transfered data */
hcd_reg1 buffer[MAX_WTOTALLENGTH] __aligned(sizeof(hcd_reg4));
};
/*===========================================================================* /*===========================================================================*
@ -224,9 +243,14 @@ typedef struct hcd_datarequest hcd_datarequest;
#define HCD_LAST_ADDR 0x7Fu #define HCD_LAST_ADDR 0x7Fu
#define HCD_LAST_EP 0x0Fu #define HCD_LAST_EP 0x0Fu
#define HCD_TOTAL_EP 0x10u #define HCD_TOTAL_EP 0x10u
#define HCD_ANY_EP 0xFFu
/* Legal interval values */
#define HCD_LOWEST_INTERVAL 0x00u
#define HCD_HIGHEST_INTERVAL 0xFFu
/* TODO: One device only */ /* TODO: One device only */
#define HCD_ATTACHED_ADDR 0x01 #define HCD_ATTACHED_ADDR 0x01u
/* Translates configuration number for 'set configuration' */ /* Translates configuration number for 'set configuration' */
#define HCD_SET_CONFIG_NUM(num) ((num)+0x01u) #define HCD_SET_CONFIG_NUM(num) ((num)+0x01u)
@ -278,7 +302,7 @@ int hcd_connect_device(hcd_device_state *, hcd_thread_function);
void hcd_disconnect_device(hcd_device_state *); void hcd_disconnect_device(hcd_device_state *);
/* Locks device thread until 'hcd_device_continue' */ /* Locks device thread until 'hcd_device_continue' */
void hcd_device_wait(hcd_device_state *, hcd_event, int); void hcd_device_wait(hcd_device_state *, hcd_event, hcd_reg1);
/* Unlocks device thread halted by 'hcd_device_wait' */ /* Unlocks device thread halted by 'hcd_device_wait' */
void hcd_device_continue(hcd_device_state *); void hcd_device_continue(hcd_device_state *);
@ -294,7 +318,7 @@ int hcd_buffer_to_tree(hcd_reg1 *, int, hcd_configuration *);
void hcd_tree_cleanup(hcd_configuration *); void hcd_tree_cleanup(hcd_configuration *);
/* Find EP in a tree */ /* Find EP in a tree */
hcd_endpoint * hcd_tree_find_ep(hcd_configuration *, int); hcd_endpoint * hcd_tree_find_ep(hcd_configuration *, hcd_reg1);
#endif /* !_HCD_COMMON_H_ */ #endif /* !_HCD_COMMON_H_ */

View File

@ -12,7 +12,7 @@
*===========================================================================*/ *===========================================================================*/
void hcd_connect_cb(hcd_device_state *); void hcd_connect_cb(hcd_device_state *);
void hcd_disconnect_cb(hcd_device_state *); void hcd_disconnect_cb(hcd_device_state *);
void hcd_completion_cb(void *); void hcd_completion_cb(hcd_urb *);
#endif /* !_HCD_DDEKIT_H_ */ #endif /* !_HCD_DDEKIT_H_ */

View File

@ -40,9 +40,9 @@ struct hcd_driver_state {
/* Current state to be handled by driver */ /* Current state to be handled by driver */
hcd_event current_event; hcd_event current_event;
int current_endpoint; hcd_reg1 current_endpoint;
hcd_event expected_event; hcd_event expected_event;
int expected_endpoint; hcd_reg1 expected_endpoint;
}; };