#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>
/* 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);
/* 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");
}
/* 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");
}
}
* 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 */
{
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;
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;
}
* 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
* 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;
}
* 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");
- return EXIT_FAILURE;
- }
-
- /* TODO: broken USB_IN... constants */
- if ((1 != urb->direction) && (0 != urb->direction)) {
- USB_MSG("Illegal EP direction");
+ if (HCD_DEFAULT_EP == urb->endpoint) {
+ USB_MSG("Non-control transfer for EP0");
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);
/* 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;
}
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... */
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,
/* 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(
/* 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;
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,
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,
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;
}
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... */
/* 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) {
/* 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,
/* 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,
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 *
*===========================================================================*/
}
-/* 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 *
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 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);
- /* TODO: URB's must be queued somewhere */
+ /* Start handling URB event */
+ drv->current_event = HCD_EVENT_URB;
hcd_handle_event(drv);
return EXIT_SUCCESS;
/*===========================================================================*
* 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);
/*===========================================================================*
* hcd_disconnect_cb *
*===========================================================================*/
-void hcd_disconnect_cb(hcd_device_state * dev)
+void
+hcd_disconnect_cb(hcd_device_state * dev)
{
DEBUG_DUMP;
/*===========================================================================*
* 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;
+
+ /* 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;
- completion_cb(priv);
+ /* Rewrite output for DDEKit part */
+ dde_urb->actual_length = urb->out_size;
+ dde_urb->status = urb->inout_status;
}
#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 */
/*===========================================================================*
- * 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 {
}
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;
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));
+};
/*===========================================================================*
#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
/*===========================================================================*
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 *);
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_ */