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
DPADD+= ${LIBDDEKIT} ${LIBDDEKIT_USB_SERVER} ${LIBDEVMAN} ${LIBUSB} ${LIBMINC} ${LIBCLKCONF}
LDADD+= -lddekit -lddekit_usb_server -ldevman -lusb -lminc -lclkconf
LDADD+= -lsys -lminlib
DPADD+= ${LIBDDEKIT} ${LIBDDEKIT_USB_SERVER} ${LIBDEVMAN} ${LIBUSB} ${LIBMINC} ${LIBCLKCONF} ${LIBSYS} ${LIBMINLIB}
LDADD+= -lddekit -lddekit_usb_server -ldevman -lusb -lminc -lclkconf -lsys -lminlib
MAN=

View file

@ -5,7 +5,6 @@
#include <string.h> /* memcpy */
#include <minix/drivers.h> /* errno with sign */
#include <minix/usb.h> /* USB_TRANSFER_CTL... */
#include <usb/hcd_common.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 */
static int hcd_enumerate(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_set_configuration(hcd_device_state *, hcd_reg1);
static int hcd_handle_urb(hcd_device_state *);
static int hcd_control_urb(hcd_device_state *);
static int hcd_non_control_urb(hcd_device_state *, int);
static int hcd_handle_urb(hcd_device_state *, hcd_urb *);
static int hcd_control_urb(hcd_device_state *, hcd_urb *);
static int hcd_non_control_urb(hcd_device_state *, hcd_urb *);
/* For internal use by more general methods */
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 */
for(;;) {
/* No URB's yet */
this_device->urb = NULL;
/* 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");
}
@ -175,7 +172,7 @@ hcd_device_finish(hcd_device_state * this_device, const char * finish_msg)
/* Lock forever */
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");
}
}
@ -308,13 +305,15 @@ hcd_get_device_descriptor(hcd_device_state * this_device)
* hcd_set_address *
*===========================================================================*/
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;
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 */
setup.bRequestType = 0x00; /* OUT */
@ -348,9 +347,9 @@ hcd_get_descriptor_tree(hcd_device_state * this_device)
{
hcd_config_descriptor config_descriptor;
hcd_ctrlrequest setup;
hcd_reg4 total_length;
hcd_reg4 buffer_length;
int completed;
int total_length;
int buffer_length;
DEBUG_DUMP;
@ -384,19 +383,16 @@ hcd_get_descriptor_tree(hcd_device_state * this_device)
sizeof(config_descriptor));
/* Continue only if there is more data */
total_length = config_descriptor.wTotalLength[0] +
(config_descriptor.wTotalLength[1] << 8);
total_length = UGETW(config_descriptor.wTotalLength);
if (total_length < (int)sizeof(config_descriptor)) {
if (total_length < sizeof(config_descriptor)) {
/* This should never happen for a fine device */
USB_MSG("Illegal wTotalLength value");
return EXIT_FAILURE;
}
else if (sizeof(config_descriptor) == total_length) {
} else if (sizeof(config_descriptor) == total_length) {
/* Nothing more was in descriptor anyway */
completed = 1;
}
else {
} else {
/* Read whatever is needed */
buffer_length = total_length;
}
@ -453,48 +449,44 @@ hcd_set_configuration(hcd_device_state * this_device, hcd_reg1 configuration)
* hcd_handle_urb *
*===========================================================================*/
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;
DEBUG_DUMP;
transfer_status = EXIT_FAILURE;
urb = this_device->urb;
USB_ASSERT(NULL != urb, "NULL URB given");
/* TODO: One device only */
USB_ASSERT((void *)this_device == (void *)urb->dev,
"Unknown device for URB");
USB_ASSERT(NULL != urb, "NULL URB given");
USB_ASSERT(this_device == urb->target_device, "Unknown device for URB");
switch (urb->type) {
case USB_TRANSFER_CTL:
transfer_status = hcd_control_urb(this_device);
case HCD_TRANSFER_CONTROL:
transfer_status = hcd_control_urb(this_device, urb);
break;
case USB_TRANSFER_BLK:
case USB_TRANSFER_INT:
transfer_status = hcd_non_control_urb(this_device,
urb->type);
case HCD_TRANSFER_BULK:
case HCD_TRANSFER_INTERRUPT:
transfer_status = hcd_non_control_urb(this_device, urb);
break;
case USB_TRANSFER_ISO:
case HCD_TRANSFER_ISOCHRONOUS:
/* TODO: ISO transfer */
USB_MSG("ISO transfer not supported");
break;
default:
USB_MSG("Invalid transfer type 0x%X", urb->type);
USB_MSG("Invalid transfer type 0x%02X", (int)urb->type);
break;
}
/* In case of error, only dump message */
if (EXIT_SUCCESS != transfer_status)
USB_MSG("USB transfer failed");
/* Call completion regardless of status */
hcd_completion_cb(urb->priv);
hcd_completion_cb(urb);
/* TODO: Only critical failures should ever yield EXIT_FAILURE, so
* 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 *
*===========================================================================*/
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;
urb = this_device->urb;
/* Assume bad values unless something different occurs later */
urb->status = EINVAL;
urb->inout_status = EINVAL;
/* Must have setup packet */
if (NULL == urb->setup_packet) {
/* Must have setup packet for control transfer */
if (NULL == urb->in_setup) {
USB_MSG("No setup packet in URB, for control transfer");
return EXIT_FAILURE;
}
/* 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");
return EXIT_FAILURE;
}
/* Hold setup packet and analyze it */
memcpy(&setup, urb->setup_packet, sizeof(setup));
/* TODO: broken constants for urb->direction (USB_OUT...) */
if (((setup.bRequestType >> 7) & 0x01) != urb->direction) {
/* Setup and URB directions should match */
if (((urb->in_setup->bRequestType >> 7) & 0x01) != urb->direction) {
USB_MSG("URB Direction mismatch");
return EXIT_FAILURE;
}
/* Send setup packet */
if (EXIT_SUCCESS != hcd_setup_packet(this_device, &setup,
(hcd_reg1)urb->endpoint)) {
if (EXIT_SUCCESS != hcd_setup_packet(this_device, urb->in_setup,
urb->endpoint)) {
USB_MSG("Sending URB setup packet, failed");
urb->status = EPIPE;
urb->inout_status = EPIPE;
return EXIT_FAILURE;
}
/* TODO: Calling memcpy may be removed when writing directly to URB */
/* Put what was read back into URB */
memcpy(urb->data, this_device->buffer, this_device->data_len);
urb->actual_length = (unsigned int)this_device->data_len;
urb->status = EXIT_SUCCESS;
memcpy(urb->inout_data, this_device->buffer, this_device->data_len);
urb->out_size = this_device->data_len;
urb->inout_status = EXIT_SUCCESS;
return EXIT_SUCCESS;
}
@ -562,80 +546,55 @@ hcd_control_urb(hcd_device_state * this_device)
* hcd_non_control_urb *
*===========================================================================*/
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_datarequest request;
hcd_urb * urb;
DEBUG_DUMP;
urb = this_device->urb;
/* 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");
return EXIT_FAILURE;
}
if ((UE_GET_ADDR(urb->endpoint) >= HCD_TOTAL_EP) ||
(UE_GET_ADDR(urb->endpoint) <= HCD_DEFAULT_EP)) {
USB_MSG("Illegal EP number");
if (HCD_DEFAULT_EP == urb->endpoint) {
USB_MSG("Non-control transfer for EP0");
return EXIT_FAILURE;
}
/* TODO: broken USB_IN... constants */
if ((1 != urb->direction) && (0 != urb->direction)) {
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);
/* Check if EP number is valid within remembered descriptor tree */
e = hcd_tree_find_ep(&(this_device->config_tree), urb->endpoint);
if (NULL == e) {
USB_MSG("Invalid EP value");
USB_MSG("Invalid EP number for this device");
return EXIT_FAILURE;
}
/* TODO: broken constants for urb->direction (USB_OUT...) */
/* Check if remembered direction matches */
/* Check if remembered descriptor direction, matches the one in URB */
if (((e->descriptor.bEndpointAddress >> 7) & 0x01) != urb->direction) {
USB_MSG("EP direction mismatch");
return EXIT_FAILURE;
}
/* 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");
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 */
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 */
if (EXIT_SUCCESS != hcd_data_transfer(this_device, &request)) {
USB_MSG("URB non-control transfer, failed");
urb->status = EPIPE;
urb->inout_status = EPIPE;
return EXIT_FAILURE;
}
/* Transfer successfully completed */
urb->actual_length = urb->size - request.data_left;
urb->status = EXIT_SUCCESS;
urb->out_size = urb->in_size - request.data_left;
urb->inout_status = EXIT_SUCCESS;
return EXIT_SUCCESS;
}
@ -671,10 +630,10 @@ hcd_setup_packet(hcd_device_state * this_device, hcd_ctrlrequest * setup,
DEBUG_DUMP;
/* Should have been set at enumeration or with default values */
USB_ASSERT(this_device->max_packet_size > 0,
"Illegal MaxPacketSize for EP0");
USB_ASSERT((ep <= HCD_LAST_EP), "Invalid EP number");
USB_ASSERT((hcd_reg1)(this_device->address) <= HCD_LAST_ADDR,
USB_ASSERT(this_device->max_packet_size >= HCD_LS_MAXPACKETSIZE,
"Illegal MaxPacketSize");
USB_ASSERT(ep <= HCD_LAST_EP, "Invalid EP number");
USB_ASSERT(this_device->address <= HCD_LAST_ADDR,
"Invalid device address");
/* Initially... */
@ -683,13 +642,13 @@ hcd_setup_packet(hcd_device_state * this_device, hcd_ctrlrequest * setup,
this_device->data_len = 0; /* Nothing read yet */
/* 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 */
d->setup_stage(d->private_data, setup);
/* 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 */
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 */
hcd_device_wait(this_device,
HCD_EVENT_ENDPOINT,
HCD_ENDPOINT_0);
HCD_EVENT_ENDPOINT, ep);
/* Check response */
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 */
rx_len = d->read_data(d->private_data,
current_byte, HCD_DEFAULT_EP);
current_byte, ep);
/* Increment */
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);
/* 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 */
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);
/* 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 */
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;
/* 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;
}
@ -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,
"Invalid EP number");
USB_ASSERT((hcd_reg1)(this_device->address) <= HCD_LAST_ADDR,
USB_ASSERT(this_device->address <= HCD_LAST_ADDR,
"Invalid device address");
/* Initially... */
@ -819,7 +775,7 @@ hcd_data_transfer(hcd_device_state * this_device, hcd_datarequest * request)
/* Set parameters for further communication */
d->setup_device(d->private_data,
(hcd_reg1)request->endpoint,
(hcd_reg1)this_device->address);
this_device->address);
/* TODO: broken USB_IN... constants */
if (1 == request->direction) {
@ -830,7 +786,7 @@ hcd_data_transfer(hcd_device_state * this_device, hcd_datarequest * request)
/* Wait for response */
hcd_device_wait(this_device, HCD_EVENT_ENDPOINT,
request->endpoint);
(hcd_reg1)request->endpoint);
/* Check response */
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 */
hcd_device_wait(this_device, HCD_EVENT_ENDPOINT,
request->endpoint);
(hcd_reg1)request->endpoint);
/* Check response */
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 *
*===========================================================================*/
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;
@ -401,7 +401,7 @@ hcd_tree_cleanup(hcd_configuration * c)
* hcd_tree_find_ep *
*===========================================================================*/
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_endpoint * e;

View file

@ -21,6 +21,11 @@ struct ddekit_usb_device_id;
struct ddekit_usb_urb;
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 *
*===========================================================================*/
@ -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
/*===========================================================================*
* ddekit_usb_get_device_id *
@ -171,20 +176,25 @@ ddekit_usb_get_device_id(struct ddekit_usb_dev * dev,
int
ddekit_usb_submit_urb(struct ddekit_usb_urb * d_urb)
{
hcd_urb * urb;
hcd_device_state * dev;
hcd_driver_state * drv;
DEBUG_DUMP;
urb = (hcd_urb *)d_urb;
dev = (hcd_device_state *)(urb->dev);
/* Retrieve info on device/driver state from DDEKit's USB */
dev = (hcd_device_state *)(d_urb->dev);
drv = (hcd_driver_state *)(dev->driver);
dev->urb = urb;
drv->current_event = HCD_EVENT_URB;
/* Remember original 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);
return EXIT_SUCCESS;
@ -228,13 +238,14 @@ ddekit_usb_init(struct ddekit_usb_driver * drv,
/*===========================================================================*
* hcd_connect_cb *
*===========================================================================*/
void hcd_connect_cb(hcd_device_state * dev)
void
hcd_connect_cb(hcd_device_state * dev)
{
unsigned int if_bitmask;
DEBUG_DUMP;
/* TODO: magic numbers like in ddekit/devman */
/* TODO: Magic numbers like in ddekit/devman */
/* Each bit starting from 0, represents valid interface */
if_bitmask = 0xFFFFFFFF >> (32 - dev->config_tree.num_interfaces);
@ -249,7 +260,8 @@ void hcd_connect_cb(hcd_device_state * dev)
/*===========================================================================*
* hcd_disconnect_cb *
*===========================================================================*/
void hcd_disconnect_cb(hcd_device_state * dev)
void
hcd_disconnect_cb(hcd_device_state * dev)
{
DEBUG_DUMP;
@ -260,9 +272,121 @@ void hcd_disconnect_cb(hcd_device_state * dev)
/*===========================================================================*
* 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;
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_usbss_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 */
static void musb_am335x_usb_reset(int);
@ -427,7 +427,7 @@ musb_am335x_internal_init(void)
return EXIT_FAILURE;
/* 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));
/* Allow OS to handle previously configured USBSS interrupts */
@ -628,7 +628,7 @@ musb_am335x_usbx_isr(void * data)
/*===========================================================================*
* musb_am335x_irqstat0_to_ep *
*===========================================================================*/
static int
static hcd_reg1
musb_am335x_irqstat0_to_ep(int irqstat0)
{
hcd_reg1 ep;
@ -653,7 +653,7 @@ musb_am335x_irqstat0_to_ep(int irqstat0)
"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);
/* 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 */
intreg = AM335X_VAL_USBXIRQENABLEXXX0_EP0 |
AM335X_VAL_USBXIRQENABLEXXX0_TX_EP1 |
@ -756,5 +748,4 @@ musb_am335x_otg_enable(int usb_num)
AM335X_VAL_USBXIRQENABLEXXX0_RX_EP15 ;
HCD_WR4(r, AM335X_REG_USBXIRQENABLESET0, intreg);
#endif
}

View file

@ -10,6 +10,7 @@
#include <ddekit/semaphore.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_ch9.h> /* for descriptor structures */
@ -99,60 +100,7 @@ hcd_configuration;
/*===========================================================================*
* HCD device helper 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 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 *
* HCD enumerations *
*===========================================================================*/
/* Possible USB transfer types */
typedef enum {
@ -183,14 +131,44 @@ typedef enum {
}
hcd_event;
/* EP event constants */
#define HCD_NO_ENDPOINT -1
#define HCD_ENDPOINT_0 0
/* Possible device states */
typedef enum {
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 {
char * data;
@ -203,8 +181,49 @@ struct hcd_datarequest {
hcd_transfer type;
};
typedef struct usb_ctrlrequest hcd_ctrlrequest;
typedef struct hcd_datarequest hcd_datarequest;
/* HCD's URB structure */
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));
};
/*===========================================================================*
@ -218,22 +237,27 @@ typedef struct hcd_datarequest hcd_datarequest;
#define HCD_NANOSLEEP_USEC(usec) ((usec) * HCD_MILI)
/* Default USB communication parameters */
#define HCD_DEFAULT_EP 0x00u
#define HCD_DEFAULT_ADDR 0x00u
#define HCD_DEFAULT_CONFIG 0x00u
#define HCD_LAST_ADDR 0x7Fu
#define HCD_LAST_EP 0x0Fu
#define HCD_TOTAL_EP 0x10u
#define HCD_DEFAULT_EP 0x00u
#define HCD_DEFAULT_ADDR 0x00u
#define HCD_DEFAULT_CONFIG 0x00u
#define HCD_LAST_ADDR 0x7Fu
#define HCD_LAST_EP 0x0Fu
#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 */
#define HCD_ATTACHED_ADDR 0x01
#define HCD_ATTACHED_ADDR 0x01u
/* Translates configuration number for 'set configuration' */
#define HCD_SET_CONFIG_NUM(num) ((num)+0x01u)
#define HCD_SET_CONFIG_NUM(num) ((num)+0x01u)
/* Default MaxPacketSize for control transfer */
#define HCD_LS_MAXPACKETSIZE 8u
#define HCD_HS_MAXPACKETSIZE 64u
#define HCD_LS_MAXPACKETSIZE 8u
#define HCD_HS_MAXPACKETSIZE 64u
/*===========================================================================*
@ -278,7 +302,7 @@ int hcd_connect_device(hcd_device_state *, hcd_thread_function);
void hcd_disconnect_device(hcd_device_state *);
/* 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' */
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 *);
/* 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_ */

View file

@ -12,7 +12,7 @@
*===========================================================================*/
void hcd_connect_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_ */

View file

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