]> Zhao Yanbai Git Server - minix.git/commitdiff
usb:Adding usb enumeration.
authorKees Jongenburger <kees.jongenburger@gmail.com>
Mon, 26 May 2014 14:47:56 +0000 (16:47 +0200)
committerLionel Sambuc <lionel@minix3.org>
Mon, 28 Jul 2014 15:05:40 +0000 (17:05 +0200)
usbd update from JPEmbedded

Change-Id: I4098b29a3188abe7110d59f0746ea40ac5818bbf

http://gerrit.minix3.org/#/c/2698/

drivers/usbd/base/usbd.c
drivers/usbd/hcd/hcd.c
drivers/usbd/hcd/hcd_common.c
drivers/usbd/hcd/hcd_ddekit.c
drivers/usbd/hcd/musb/musb_am335x.c
drivers/usbd/hcd/musb/musb_core.c
drivers/usbd/hcd/musb/musb_core.h
drivers/usbd/hcd/musb/musb_regs.h
drivers/usbd/include/usb/hcd_common.h
drivers/usbd/include/usb/hcd_interface.h

index 7a78293d12d6038f6b4cac9bbd6ec699b108c142..288f7f942d221367c5f318260c3a46ea7eb3db15 100755 (executable)
@@ -5,6 +5,8 @@
 #include <ddekit/ddekit.h>             /* ddekit_init */
 #include <ddekit/thread.h>             /* DDEKit threading */
 
+#include <libdde/usb_server.h>         /* DDEKit USB server */
+
 #include <minix/devman.h>              /* Initializing 'devman' */
 #include <minix/sef.h>                 /* SEF handling */
 
@@ -22,7 +24,6 @@ static void usbd_server_thread(void *);
 
 /* TODO: No headers for these... */
 extern void ddekit_minix_wait_exit(void); /* dde.c */
-extern void ddekit_usb_server_init(void); /* usb_server.c */
 
 
 /*===========================================================================*
@@ -34,6 +35,7 @@ main(int UNUSED(argc), char * UNUSED(argv[]))
        int ret_val;
 
        USB_MSG("Starting USBD");
+       USB_DBG("Built: %s %s", __DATE__, __TIME__);
 
        /* Basic SEF,DDE,... initialization */
        usbd_init();
index e2ba4098926890798940f63f586c74ed2939c34e..bbb39dec9e7bb390807d26f8f63a6524ddbd4908 100755 (executable)
@@ -2,9 +2,11 @@
  * Implementation of generic HCD
  */
 
-#include <time.h>                              /* nanosleep */
 #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>
 #include <usb/hcd_interface.h>
@@ -27,15 +29,21 @@ static int hcd_set_address(hcd_device_state *, int);
 static int hcd_get_descriptor_tree(hcd_device_state *);
 static int hcd_set_configuration(hcd_device_state *, int);
 static int hcd_handle_urb(hcd_device_state *);
+static int hcd_control_urb(hcd_device_state *);
+static int hcd_bulk_urb(hcd_device_state *);
 
 /* For internal use by more general methods */
 static int hcd_setup_packet(hcd_device_state *, hcd_ctrlrequest *);
+static int hcd_bulk_transfer(hcd_device_state *, hcd_bulkrequest *, int);
 
 
 /*===========================================================================*
  *    Local definitions                                                      *
  *===========================================================================*/
-/* TODO: Only one device at a time */
+/* TODO: Only one device at a time
+ * If ever HUB functionality is added, one must remember that disconnecting
+ * HUB, means disconnecting every device attached to it, so data structure may
+ * have to be altered to allow that */
 static hcd_device_state hcd_device[1];
 
 
@@ -55,13 +63,13 @@ hcd_handle_event(hcd_driver_state * driver)
        /* Sometimes interrupts occur in a weird order (EP after disconnect)
         * This helps finding ordering errors in DEBUG */
        USB_DBG("Event: 0x%02X, state: 0x%02X",
-               driver->event, this_device->state);
+               driver->current_event, this_device->state);
 
        /* Set what was received for device thread to use */
        this_device->driver = driver;
 
        /* Handle event and forward control to device thread when required */
-       switch (driver->event) {
+       switch (driver->current_event) {
                case HCD_EVENT_CONNECTED:
                        if (HCD_STATE_DISCONNECTED == this_device->state) {
                                if (EXIT_SUCCESS != hcd_connect_device(
@@ -89,6 +97,7 @@ hcd_handle_event(hcd_driver_state * driver)
                        break;
 
                case HCD_EVENT_ENDPOINT:
+               case HCD_EVENT_URB:
                        /* Allow device thread to continue with it's logic */
                        if (HCD_STATE_DISCONNECTED != this_device->state)
                                hcd_device_continue(this_device);
@@ -133,13 +142,13 @@ hcd_device_thread(void * thread_args)
 
        USB_DBG("Waiting for URBs");
 
-       /* No URB's yet */
-       this_device->urb = NULL;
-
        /* 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_device_wait(this_device, HCD_EVENT_URB, HCD_NO_ENDPOINT);
 
                if (EXIT_SUCCESS != hcd_handle_urb(this_device))
                        hcd_device_finish(this_device, "URB handling failed");
@@ -162,7 +171,7 @@ hcd_device_finish(hcd_device_state * this_device, const char * finish_msg)
 
        /* Lock forever */
        for (;;) {
-               hcd_device_wait(this_device);
+               hcd_device_wait(this_device, HCD_EVENT_URB, HCD_NO_ENDPOINT);
                USB_MSG("Failed attempt to continue finished thread");
        }
 }
@@ -181,10 +190,11 @@ hcd_enumerate(hcd_device_state * this_device)
        d = this_device->driver;
 
        /* First let driver reset device */
-       d->reset_device(d->private_data);
-
-       /* Set parameters for further communication */
-       d->setup_device(d->private_data, HCD_DEFAULT_EP, HCD_DEFAULT_ADDR);
+       if (EXIT_SUCCESS != d->reset_device(d->private_data,
+                                       &(this_device->speed))) {
+               USB_MSG("Failed to reset device");
+               return EXIT_FAILURE;
+       }
 
        /* Get device descriptor */
        if (EXIT_SUCCESS != hcd_get_device_descriptor(this_device)) {
@@ -201,7 +211,7 @@ hcd_enumerate(hcd_device_state * this_device)
        }
 
        /* Set parameters for further communication */
-       d->setup_device(d->private_data, HCD_DEFAULT_EP, HCD_ATTACHED_ADDR);
+       d->setup_device(d->private_data, HCD_DEFAULT_EP, this_device->address);
 
        /* Get other descriptors */
        if (EXIT_SUCCESS != hcd_get_descriptor_tree(this_device)) {
@@ -254,11 +264,29 @@ hcd_get_device_descriptor(hcd_device_state * this_device)
        /* Remember max packet size from device descriptor */
        this_device->max_packet_size = this_device->device_desc.bMaxPacketSize;
 
-       /* Output VID/PID when debugging */
-       USB_DBG("idVendor: %02X%02X", this_device->device_desc.idVendor[1],
-                                       this_device->device_desc.idVendor[0]);
-       USB_DBG("idProduct: %02X%02X", this_device->device_desc.idProduct[1],
-                                       this_device->device_desc.idProduct[0]);
+       /* Dump device descriptor in debug mode */
+#ifdef DEBUG
+       {
+               hcd_device_descriptor * d;
+               d = &(this_device->device_desc);
+
+               USB_DBG("<<DEVICE>>");
+               USB_DBG("bLength %02X",                 d->bLength);
+               USB_DBG("bDescriptorType %02X",         d->bDescriptorType);
+               USB_DBG("bcdUSB %04X",                  UGETW(d->bcdUSB));
+               USB_DBG("bDeviceClass %02X",            d->bDeviceClass);
+               USB_DBG("bDeviceSubClass %02X",         d->bDeviceSubClass);
+               USB_DBG("bDeviceProtocol %02X",         d->bDeviceProtocol);
+               USB_DBG("bMaxPacketSize %02X",          d->bMaxPacketSize);
+               USB_DBG("idVendor %04X",                UGETW(d->idVendor));
+               USB_DBG("idProduct %04X",               UGETW(d->idProduct));
+               USB_DBG("bcdDevice %04X",               UGETW(d->bcdDevice));
+               USB_DBG("iManufacturer %02X",           d->iManufacturer);
+               USB_DBG("iProduct %02X",                d->iProduct);
+               USB_DBG("iSerialNumber %02X",           d->iSerialNumber);
+               USB_DBG("bNumConfigurations %02X",      d->bNumConfigurations);
+       }
+#endif
 
        return EXIT_SUCCESS;
 }
@@ -289,11 +317,11 @@ hcd_set_address(hcd_device_state * this_device, int address)
                return EXIT_FAILURE;
        }
 
-       {
-               /* Sleep 5ms for proper addressing */
-               struct timespec nanotm = {0, HCD_NANOSLEEP_MSEC(5)};
-               nanosleep(&nanotm, NULL);
-       }
+       /* Sleep 5msec to allow addressing */
+       hcd_os_nanosleep(HCD_NANOSLEEP_MSEC(5));
+
+       /* Remember what was assigned in hardware */
+       this_device->address = address;
 
        return EXIT_SUCCESS;
 }
@@ -412,15 +440,180 @@ hcd_set_configuration(hcd_device_state * this_device, int configuration)
 static int
 hcd_handle_urb(hcd_device_state * this_device)
 {
+       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");
+
+       switch (urb->type) {
+
+               case USB_TRANSFER_CTL:
+                       transfer_status = hcd_control_urb(this_device);
+                       break;
+
+               case USB_TRANSFER_BLK:
+                       transfer_status = hcd_bulk_urb(this_device);
+                       break;
+
+               case USB_TRANSFER_INT:
+                       /* TODO: transfer */
+                       USB_MSG("Interrupt transfer not supported");
+                       break;
+
+               case USB_TRANSFER_ISO:
+                       /* TODO: transfer */
+                       USB_MSG("ISO transfer not supported");
+                       break;
+
+               default:
+                       USB_MSG("Invalid transfer type 0x%X", urb->type);
+                       break;
+       }
+
+#ifndef URB_TEST
+       /* Call completion */
+       hcd_completion_cb(urb->priv);
+#endif
+
+       /* Only critical failures should ever yield EXIT_FAILURE */
+       return EXIT_SUCCESS;
+}
+
+
+/*===========================================================================*
+ *    hcd_control_urb                                                        *
+ *===========================================================================*/
+static int
+hcd_control_urb(hcd_device_state * this_device)
+{
+       hcd_urb * urb;
+       hcd_ctrlrequest setup;
+
        DEBUG_DUMP;
 
-       USB_ASSERT(NULL != this_device->urb, "NULL URB received");
+       urb = this_device->urb;
 
-       /* TODO: URB handling will be here */
+       /* Assume bad values unless something different occurs later */
+       urb->status = EINVAL;
 
-       /* TODO: call completion */
-       /* hcd_completion_cb */
+       /* Must have setup packet */
+       if (NULL == urb->setup_packet) {
+               USB_MSG("No setup packet in URB, for control transfer");
+               return EXIT_FAILURE;
+       }
+
+       /* TODO: Only EP0 can have control transfer */
+       if (0 != 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) {
+               USB_MSG("URB Direction mismatch");
+               return EXIT_FAILURE;
+       }
 
+       /* Send setup packet */
+       if (EXIT_SUCCESS != hcd_setup_packet(this_device, &setup)) {
+               USB_MSG("Sending URB setup packet, failed");
+               urb->status = EPIPE;
+               return EXIT_FAILURE;
+       }
+
+       urb->status = EXIT_SUCCESS;
+       return EXIT_SUCCESS;
+}
+
+
+/*===========================================================================*
+ *    hcd_bulk_urb                                                           *
+ *===========================================================================*/
+static int
+hcd_bulk_urb(hcd_device_state * this_device)
+{
+       hcd_endpoint * e;
+       hcd_bulkrequest request;
+       hcd_urb * urb;
+
+       DEBUG_DUMP;
+
+       urb = this_device->urb;
+
+       /* Assume bad values unless something different occurs later */
+       urb->status = EINVAL;
+
+       if (NULL == urb->data) {
+               USB_MSG("No data packet in URB, for bulk transfer");
+               return EXIT_FAILURE;
+       }
+
+       if ((UE_GET_ADDR(urb->endpoint) >= 16) ||
+               (UE_GET_ADDR(urb->endpoint) <= 0)) {
+               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");
+               return EXIT_FAILURE;
+       }
+
+       /* TODO: Any additional checks? (sane size?) */
+
+       /* Assign to bulk request structure */
+       request.endpoint = urb->endpoint;
+       request.size = (int)urb->size;
+       request.data = urb->data;
+
+       /* Check if EP number is valid */
+       e = hcd_tree_find_ep(&(this_device->config_tree), request.endpoint);
+
+       if (NULL == e) {
+               USB_MSG("Invalid EP value");
+               return EXIT_FAILURE;
+       }
+
+       /* TODO: broken constants for urb->direction (USB_OUT...) */
+       /* Check if remembered direction matches */
+       if (((e->descriptor.bEndpointAddress >> 7) & 0x01) != urb->direction) {
+               USB_MSG("EP direction mismatch");
+               return EXIT_FAILURE;
+       }
+
+       /* Check if remembered type matches */
+       if (e->descriptor.bmAttributes != UE_BULK) {
+               USB_MSG("EP type mismatch");
+               return EXIT_FAILURE;
+       }
+
+       /* Assign to let know how much data can be transfered at a time */
+       request.max_packet_size = UGETW(e->descriptor.wMaxPacketSize);
+
+       /* Let know how to configure EP for speed */
+       request.speed = this_device->speed;
+
+       /* Send bulk data */
+       if (EXIT_SUCCESS != hcd_bulk_transfer(this_device, &request,
+                                               urb->direction)) {
+               USB_MSG("URB bulk transfer, failed");
+               urb->status = EPIPE;
+               return EXIT_FAILURE;
+       }
+
+       urb->status = EXIT_SUCCESS;
        return EXIT_SUCCESS;
 }
 
@@ -447,10 +640,12 @@ hcd_setup_packet(hcd_device_state * this_device, hcd_ctrlrequest * setup)
        d->setup_stage(d->private_data, setup);
 
        /* Wait for response */
-       hcd_device_wait(this_device);
+       hcd_device_wait(this_device, HCD_EVENT_ENDPOINT, HCD_ENDPOINT_0);
 
        /* Check response */
-       if (EXIT_SUCCESS != d->check_error(d->private_data))
+       if (EXIT_SUCCESS != d->check_error(d->private_data,
+                                       HCD_TRANSFER_CONTROL,
+                                       HCD_DIRECTION_UNUSED))
                return EXIT_FAILURE;
 
        /* For data packets... */
@@ -468,11 +663,15 @@ hcd_setup_packet(hcd_device_state * this_device, hcd_ctrlrequest * setup)
                                d->in_data_stage(d->private_data);
 
                                /* Wait for response */
-                               hcd_device_wait(this_device);
+                               hcd_device_wait(this_device,
+                                               HCD_EVENT_ENDPOINT,
+                                               HCD_ENDPOINT_0);
 
                                /* Check response */
                                if (EXIT_SUCCESS != d->check_error(
-                                                       d->private_data))
+                                                       d->private_data,
+                                                       HCD_TRANSFER_CONTROL,
+                                                       HCD_DIRECTION_UNUSED))
                                        return EXIT_FAILURE;
 
                                /* Read data received as response */
@@ -510,10 +709,13 @@ 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_device_wait(this_device, HCD_EVENT_ENDPOINT,
+                               HCD_ENDPOINT_0);
 
                /* Check response */
-               if (EXIT_SUCCESS != d->check_error(d->private_data))
+               if (EXIT_SUCCESS != d->check_error(d->private_data,
+                                               HCD_TRANSFER_CONTROL,
+                                               HCD_DIRECTION_UNUSED))
                        return EXIT_FAILURE;
 
        } else {
@@ -522,10 +724,13 @@ 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_device_wait(this_device, HCD_EVENT_ENDPOINT,
+                               HCD_ENDPOINT_0);
 
                /* Check response */
-               if (EXIT_SUCCESS != d->check_error(d->private_data))
+               if (EXIT_SUCCESS != d->check_error(d->private_data,
+                                               HCD_TRANSFER_CONTROL,
+                                               HCD_DIRECTION_UNUSED))
                        return EXIT_FAILURE;
 
                /* Read zero data from response to clear registers */
@@ -535,3 +740,103 @@ hcd_setup_packet(hcd_device_state * this_device, hcd_ctrlrequest * setup)
 
        return EXIT_SUCCESS;
 }
+
+
+/*===========================================================================*
+ *    hcd_bulk_transfer                                                      *
+ *===========================================================================*/
+static int
+hcd_bulk_transfer(hcd_device_state * this_device, hcd_bulkrequest * request,
+               int direction)
+{
+       hcd_driver_state * d;
+       hcd_bulkrequest temp_req;
+       int transfer_len;
+
+       DEBUG_DUMP;
+
+       /* Initially... */
+       d = this_device->driver;
+
+       /* Set parameters for further communication */
+       d->setup_device(d->private_data,
+                       request->endpoint,
+                       this_device->address);
+
+       /* TODO: broken USB_IN... constants */
+       if (1 == direction) {
+
+               do {
+                       /* Start actual bulk transfer */
+                       d->bulk_in_stage(d->private_data, request);
+
+                       /* Wait for response */
+                       hcd_device_wait(this_device, HCD_EVENT_ENDPOINT,
+                                       request->endpoint);
+
+                       /* Check response */
+                       if (EXIT_SUCCESS != d->check_error(d->private_data,
+                                                       HCD_TRANSFER_BULK,
+                                                       HCD_DIRECTION_IN))
+                               return EXIT_FAILURE;
+
+                       /* Read data received as response */
+                       transfer_len = d->read_data(d->private_data,
+                                               (hcd_reg1 *)request->data,
+                                               request->endpoint);
+
+                       request->size -= transfer_len;
+                       request->data += transfer_len;
+
+                       /* Total length shall not become negative */
+                       USB_ASSERT(request->size >= 0,
+                               "Invalid amount of data received");
+
+                       /* TODO: REMOVEME (dumping of bulk transfer) */
+                       {
+                               int i;
+                               USB_MSG("RECEIVED: %d", transfer_len);
+                               for (i = 0; i < transfer_len; i++)
+                                       USB_MSG("%c",
+                                       (request->data-transfer_len)[i]);
+                       }
+
+               } while (0 != request->size);
+
+       } else if (0 == direction) {
+
+               do {
+                       temp_req = *request;
+
+                       /* Decide transfer size */
+                       if (temp_req.size > (int)temp_req.max_packet_size) {
+                               temp_req.size = temp_req.max_packet_size;
+                       }
+
+                       request->data += temp_req.size;
+                       request->size -= temp_req.size;
+
+                       /* Total length shall not become negative */
+                       USB_ASSERT(request->size >= 0,
+                               "Invalid amount of data received");
+
+                       /* Start actual bulk transfer */
+                       d->bulk_out_stage(d->private_data, &temp_req);
+
+                       /* Wait for response */
+                       hcd_device_wait(this_device, HCD_EVENT_ENDPOINT,
+                                       request->endpoint);
+
+                       /* Check response */
+                       if (EXIT_SUCCESS != d->check_error(d->private_data,
+                                                       HCD_TRANSFER_BULK,
+                                                       HCD_DIRECTION_OUT))
+                               return EXIT_FAILURE;
+
+               } while (0 != request->size);
+
+       } else
+               USB_ASSERT(0, "Invalid transfer direction");
+
+       return EXIT_SUCCESS;
+}
index d93088d64e880ee20eda0e30de4ba9655d58855f..23f981f17557066a61ee75f88305d595595e5e12 100755 (executable)
@@ -4,6 +4,7 @@
  */
 
 #include <string.h>                    /* memset... */
+#include <time.h>                      /* nanosleep */
 
 #include <sys/mman.h>                  /* Physical to virtual memory mapping */
 
@@ -13,6 +14,7 @@
 #include <minix/syslib.h>              /* sys_privctl */
 
 #include <usb/hcd_common.h>
+#include <usb/hcd_interface.h>
 #include <usb/usb_common.h>
 
 
@@ -159,6 +161,31 @@ hcd_os_clkconf_release(void)
 }
 
 
+/*===========================================================================*
+ *    hcd_os_nanosleep                                                       *
+ *===========================================================================*/
+void
+hcd_os_nanosleep(int nanosec)
+{
+       struct timespec nanotm;
+
+       DEBUG_DUMP;
+
+       if (nanosec >= HCD_NANO) {
+               nanotm.tv_sec = nanosec / HCD_NANO;
+               nanotm.tv_nsec = nanosec % HCD_NANO;
+       } else {
+               nanotm.tv_sec = 0;
+               nanotm.tv_nsec = nanosec;
+       }
+
+       /* TODO: since it is not likely to be ever interrupted, we do not try
+        * to sleep for a remaining time in case of signal handling */
+       USB_ASSERT(EXIT_SUCCESS == nanosleep(&nanotm, NULL),
+               "Calling nanosleep() failed");
+}
+
+
 /*===========================================================================*
  *    hcd_init_device                                                        *
  *===========================================================================*/
@@ -211,10 +238,19 @@ hcd_disconnect_device(hcd_device_state * this_device)
  *    hcd_device_wait                                                        *
  *===========================================================================*/
 void
-hcd_device_wait(hcd_device_state * this_device)
+hcd_device_wait(hcd_device_state * this_device, hcd_event event, int ep)
 {
+       hcd_driver_state * drv;
+
        DEBUG_DUMP;
 
+       drv = (hcd_driver_state *)this_device->driver;
+
+       drv->expected_event = event;
+       drv->expected_endpoint = ep;
+
+       USB_DBG("Waiting for: ev=0x%X, ep=0x%X", (int)event, ep);
+
        ddekit_sem_down(this_device->lock);
 }
 
@@ -225,8 +261,22 @@ hcd_device_wait(hcd_device_state * this_device)
 void
 hcd_device_continue(hcd_device_state * this_device)
 {
+       hcd_driver_state * drv;
+
        DEBUG_DUMP;
 
+       drv = (hcd_driver_state *)this_device->driver;
+
+       /* We need to get what was expected... */
+       USB_ASSERT(drv->current_event == drv->expected_event,
+               "Unexpected event occurred");
+
+       /* ...including endpoint interrupts */
+       if (HCD_EVENT_ENDPOINT == drv->current_event) {
+               USB_ASSERT(drv->current_endpoint == drv->expected_endpoint,
+                       "Unexpected endpoint interrupt");
+       }
+
        ddekit_sem_up(this_device->lock);
 }
 
@@ -260,6 +310,11 @@ hcd_buffer_to_tree(hcd_reg1 * buf, int len, hcd_configuration * c)
                /* Check descriptor type */
                desc = (hcd_descriptor *)buf;
 
+               if (0 == desc->bLength) {
+                       USB_MSG("Zero length descriptor");
+                       goto PARSE_ERROR;
+               }
+
                if (UDESC_CONFIG == desc->bDescriptorType) {
                        if (EXIT_SUCCESS != hcd_fill_configuration(buf, len,
                                                                c, cfg_num++))
@@ -341,6 +396,36 @@ hcd_tree_cleanup(hcd_configuration * c)
 }
 
 
+/*===========================================================================*
+ *    hcd_tree_find_ep                                                       *
+ *===========================================================================*/
+hcd_endpoint *
+hcd_tree_find_ep(hcd_configuration * c, int ep)
+{
+       hcd_interface * i;
+       hcd_endpoint * e;
+       int if_idx;
+       int ep_idx;
+
+       DEBUG_DUMP;
+
+       /* Free if anything was allocated */
+       USB_ASSERT(NULL != c->interface, "No interfaces available");
+       USB_ASSERT(c->num_interfaces > 0, "Interface number error");
+
+       for (if_idx = 0; if_idx < c->num_interfaces; if_idx++) {
+               i = &(c->interface[if_idx]);
+               for (ep_idx = 0; ep_idx < i->num_endpoints; ep_idx++) {
+                       e = &(i->endpoint[ep_idx]);
+                       if (UE_GET_ADDR(e->descriptor.bEndpointAddress) == ep)
+                               return e;
+               }
+       }
+
+       return NULL;
+}
+
+
 /*===========================================================================*
  *    hcd_fill_configuration                                                 *
  *===========================================================================*/
@@ -385,8 +470,7 @@ hcd_fill_configuration(hcd_reg1 * buf, int len, hcd_configuration * c, int num)
        USB_DBG("<<CONFIGURATION>>");
        USB_DBG("bLength %02X",                 desc->bLength);
        USB_DBG("bDescriptorType %02X",         desc->bDescriptorType);
-       USB_DBG("wTotalLength %02X%02X",        desc->wTotalLength[1],
-                                               desc->wTotalLength[0]);
+       USB_DBG("wTotalLength %04X",            UGETW(desc->wTotalLength));
        USB_DBG("bNumInterface %02X",           desc->bNumInterface);
        USB_DBG("bConfigurationValue %02X",     desc->bConfigurationValue);
        USB_DBG("iConfiguration %02X",          desc->iConfiguration);
@@ -482,8 +566,7 @@ hcd_fill_endpoint(hcd_reg1 * buf, int len, hcd_endpoint * e, int num)
        USB_DBG("bDescriptorType %02X",         desc->bDescriptorType);
        USB_DBG("bEndpointAddress %02X",        desc->bEndpointAddress);
        USB_DBG("bmAttributes %02X",            desc->bmAttributes);
-       USB_DBG("wMaxPacketSize %02X%02X",      desc->wMaxPacketSize[1],
-                                               desc->wMaxPacketSize[0]);
+       USB_DBG("wMaxPacketSize %04X",          UGETW(desc->wMaxPacketSize));
        USB_DBG("bInterval %02X",               desc->bInterval);
 
        return EXIT_SUCCESS;
index 950865526c36eeb74bcaf438bb1e111ec9bcc32c..5f650d06f428a73d5bb4977f70abbd1506250a60 100755 (executable)
@@ -7,6 +7,7 @@
 #include <ddekit/usb.h>
 
 #include <usb/hcd_ddekit.h>
+#include <usb/hcd_interface.h>
 #include <usb/usb_common.h>
 
 
@@ -40,7 +41,7 @@ _ddekit_usb_get_manufacturer(struct ddekit_usb_dev * ddev)
 {
        static const char mfg[] = "UNKNOWN";
        DEBUG_DUMP;
-       /* TODO: UNUSED won't work */
+       /* TODO: UNUSED for argument won't work */
        ((void)ddev);
        return (char *)mfg;
 }
@@ -54,7 +55,7 @@ _ddekit_usb_get_product(struct ddekit_usb_dev * ddev)
 {
        static const char prod[] = "UNKNOWN";
        DEBUG_DUMP;
-       /* TODO: UNUSED won't work */
+       /* TODO: UNUSED for argument won't work */
        ((void)ddev);
        return (char *)prod;
 }
@@ -68,7 +69,7 @@ _ddekit_usb_get_serial(struct ddekit_usb_dev * ddev)
 {
        static const char serial[] = "UNKNOWN";
        DEBUG_DUMP;
-       /* TODO: UNUSED won't work */
+       /* TODO: UNUSED for argument won't work */
        ((void)ddev);
        return (char *)serial;
 }
@@ -156,7 +157,7 @@ ddekit_usb_get_device_id(struct ddekit_usb_dev * dev,
                        struct ddekit_usb_device_id * id)
 {
        DEBUG_DUMP;
-       /* TODO: UNUSED won't work */
+       /* TODO: UNUSED for argument won't work */
        ((void)dev);
        ((void)id);
        return;
@@ -172,17 +173,19 @@ 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);
+       drv = (hcd_driver_state *)(dev->driver);
 
-       /* TODO: queue URB's */
-       /* Reassign and go to thread */
        dev->urb = urb;
-       hcd_device_continue(dev);
-       dev->urb = NULL;
+       drv->current_event = HCD_EVENT_URB;
+
+       /* TODO: URB's must be queued somewhere */
+       hcd_handle_event(drv);
 
        return EXIT_SUCCESS;
 }
@@ -195,7 +198,7 @@ int
 ddekit_usb_cancle_urb(struct ddekit_usb_urb * d_urb)
 {
        DEBUG_DUMP;
-       /* TODO: UNUSED won't work */
+       /* TODO: UNUSED for argument won't work */
        ((void)d_urb);
        return EXIT_SUCCESS;
 }
index 7ea016d6d771e69db8d964530ee7b2cea9414bed..f818e5f25b736f1c3d46dc63fdac3fadfbaa1673 100755 (executable)
@@ -3,7 +3,6 @@
  */
 
 #include <string.h>                                    /* memset */
-#include <time.h>                                      /* nanosleep */
 
 #include <usb/hcd_common.h>
 #include <usb/hcd_platforms.h>
 /*===========================================================================*
  *    AM335x base register defines                                           *
  *===========================================================================*/
-/* Where MUSB core space starts */
-#define AM335X_MUSB_CORE0_BASE_ADDR            0x47401400u
-#define AM335X_MUSB_CORE1_BASE_ADDR            0x47401C00u
-#define AM335X_MUSB_CORE_BASE_LEN              0x400u
+/* Memory placement defines */
+#define AM335X_USBSS_BASE_ADDR                 0x47400000u
+#define AM335X_USB0_BASE_OFFSET                        0x1000u
+#define AM335X_MUSB_CORE0_BASE_OFFSET          0x1400u
+#define AM335X_USB1_BASE_OFFSET                        0x1800u
+#define AM335X_MUSB_CORE1_BASE_OFFSET          0x1C00u
+#define AM335X_USBSS_TOTAL_REG_LEN             0x5000u
 
 
 /*===========================================================================*
  *    AM335x USB specific register defines                                   *
  *===========================================================================*/
 /* SS registers base address */
-#define AM335X_USBSS_BASE_ADDR                 0x47400000u
 
 #define AM335X_REG_REVREG                      0x000u
 #define AM335X_REG_SYSCONFIG                   0x010u
 #define AM335X_REG_IRQFRAMEENABLE0             0x240u
 #define AM335X_REG_IRQFRAMEENABLE1             0x244u
 
-/* Length in bytes of SS registers */
-#define AM335X_USBSS_BASE_LEN                  AM335X_REG_IRQFRAMEENABLE1 + 4u
-
-/* USBx registers base addresses */
-#define AM335X_USB0_BASE_ADDR                  0x47401000u
-#define AM335X_USB1_BASE_ADDR                  0x47401800u
-
 #define AM335X_REG_USBXREV                     0x00u
 #define AM335X_REG_USBXCTRL                    0x14u
 #define AM335X_REG_USBXSTAT                    0x18u
 #define AM335X_VAL_USBXIRQENABLEXXX1_DRVVBUS           HCD_BIT(8)
 #define AM335X_VAL_USBXIRQENABLEXXX1_GENERIC           HCD_BIT(9)
 
+#define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_1         HCD_BIT(17)
+#define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_2         HCD_BIT(18)
+#define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_3         HCD_BIT(19)
+#define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_4         HCD_BIT(20)
+#define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_5         HCD_BIT(21)
+#define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_6         HCD_BIT(22)
+#define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_7         HCD_BIT(23)
+#define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_8         HCD_BIT(24)
+#define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_9         HCD_BIT(25)
+#define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_10                HCD_BIT(26)
+#define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_11                HCD_BIT(27)
+#define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_12                HCD_BIT(28)
+#define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_13                HCD_BIT(29)
+#define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_14                HCD_BIT(30)
+#define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_15                HCD_BIT(31)
+
 #define AM335X_VAL_USBXIRQSTAT1_SUSPEND                HCD_BIT(0)
 #define AM335X_VAL_USBXIRQSTAT1_RESUME         HCD_BIT(1)
 #define AM335X_VAL_USBXIRQSTAT1_RESET_BABBLE   HCD_BIT(2)
 #define AM335X_VAL_USBXIRQSTAT1_DRVVBUS                HCD_BIT(8)
 #define AM335X_VAL_USBXIRQSTAT1_GENERIC                HCD_BIT(9)
 
-/* Length in bytes of USBx registers */
-#define AM335X_USBX_BASE_LEN                   AM335X_REG_USBXMODE + 4u
-
 /* Helpers for interrupt clearing */
 #define CLEAR_IRQ0(irq0_bit)   HCD_WR4(r, AM335X_REG_USBXIRQSTAT0, (irq0_bit))
 #define CLEAR_IRQ1(irq1_bit)   HCD_WR4(r, AM335X_REG_USBXIRQSTAT1, (irq1_bit))
@@ -263,6 +270,7 @@ static void musb_am335x_internal_deinit(void);
 static void musb_am335x_irq_init(void *); /* TODO: required by DDEKit */
 static void musb_am335x_usbss_isr(void *);
 static void musb_am335x_usbx_isr(void *);
+static int musb_am335x_irqstat0_to_ep(int);
 
 /* Configuration helpers */
 static void musb_am335x_usb_reset(int);
@@ -289,7 +297,7 @@ musb_am335x_init(void)
 
        /* Map memory for USBSS */
        am335x.ss.regs = hcd_os_regs_init(AM335X_USBSS_BASE_ADDR,
-                                       AM335X_USBSS_BASE_LEN);
+                                       AM335X_USBSS_TOTAL_REG_LEN);
 
        if (NULL == am335x.ss.regs)
                return EXIT_FAILURE;
@@ -312,18 +320,12 @@ musb_am335x_init(void)
                ctrl->priv.usb_num = AM335X_USB0;
 
                /* MUSB core addresses for later registering */
-               ctrl->core.regs = hcd_os_regs_init(AM335X_MUSB_CORE0_BASE_ADDR,
-                                               AM335X_MUSB_CORE_BASE_LEN);
-
-               if (NULL == ctrl->core.regs)
-                       return EXIT_FAILURE;
+               ctrl->core.regs = (void*)((hcd_addr)am335x.ss.regs +
+                                       AM335X_MUSB_CORE0_BASE_OFFSET);
 
                /* Map AM335X USB0 specific addresses */
-               ctrl->usb.regs = hcd_os_regs_init(AM335X_USB0_BASE_ADDR,
-                                               AM335X_USBX_BASE_LEN);
-
-               if (NULL == ctrl->usb.regs)
-                       return EXIT_FAILURE;
+               ctrl->usb.regs = (void*)((hcd_addr)am335x.ss.regs +
+                                       AM335X_USB0_BASE_OFFSET);
 
                /* Attach IRQ to number */
                if (EXIT_SUCCESS != hcd_os_interrupt_attach(AM335X_USB0_IRQ,
@@ -337,6 +339,8 @@ musb_am335x_init(void)
                ctrl->driver.setup_device = musb_setup_device;
                ctrl->driver.reset_device = musb_reset_device;
                ctrl->driver.setup_stage = musb_setup_stage;
+               ctrl->driver.bulk_in_stage = musb_bulk_in_stage;
+               ctrl->driver.bulk_out_stage = musb_bulk_out_stage;
                ctrl->driver.in_data_stage = musb_in_data_stage;
                ctrl->driver.out_data_stage = musb_out_data_stage;
                ctrl->driver.in_status_stage = musb_in_status_stage;
@@ -356,18 +360,12 @@ musb_am335x_init(void)
                ctrl->priv.usb_num = AM335X_USB1;
 
                /* MUSB core addresses for later registering */
-               ctrl->core.regs = hcd_os_regs_init(AM335X_MUSB_CORE1_BASE_ADDR,
-                                               AM335X_MUSB_CORE_BASE_LEN);
+               ctrl->core.regs = (void*)((hcd_addr)am335x.ss.regs +
+                                       AM335X_MUSB_CORE1_BASE_OFFSET);
 
-               if (NULL == ctrl->core.regs)
-                       return EXIT_FAILURE;
-
-               /* Map AM335X USB1 specific addresses */
-               ctrl->usb.regs = hcd_os_regs_init(AM335X_USB1_BASE_ADDR,
-                                               AM335X_USBX_BASE_LEN);
-
-               if (NULL == ctrl->usb.regs)
-                       return EXIT_FAILURE;
+               /* Map AM335X USB0 specific addresses */
+               ctrl->usb.regs = (void*)((hcd_addr)am335x.ss.regs +
+                                       AM335X_USB1_BASE_OFFSET);
 
                /* Attach IRQ to number */
                if (EXIT_SUCCESS != hcd_os_interrupt_attach(AM335X_USB1_IRQ,
@@ -381,6 +379,8 @@ musb_am335x_init(void)
                ctrl->driver.setup_device = musb_setup_device;
                ctrl->driver.reset_device = musb_reset_device;
                ctrl->driver.setup_stage = musb_setup_stage;
+               ctrl->driver.bulk_in_stage = musb_bulk_in_stage;
+               ctrl->driver.bulk_out_stage = musb_bulk_out_stage;
                ctrl->driver.in_data_stage = musb_in_data_stage;
                ctrl->driver.out_data_stage = musb_out_data_stage;
                ctrl->driver.in_status_stage = musb_in_status_stage;
@@ -404,32 +404,9 @@ musb_am335x_deinit(void)
        musb_am335x_internal_deinit();
 
        /* Release maps if anything was assigned */
-#ifdef AM335X_USE_USB0
-       if (NULL != am335x.ctrl[AM335X_USB0].usb.regs)
-               if (EXIT_SUCCESS != hcd_os_regs_deinit(AM335X_USB0_BASE_ADDR,
-                                                       AM335X_USBX_BASE_LEN))
-                       USB_MSG("Failed to release USB0 OTG mapping");
-
-       if (NULL != am335x.ctrl[AM335X_USB0].core.regs)
-               if (EXIT_SUCCESS != hcd_os_regs_deinit(
-                                               AM335X_MUSB_CORE0_BASE_ADDR,
-                                               AM335X_MUSB_CORE_BASE_LEN))
-                       USB_MSG("Failed to release USB0 core mapping");
-#endif
-       if (NULL != am335x.ctrl[AM335X_USB1].usb.regs)
-               if (EXIT_SUCCESS != hcd_os_regs_deinit(AM335X_USB1_BASE_ADDR,
-                                                       AM335X_USBX_BASE_LEN))
-                       USB_MSG("Failed to release USB1 OTG mapping");
-
-       if (NULL != am335x.ctrl[AM335X_USB1].core.regs)
-               if (EXIT_SUCCESS != hcd_os_regs_deinit(
-                                               AM335X_MUSB_CORE1_BASE_ADDR,
-                                               AM335X_MUSB_CORE_BASE_LEN))
-                       USB_MSG("Failed to release USB1 core mapping");
-
        if (NULL != am335x.ss.regs)
                if (EXIT_SUCCESS != hcd_os_regs_deinit(AM335X_USBSS_BASE_ADDR,
-                                                       AM335X_USBSS_BASE_LEN))
+                                               AM335X_USBSS_TOTAL_REG_LEN))
                        USB_MSG("Failed to release USBSS mapping");
 }
 
@@ -449,14 +426,11 @@ musb_am335x_internal_init(void)
                return EXIT_FAILURE;
 
        /* TODO: time to stabilize? */
-       {
-               /* Sleep 25ms */
-               struct timespec nanotm = {0, HCD_NANOSLEEP_MSEC(25)};
-               nanosleep(&nanotm, NULL);
-       }
+       /* Sleep 25msec */
+       hcd_os_nanosleep(HCD_NANOSLEEP_MSEC(25));
 
        /* Read and dump revision register */
-       USB_MSG("Revision (REVREG): %08X",
+       USB_MSG("MUSB revision (REVREG): %08X",
                (unsigned int)HCD_RD4(am335x.ss.regs, AM335X_REG_REVREG));
 
        /* Allow OS to handle previously configured USBSS interrupts */
@@ -469,8 +443,6 @@ musb_am335x_internal_init(void)
        hcd_os_interrupt_enable(AM335X_USB0_IRQ);
        /* Enable whatever necessary for OTG part of controller */
        musb_am335x_otg_enable(AM335X_USB0);
-       /* Configure control endpoint EP0 */
-       musb_ep0_config(&(am335x.ctrl[AM335X_USB0].core));
        /* Start actual MUSB core */
        musb_core_start(&(am335x.ctrl[AM335X_USB0].core));
 #endif
@@ -481,8 +453,6 @@ musb_am335x_internal_init(void)
        hcd_os_interrupt_enable(AM335X_USB1_IRQ);
        /* Enable whatever necessary for OTG part of controller */
        musb_am335x_otg_enable(AM335X_USB1);
-       /* Configure control endpoint EP0 */
-       musb_ep0_config(&(am335x.ctrl[AM335X_USB1].core));
        /* Start actual MUSB core */
        musb_core_start(&(am335x.ctrl[AM335X_USB1].core));
 
@@ -581,8 +551,7 @@ musb_am335x_usbx_isr(void * data)
        if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_CONNECTED) {
                USB_DBG("Device connected");
                CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_CONNECTED);
-               driver->event = HCD_EVENT_CONNECTED;
-               driver->subevent = HCD_SUBEVENT_NONE;
+               driver->current_event = HCD_EVENT_CONNECTED;
                hcd_handle_event(driver);
                return;
        }
@@ -590,17 +559,16 @@ musb_am335x_usbx_isr(void * data)
        if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_DISCONNECTED) {
                USB_DBG("Device disconnected");
                CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_DISCONNECTED);
-               driver->event = HCD_EVENT_DISCONNECTED;
-               driver->subevent = HCD_SUBEVENT_NONE;
+               driver->current_event = HCD_EVENT_DISCONNECTED;
                hcd_handle_event(driver);
                return;
        }
 
-       if (irqstat0 & 0x01) {
-               USB_DBG("EP0 interrupt");
-               CLEAR_IRQ0(0x01);
-               driver->event = HCD_EVENT_ENDPOINT;
-               driver->subevent = HCD_SUBEVENT_EP0;
+       if (0 != irqstat0) {
+               USB_DBG("EP interrupt");
+               CLEAR_IRQ0(irqstat0);
+               driver->current_event = HCD_EVENT_ENDPOINT;
+               driver->current_endpoint = musb_am335x_irqstat0_to_ep(irqstat0);
                hcd_handle_event(driver);
                return;
        }
@@ -654,6 +622,34 @@ musb_am335x_usbx_isr(void * data)
 }
 
 
+/*===========================================================================*
+ *    musb_am335x_irqstat0_to_ep                                             *
+ *===========================================================================*/
+static int
+musb_am335x_irqstat0_to_ep(int irqstat0)
+{
+       int ep;
+
+       DEBUG_DUMP;
+
+       ep = 0;
+
+       while (0 == (irqstat0 & 0x01)) {
+               irqstat0 >>= 1;
+               ep++;
+               USB_ASSERT(ep < 32, "Invalid IRQSTAT0 supplied (1)");
+       }
+
+       /* Convert RX interrupt to EP number */
+       if (ep >= 16) {
+               ep -= 16;
+               USB_ASSERT(ep != 0, "Invalid IRQSTAT0 supplied (2)");
+       }
+
+       return ep;
+}
+
+
 /*===========================================================================*
  *    musb_am335x_usb_reset                                                  *
  *===========================================================================*/
@@ -711,8 +707,47 @@ musb_am335x_otg_enable(int usb_num)
 
        HCD_WR4(r, AM335X_REG_USBXIRQENABLESET1, intreg);
 
-       /* Set endpoint 0 interrupt to be enabled */
+       /* 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     |
+               AM335X_VAL_USBXIRQENABLEXXX0_TX_EP2     |
+               AM335X_VAL_USBXIRQENABLEXXX0_TX_EP3     |
+               AM335X_VAL_USBXIRQENABLEXXX0_TX_EP4     |
+               AM335X_VAL_USBXIRQENABLEXXX0_TX_EP5     |
+               AM335X_VAL_USBXIRQENABLEXXX0_TX_EP6     |
+               AM335X_VAL_USBXIRQENABLEXXX0_TX_EP7     |
+               AM335X_VAL_USBXIRQENABLEXXX0_TX_EP8     |
+               AM335X_VAL_USBXIRQENABLEXXX0_TX_EP9     |
+               AM335X_VAL_USBXIRQENABLEXXX0_TX_EP10    |
+               AM335X_VAL_USBXIRQENABLEXXX0_TX_EP11    |
+               AM335X_VAL_USBXIRQENABLEXXX0_TX_EP12    |
+               AM335X_VAL_USBXIRQENABLEXXX0_TX_EP13    |
+               AM335X_VAL_USBXIRQENABLEXXX0_TX_EP14    |
+               AM335X_VAL_USBXIRQENABLEXXX0_TX_EP15    |
+               AM335X_VAL_USBXIRQENABLEXXX0_RX_EP1     |
+               AM335X_VAL_USBXIRQENABLEXXX0_RX_EP2     |
+               AM335X_VAL_USBXIRQENABLEXXX0_RX_EP3     |
+               AM335X_VAL_USBXIRQENABLEXXX0_RX_EP4     |
+               AM335X_VAL_USBXIRQENABLEXXX0_RX_EP5     |
+               AM335X_VAL_USBXIRQENABLEXXX0_RX_EP6     |
+               AM335X_VAL_USBXIRQENABLEXXX0_RX_EP7     |
+               AM335X_VAL_USBXIRQENABLEXXX0_RX_EP8     |
+               AM335X_VAL_USBXIRQENABLEXXX0_RX_EP9     |
+               AM335X_VAL_USBXIRQENABLEXXX0_RX_EP10    |
+               AM335X_VAL_USBXIRQENABLEXXX0_RX_EP11    |
+               AM335X_VAL_USBXIRQENABLEXXX0_RX_EP12    |
+               AM335X_VAL_USBXIRQENABLEXXX0_RX_EP13    |
+               AM335X_VAL_USBXIRQENABLEXXX0_RX_EP14    |
+               AM335X_VAL_USBXIRQENABLEXXX0_RX_EP15    ;
+
+       HCD_WR4(r, AM335X_REG_USBXIRQENABLESET0, intreg);
+#endif
 }
index cf2435ad9653ac0e0cfb31e28145ca20845b7d9c..f17a0972e5a1a3afb38aac94d435114fbe7aae66 100755 (executable)
@@ -3,7 +3,6 @@
  */
 
 #include <string.h>                            /* memcpy */
-#include <time.h>                              /* nanosleep */
 
 #include <usb/hcd_common.h>
 #include <usb/hcd_interface.h>
 #include "musb_regs.h"
 
 
-/*===========================================================================*
- *    Local defines                                                          *
- *===========================================================================*/
-#define HCD_COPYBUF_BYTES 64 /* Stack allocated, must be multiple of 4 */
-#define HCD_COPYBUF_WORDS (HCD_COPYBUF_BYTES/4)
-
-
 /*===========================================================================*
  *    Local prototypes                                                       *
  *===========================================================================*/
 static void musb_set_state(musb_core_config *);
-static int musb_check_rxpktrdy(void *);
-static void musb_in_stage_cleanup(void *);
-static void musb_clear_rxpktrdy(void *);
+static int musb_check_rxpktrdy(void *, int);
+static void musb_in_stage_cleanup(void *, int);
+static void musb_clear_rxpktrdy(void *, int);
 static void musb_clear_statuspkt(void *);
 static int musb_get_count(void *);
-static void musb_read_fifo(void *, hcd_reg1 *, int, int);
+static void musb_read_fifo(void *, void *, int, int);
+static void musb_write_fifo(void *, void *, int, int);
 
 
 /*===========================================================================*
@@ -45,23 +38,23 @@ static void
 musb_set_state(musb_core_config * cfg)
 {
        void * r;
-       hcd_reg1 idx;
 
        DEBUG_DUMP;
 
        r = cfg->regs;
 
+       USB_ASSERT(cfg->ep <= 15, "Invalid EP supplied");
+       USB_ASSERT(cfg->addr <= 127, "Invalid device address supplied");
+
        /* Set EP and address to be used in next MUSB command */
 
        /* Set EP by selecting INDEX */
-       idx = HCD_RD1(r, MUSB_REG_INDEX);
-       HCD_CLR(idx, 0x0F);
-       HCD_SET(idx, cfg->ep & 0x0F);
-       HCD_WR1(r, MUSB_REG_INDEX, idx);
+       HCD_WR1(r, MUSB_REG_INDEX, cfg->ep);
 
        /* Use device with address 'cfg->addr' */
-       HCD_WR2(r, MUSB_REG_RXFUNCADDR, cfg->addr);
-       HCD_WR2(r, MUSB_REG_TXFUNCADDR, cfg->addr);
+       HCD_WR1(r, MUSB_REG_FADDR, cfg->addr);
+       HCD_WR2(r, MUSB_REG_CONFIG(cfg->ep, MUSB_REG_RXFUNCADDR), cfg->addr);
+       HCD_WR2(r, MUSB_REG_CONFIG(cfg->ep, MUSB_REG_TXFUNCADDR), cfg->addr);
 }
 
 
@@ -69,10 +62,9 @@ musb_set_state(musb_core_config * cfg)
  *    musb_check_rxpktrdy                                                    *
  *===========================================================================*/
 static int
-musb_check_rxpktrdy(void * cfg)
+musb_check_rxpktrdy(void * cfg, int ep_num)
 {
        void * r;
-       hcd_reg2 host_csr0;
 
        DEBUG_DUMP;
 
@@ -81,12 +73,18 @@ musb_check_rxpktrdy(void * cfg)
        /* Set EP and device address to be used in this command */
        musb_set_state((musb_core_config *)cfg);
 
-       /* Get control status register for EP 0 */
-       host_csr0 = HCD_RD2(r, MUSB_REG_HOST_CSR0);
-
        /* Check for RXPKTRDY */
-       if (host_csr0 & MUSB_VAL_HOST_CSR0_RXPKTRDY)
-               return EXIT_SUCCESS;
+       if (0 == ep_num) {
+               /* Get control status register for EP 0 */
+               if (HCD_RD2(r, MUSB_REG_HOST_CSR0) &
+                       MUSB_VAL_HOST_CSR0_RXPKTRDY)
+                       return EXIT_SUCCESS;
+       } else {
+               /* Get RX status register for any other EP */
+               if (HCD_RD2(r, MUSB_REG_HOST_RXCSR) &
+                       MUSB_VAL_HOST_RXCSR_RXPKTRDY)
+                       return EXIT_SUCCESS;
+       }
 
        return EXIT_FAILURE;
 }
@@ -96,12 +94,15 @@ musb_check_rxpktrdy(void * cfg)
  *    musb_in_stage_cleanup                                                  *
  *===========================================================================*/
 static void
-musb_in_stage_cleanup(void * cfg)
+musb_in_stage_cleanup(void * cfg, int ep_num)
 {
        DEBUG_DUMP;
 
-       musb_clear_rxpktrdy(cfg);
-       musb_clear_statuspkt(cfg);
+       musb_clear_rxpktrdy(cfg, ep_num);
+
+       /* For control EP 0 also clear STATUSPKT */
+       if (0 == ep_num)
+               musb_clear_statuspkt(cfg);
 }
 
 
@@ -109,10 +110,10 @@ musb_in_stage_cleanup(void * cfg)
  *    musb_clear_rxpktrdy                                                    *
  *===========================================================================*/
 static void
-musb_clear_rxpktrdy(void * cfg)
+musb_clear_rxpktrdy(void * cfg, int ep_num)
 {
        void * r;
-       hcd_reg2 host_csr0;
+       hcd_reg2 host_csr;
 
        DEBUG_DUMP;
 
@@ -121,12 +122,22 @@ musb_clear_rxpktrdy(void * cfg)
        /* Set EP and device address to be used in this command */
        musb_set_state((musb_core_config *)cfg);
 
-       /* Get control status register for EP 0 */
-       host_csr0 = HCD_RD2(r, MUSB_REG_HOST_CSR0);
-
-       /* Clear RXPKTRDY to signal receive completion */
-       HCD_CLR(host_csr0, MUSB_VAL_HOST_CSR0_RXPKTRDY);
-       HCD_WR2(r, MUSB_REG_HOST_CSR0, host_csr0);
+       /* Check for RXPKTRDY */
+       if (0 == ep_num) {
+               /* Get control status register for EP 0 */
+               host_csr = HCD_RD2(r, MUSB_REG_HOST_CSR0);
+
+               /* Clear RXPKTRDY to signal receive completion */
+               HCD_CLR(host_csr, MUSB_VAL_HOST_CSR0_RXPKTRDY);
+               HCD_WR2(r, MUSB_REG_HOST_CSR0, host_csr);
+       } else {
+               /* Get RX status register for any other EP */
+               host_csr = HCD_RD2(r, MUSB_REG_HOST_RXCSR);
+
+               /* Clear RXPKTRDY to signal receive completion */
+               HCD_CLR(host_csr, MUSB_VAL_HOST_RXCSR_RXPKTRDY);
+               HCD_WR2(r, MUSB_REG_HOST_RXCSR, host_csr);
+       }
 }
 
 
@@ -180,41 +191,92 @@ musb_get_count(void * cfg)
  *    musb_read_fifo                                                         *
  *===========================================================================*/
 static void
-musb_read_fifo(void * cfg, hcd_reg1 * output, int size, int fifo_num)
+musb_read_fifo(void * cfg, void * output, int size, int fifo_num)
 {
        void * r;
-       hcd_reg4 * word;
-       hcd_reg4 copy_buf[HCD_COPYBUF_WORDS];
+
+       hcd_reg1 * output_b;
+       hcd_reg4 * output_w;
+
        hcd_addr fifo_addr;
-       int limit;
-       int idx;
 
        DEBUG_DUMP;
 
-       USB_ASSERT((fifo_num >= 0) && (fifo_num <= 4), "Wrong FIFO number");
+       USB_ASSERT((fifo_num >= 0) && (fifo_num <= 15), "Wrong FIFO number");
 
        r = ((musb_core_config *)cfg)->regs;
        fifo_addr = MUSB_REG_FIFO0 + (fifo_num * MUSB_REG_FIFO_LEN);
 
-       /* Set EP and device address to be used in this command */
-       musb_set_state((musb_core_config *)cfg);
+       /* TODO: Apparently, FIFO can only be read by:
+        * 1. initially using words
+        * 2. using bytes for whatever remains
+        * Reading bytes first to achieve alignment of remaining data
+        * will for some reason disable further word based reading
+        * Such reading method, may not be optimal for unaligned data */
+       output_w = (hcd_reg4 *)output;
+
+       /* Try and copy aligned words */
+       if (0 == ((hcd_addr)output_w % 4)) {
+
+               while (size > (int)(sizeof(*output_w) - 1)) {
+                       *output_w++ = HCD_RD4(r, fifo_addr);
+                       size -= sizeof(*output_w);
+               }
+       }
 
-       /* Read full words from MUSB FIFO */
+       output_b = (hcd_reg1 *)output_w;
+
+       /* Then, go with remaining bytes */
        while (size > 0) {
-               /* Largest amount of bytes that can be copied at a time */
-               limit = (size < HCD_COPYBUF_BYTES) ? size : HCD_COPYBUF_BYTES;
+               *output_b++ = HCD_RD1(r, fifo_addr);
+               size--;
+       }
+}
+
 
-               /* Start copying into that */
-               word = copy_buf;
+/*===========================================================================*
+ *    musb_write_fifo                                                         *
+ *===========================================================================*/
+static void
+musb_write_fifo(void * cfg, void * input, int size, int fifo_num)
+{
+       void * r;
 
-               /* Read words from FIFO into copy_buf */
-               for (idx = 0; idx < limit; idx += sizeof(*word))
-                       *word++ = HCD_RD4(r, fifo_addr);
+       hcd_reg1 * input_b;
+       hcd_reg4 * input_w;
 
-               /* Copy and shift */
-               memcpy(output, copy_buf, limit);
-               output += limit;
-               size -= limit;
+       hcd_addr fifo_addr;
+
+       DEBUG_DUMP;
+
+       USB_ASSERT((fifo_num >= 0) && (fifo_num <= 15), "Wrong FIFO number");
+
+       r = ((musb_core_config *)cfg)->regs;
+       fifo_addr = MUSB_REG_FIFO0 + (fifo_num * MUSB_REG_FIFO_LEN);
+
+       /* TODO: Apparently, FIFO can only be written by:
+        * 1. initially using words
+        * 2. using bytes for whatever remains
+        * Writing bytes first to achieve alignment of remaining data
+        * will for some reason disable further word based writing
+        * Such writing method, may not be optimal for unaligned data */
+       input_w = (hcd_reg4 *)input;
+
+       /* Try and copy aligned words */
+       if (0 == ((hcd_addr)input_w % 4)) {
+
+               while (size > (int)(sizeof(*input_w) - 1)) {
+                       HCD_WR4(r, fifo_addr, *input_w++);
+                       size -= sizeof(*input_w);
+               }
+       }
+
+       input_b = (hcd_reg1 *)input_w;
+
+       /* Then, go with remaining bytes */
+       while (size > 0) {
+               HCD_WR1(r, fifo_addr, *input_b++);
+               size--;
        }
 }
 
@@ -272,41 +334,6 @@ musb_core_stop(void * cfg)
 }
 
 
-/*===========================================================================*
- *    musb_ep0_config                                                        *
- *===========================================================================*/
-void
-musb_ep0_config(void * cfg)
-{
-       void * r;
-       hcd_reg1 host_type0;
-       hcd_reg2 intrtxe;
-
-       DEBUG_DUMP;
-
-       r = ((musb_core_config *)cfg)->regs;
-
-       /* Set parameters temporarily */
-       musb_setup_device((musb_core_config *)cfg,
-                       HCD_DEFAULT_EP,
-                       HCD_DEFAULT_ADDR);
-
-       /* Set EP and device address to be used in this command */
-       musb_set_state((musb_core_config *)cfg);
-
-       /* Set high speed for EP0 */
-       host_type0 = HCD_RD1(r, MUSB_REG_HOST_TYPE0);
-       HCD_CLR(host_type0, MUSB_VAL_HOST_TYPE0_MASK);
-       HCD_SET(host_type0, MUSB_VAL_HOST_TYPE0_HIGH_SPEED);
-       HCD_WR1(r, MUSB_REG_HOST_TYPE0, host_type0);
-
-       /* Enable EP interrupt */
-       intrtxe = HCD_RD2(r, MUSB_REG_INTRTXE);
-       HCD_SET(intrtxe, MUSB_VAL_INTRTXE_EP0);
-       HCD_WR2(r, MUSB_REG_INTRTXE, intrtxe);
-}
-
-
 /*===========================================================================*
  *                                                                           *
  *    HCD interface implementation                                           *
@@ -330,15 +357,24 @@ musb_setup_device(void * cfg, hcd_reg1 ep, hcd_reg1 addr)
 /*===========================================================================*
  *    musb_reset_device                                                      *
  *===========================================================================*/
-void
-musb_reset_device(void * cfg)
+int
+musb_reset_device(void * cfg, hcd_speed * speed)
 {
        void * r;
+       musb_core_config * core;
        hcd_reg1 power;
+       hcd_reg1 host_type0;
 
        DEBUG_DUMP;
 
-       r = ((musb_core_config *)cfg)->regs;
+       core = (musb_core_config *)cfg;
+       r = core->regs;
+
+       /* Set initial parameters */
+       musb_setup_device(core, HCD_DEFAULT_EP, HCD_DEFAULT_ADDR);
+
+       /* Set EP and device address to be used in this command */
+       musb_set_state(core);
 
        /* Write reset bit and high speed negotiation wait for at least
         * 20ms for reset, clear reset bit and wait for device */
@@ -346,21 +382,37 @@ musb_reset_device(void * cfg)
        HCD_SET(power, MUSB_VAL_POWER_RESET | MUSB_VAL_POWER_HSEN);
        HCD_WR1(r, MUSB_REG_POWER, power);
 
-       {
-               /* Sleep 25ms */
-               struct timespec nanotm = {0, HCD_NANOSLEEP_MSEC(25)};
-               nanosleep(&nanotm, NULL);
-       }
+       /* Sleep 25msec */
+       hcd_os_nanosleep(HCD_NANOSLEEP_MSEC(25));
 
        power = HCD_RD1(r, MUSB_REG_POWER);
        HCD_CLR(power, MUSB_VAL_POWER_RESET);
        HCD_WR1(r, MUSB_REG_POWER, power);
 
-       {
-               /* Sleep 25ms */
-               struct timespec nanotm = {0, HCD_NANOSLEEP_MSEC(25)};
-               nanosleep(&nanotm, NULL);
+       /* Sleep 25msec */
+       hcd_os_nanosleep(HCD_NANOSLEEP_MSEC(25));
+
+       /* High speed check */
+       power = HCD_RD1(r, MUSB_REG_POWER);
+
+       if (power & MUSB_VAL_POWER_HSMODE) {
+               /* Set high-speed for EP0 */
+               host_type0 = HCD_RD1(r, MUSB_REG_HOST_TYPE0);
+               HCD_CLR(host_type0, MUSB_VAL_HOST_TYPE0_MASK);
+               HCD_SET(host_type0, MUSB_VAL_HOST_TYPE0_HIGH_SPEED);
+               HCD_WR1(r, MUSB_REG_HOST_TYPE0, host_type0);
+
+               *speed = HCD_SPEED_HIGH;
+
+               USB_DBG("High speed USB enabled");
+       } else {
+               /* Only full-speed supported */
+               USB_DBG("High speed USB disabled");
+
+               *speed = HCD_SPEED_FULL;
        }
+
+       return EXIT_SUCCESS;
 }
 
 
@@ -372,19 +424,21 @@ musb_setup_stage(void * cfg, hcd_ctrlrequest * setup)
 {
        void * r;
        char * setup_byte;
+       musb_core_config * core;
        hcd_reg2 host_csr0;
 
        DEBUG_DUMP;
 
-       r = ((musb_core_config *)cfg)->regs;
+       core = (musb_core_config *)cfg;
+       r = core->regs;
        setup_byte = (char*)setup;
 
-       /* Set EP and device address to be used in this command */
-       musb_set_state((musb_core_config *)cfg);
+       USB_ASSERT(0 == core->ep, "Only EP 0 can handle control transfers");
 
-       /* TODO: check for ongoing transmission */
+       /* Set EP and device address to be used in this command */
+       musb_set_state(core);
 
-       /* Put USB setup data into corresponding FIFO */
+       /* Put USB setup data into EP0 FIFO */
        HCD_WR4(r, MUSB_REG_FIFO0, HCD_8TO32(&setup_byte[0]));
        HCD_WR4(r, MUSB_REG_FIFO0, HCD_8TO32(&setup_byte[sizeof(hcd_reg4)]));
 
@@ -399,6 +453,180 @@ musb_setup_stage(void * cfg, hcd_ctrlrequest * setup)
 }
 
 
+/*===========================================================================*
+ *    musb_bulk_in_stage                                                     *
+ *===========================================================================*/
+void
+musb_bulk_in_stage(void * cfg, hcd_bulkrequest * request)
+{
+       musb_core_config * core;
+#if 0
+       hcd_reg2 intrrxe;
+#endif
+       hcd_reg2 host_rxcsr;
+       hcd_reg1 host_rxtype;
+       void * r;
+
+       DEBUG_DUMP;
+
+       core = (musb_core_config *)cfg;
+       r = core->regs;
+
+       USB_ASSERT(request->max_packet_size <= 1024, "Invalid wMaxPacketSize");
+       USB_ASSERT((core->ep <= 15) && (core->ep > 0),
+               "Invalid bulk EP supplied");
+
+       /* Set EP and device address to be used in this command */
+       musb_set_state(core);
+
+       /* Evaluate RXTYPE */
+       host_rxtype = MUSB_VAL_HOST_XXTYPE_BULK | core->ep;
+
+       if (HCD_SPEED_HIGH == request->speed)
+               host_rxtype |= MUSB_VAL_HOST_XXTYPE_HIGH_SPEED;
+       else
+               host_rxtype |= MUSB_VAL_HOST_XXTYPE_FULL_SPEED;
+
+       /* Rewrite HOST_RXTYPE */
+       HCD_WR1(r, MUSB_REG_HOST_RXTYPE, host_rxtype);
+
+       /* Rewrite RXMAXP */
+       HCD_WR2(r, MUSB_REG_RXMAXP, request->max_packet_size);
+
+       /* Rewrite HOST_RXINTERVAL */
+       HCD_WR1(r, MUSB_REG_HOST_RXINTERVAL, MUSB_VAL_HOST_XXINTERVAL_DEFAULT);
+
+       /* Not required in some MUSB implementations */
+#if 0
+       /* Enable this interrupt */
+       intrrxe = HCD_RD2(r, MUSB_REG_INTRRXE);
+       HCD_SET(intrrxe, HCD_BIT(core->ep));
+       HCD_WR2(r, MUSB_REG_INTRRXE, intrrxe);
+#endif
+
+       /* TODO: One reusable FIFO, no double buffering */
+       /* TODO: With this, only one device can work at a time but it
+        * may be impossible to have MUSB work reasonably with multiple
+        * EP interrupts anyway */
+       /* Assign FIFO */
+       HCD_WR2(r, MUSB_REG_RXFIFOADDR, MUSB_VAL_XXFIFOADDR_EP0_END);
+       HCD_WR1(r, MUSB_REG_RXFIFOSZ, MUSB_VAL_XXFIFOSZ_4096);
+
+       /* TODO: decide which is better (or working at all when we use more
+        * than one transfer for bulk data in single device) */
+#if 0
+       /* Make controller reconfigure */
+       host_rxcsr = HCD_RD2(r, MUSB_REG_HOST_RXCSR);
+       HCD_SET(host_rxcsr, MUSB_VAL_HOST_RXCSR_CLRDATATOG);
+       HCD_SET(host_rxcsr, MUSB_VAL_HOST_RXCSR_FLUSHFIFO);
+       HCD_WR2(r, MUSB_REG_HOST_RXCSR, host_rxcsr);
+#else
+       /* Reset and flush */
+       host_rxcsr = 0;
+       HCD_SET(host_rxcsr, MUSB_VAL_HOST_RXCSR_CLRDATATOG);
+       HCD_SET(host_rxcsr, MUSB_VAL_HOST_RXCSR_FLUSHFIFO);
+       HCD_WR2(r, MUSB_REG_HOST_RXCSR, host_rxcsr);
+#endif
+
+       /* Request packet */
+       host_rxcsr = HCD_RD2(r, MUSB_REG_HOST_RXCSR);
+       HCD_SET(host_rxcsr, MUSB_VAL_HOST_RXCSR_REQPKT);
+       HCD_WR2(r, MUSB_REG_HOST_RXCSR, host_rxcsr);
+}
+
+
+/*===========================================================================*
+ *    musb_bulk_out_stage                                                    *
+ *===========================================================================*/
+void
+musb_bulk_out_stage(void * cfg, hcd_bulkrequest * request)
+{
+       musb_core_config * core;
+#if 0
+       hcd_reg2 intrtxe;
+#endif
+       hcd_reg2 host_txcsr;
+       hcd_reg1 host_txtype;
+       void * r;
+
+       DEBUG_DUMP;
+
+       core = (musb_core_config *)cfg;
+       r = core->regs;
+
+       USB_ASSERT(request->max_packet_size <= 1024, "Invalid wMaxPacketSize");
+       USB_ASSERT((core->ep <= 15) && (core->ep > 0),
+               "Invalid bulk EP supplied");
+
+       /* Set EP and device address to be used in this command */
+       musb_set_state(core);
+
+       /* Evaluate TXTYPE */
+       host_txtype = MUSB_VAL_HOST_XXTYPE_BULK | core->ep;
+
+       if (HCD_SPEED_HIGH == request->speed)
+               host_txtype |= MUSB_VAL_HOST_XXTYPE_HIGH_SPEED;
+       else
+               host_txtype |= MUSB_VAL_HOST_XXTYPE_FULL_SPEED;
+
+       /* Rewrite HOST_TXTYPE */
+       HCD_WR1(r, MUSB_REG_HOST_TXTYPE, host_txtype);
+
+       /* Rewrite TXMAXP */
+       HCD_WR2(r, MUSB_REG_TXMAXP, request->max_packet_size);
+
+       /* Rewrite HOST_TXINTERVAL */
+       HCD_WR1(r, MUSB_REG_HOST_TXINTERVAL, MUSB_VAL_HOST_XXINTERVAL_DEFAULT);
+
+       /* Not required in some MUSB implementations */
+#if 0
+       /* Enable this interrupt */
+       intrtxe = HCD_RD2(r, MUSB_REG_INTRTXE);
+       HCD_SET(intrtxe, HCD_BIT(core->ep));
+       HCD_WR2(r, MUSB_REG_INTRTXE, intrtxe);
+#endif
+
+       /* TODO: One reusable FIFO, no double buffering */
+       /* TODO: With this, only one device can work at a time but it
+        * may be impossible to have MUSB work reasonably with multiple
+        * EP interrupts anyway */
+       /* Assign FIFO */
+       HCD_WR2(r, MUSB_REG_TXFIFOADDR, MUSB_VAL_XXFIFOADDR_EP0_END);
+       HCD_WR1(r, MUSB_REG_TXFIFOSZ, MUSB_VAL_XXFIFOSZ_4096);
+
+       /* TODO: decide which is better (or working at all when we use more
+        * than one transfer for bulk data in single device) */
+#if 0
+       /* Make controller reconfigure */
+       host_txcsr = HCD_RD2(r, MUSB_REG_HOST_TXCSR);
+       HCD_CLR(host_txcsr, MUSB_VAL_HOST_TXCSR_DMAMODE);
+       HCD_CLR(host_txcsr, MUSB_VAL_HOST_TXCSR_FRCDATATOG);
+       HCD_CLR(host_txcsr, MUSB_VAL_HOST_TXCSR_DMAEN);
+       HCD_SET(host_txcsr, MUSB_VAL_HOST_TXCSR_MODE);
+       HCD_CLR(host_txcsr, MUSB_VAL_HOST_TXCSR_ISO);
+       HCD_CLR(host_txcsr, MUSB_VAL_HOST_TXCSR_AUTOSET);
+       HCD_SET(host_txcsr, MUSB_VAL_HOST_TXCSR_CLRDATATOG);
+       HCD_SET(host_txcsr, MUSB_VAL_HOST_TXCSR_FLUSHFIFO);
+       HCD_WR2(r, MUSB_REG_HOST_TXCSR, host_txcsr);
+#else
+       /* Reset and flush */
+       host_txcsr = 0;
+       HCD_SET(host_txcsr, MUSB_VAL_HOST_TXCSR_MODE);
+       HCD_SET(host_txcsr, MUSB_VAL_HOST_TXCSR_CLRDATATOG);
+       HCD_SET(host_txcsr, MUSB_VAL_HOST_TXCSR_FLUSHFIFO);
+       HCD_WR2(r, MUSB_REG_HOST_TXCSR, host_txcsr);
+#endif
+
+       /* Put data in FIFO */
+       musb_write_fifo(cfg, request->data, request->size, core->ep);
+
+       /* Request packet */
+       host_txcsr = HCD_RD2(r, MUSB_REG_HOST_TXCSR);
+       HCD_SET(host_txcsr, MUSB_VAL_HOST_TXCSR_TXPKTRDY);
+       HCD_WR2(r, MUSB_REG_HOST_TXCSR, host_txcsr);
+}
+
+
 /*===========================================================================*
  *    musb_in_data_stage                                                     *
  *===========================================================================*/
@@ -435,9 +663,8 @@ musb_out_data_stage(void * cfg)
        /* Set EP and device address to be used in this command */
        musb_set_state((musb_core_config *)cfg);
 
-       /* TODO: not needed for enumeration but will be needed later */
-       ((void)cfg);
-       USB_MSG("NOT IMPLEMENTED");
+       /* TODO: not needed for enumeration but may be needed later */
+       USB_MSG("Setup packet's 'DATA OUT' stage not implemented");
 }
 
 
@@ -499,29 +726,29 @@ musb_out_status_stage(void * cfg)
  *    musb_read_data                                                         *
  *===========================================================================*/
 int
-musb_read_data(void * cfg, hcd_reg1 * buffer, int buffer_num)
+musb_read_data(void * cfg, hcd_reg1 * buffer, int ep_num)
 {
-       int count0;
+       int count;
 
        DEBUG_DUMP;
 
        /* Check if anything received at all */
-       if (EXIT_SUCCESS != musb_check_rxpktrdy(cfg)) {
+       if (EXIT_SUCCESS != musb_check_rxpktrdy(cfg, ep_num)) {
                USB_MSG("RXPKTRDY not set when receiving");
                return HCD_READ_ERR;
        }
 
-       /* Number of bytes received at EP0 */
-       count0 = musb_get_count(cfg);
+       /* Number of bytes received at any EP */
+       count = musb_get_count(cfg);
 
        /* Read from given FIFO */
-       if ((NULL != buffer) && (count0 > 0))
-               musb_read_fifo(cfg, buffer, count0, buffer_num);
+       if ((NULL != buffer) && (count > 0))
+               musb_read_fifo(cfg, buffer, count, ep_num);
 
        /* Cleanup after reading */
-       musb_in_stage_cleanup(cfg);
+       musb_in_stage_cleanup(cfg, ep_num);
 
-       return count0;
+       return count;
 }
 
 
@@ -529,10 +756,10 @@ musb_read_data(void * cfg, hcd_reg1 * buffer, int buffer_num)
  *    musb_check_error                                                       *
  *===========================================================================*/
 int
-musb_check_error(void * cfg)
+musb_check_error(void * cfg, hcd_transfer transfer, hcd_direction dir)
 {
        void * r;
-       hcd_reg2 host_csr0;
+       hcd_reg2 host_csr;
 
        DEBUG_DUMP;
 
@@ -541,30 +768,95 @@ musb_check_error(void * cfg)
        /* Set EP and device address to be used in this command */
        musb_set_state((musb_core_config *)cfg);
 
-       /* Get control status register for EP 0 */
-       host_csr0 = HCD_RD2(r, MUSB_REG_HOST_CSR0);
+       /* TODO: In MUSB only EP0 is allowed to handle control transfers
+        * so there is no EP checking in this function */
+       if (HCD_TRANSFER_CONTROL == transfer) {
+               /* Get control status register */
+               host_csr = HCD_RD2(r, MUSB_REG_HOST_CSR0);
+
+               /* Check for common errors */
+               if (host_csr & MUSB_VAL_HOST_CSR0_ERROR) {
+                       USB_MSG("HOST_CSR0 ERROR: %04X", host_csr);
+                       HCD_CLR(host_csr, MUSB_VAL_HOST_CSR0_ERROR);
+                       HCD_WR2(r, MUSB_REG_HOST_CSR0, host_csr);
+                       return EXIT_FAILURE;
+               }
+
+               if (host_csr & MUSB_VAL_HOST_CSR0_RXSTALL) {
+                       USB_MSG("HOST_CSR0 STALL: %04X", host_csr);
+                       HCD_CLR(host_csr, MUSB_VAL_HOST_CSR0_RXSTALL);
+                       HCD_WR2(r, MUSB_REG_HOST_CSR0, host_csr);
+                       return EXIT_FAILURE;
+               }
+
+               if (host_csr & MUSB_VAL_HOST_CSR0_NAK_TIMEOUT) {
+                       USB_MSG("HOST_CSR0 NAK_TIMEOUT: %04X", host_csr);
+                       HCD_CLR(host_csr, MUSB_VAL_HOST_CSR0_NAK_TIMEOUT);
+                       HCD_WR2(r, MUSB_REG_HOST_CSR0, host_csr);
+                       return EXIT_FAILURE;
+               }
 
-       /* Check for common errors */
-       if (host_csr0 & MUSB_VAL_HOST_CSR0_ERROR) {
-               USB_MSG("HOST_CSR0 ERROR: %04X", host_csr0);
-               HCD_CLR(host_csr0, MUSB_VAL_HOST_CSR0_ERROR);
-               HCD_WR2(r, MUSB_REG_HOST_CSR0, host_csr0);
-               return EXIT_FAILURE;
+               return EXIT_SUCCESS;
        }
 
-       if (host_csr0 & MUSB_VAL_HOST_CSR0_RXSTALL) {
-               USB_MSG("HOST_CSR0 STALL: %04X", host_csr0);
-               HCD_CLR(host_csr0, MUSB_VAL_HOST_CSR0_RXSTALL);
-               HCD_WR2(r, MUSB_REG_HOST_CSR0, host_csr0);
-               return EXIT_FAILURE;
+       if ((HCD_TRANSFER_BULK == transfer) && (HCD_DIRECTION_OUT == dir)) {
+               /* Get RX status register */
+               host_csr = HCD_RD2(r, MUSB_REG_HOST_TXCSR);
+
+               /* Check for common errors */
+               if (host_csr & MUSB_VAL_HOST_TXCSR_ERROR) {
+                       USB_MSG("HOST_TXCSR ERROR: %04X", host_csr);
+                       HCD_CLR(host_csr, MUSB_VAL_HOST_TXCSR_ERROR);
+                       HCD_WR2(r, MUSB_REG_HOST_TXCSR, host_csr);
+                       return EXIT_FAILURE;
+               }
+
+               if (host_csr & MUSB_VAL_HOST_TXCSR_RXSTALL) {
+                       USB_MSG("HOST_TXCSR STALL: %04X", host_csr);
+                       HCD_CLR(host_csr, MUSB_VAL_HOST_TXCSR_RXSTALL);
+                       HCD_WR2(r, MUSB_REG_HOST_TXCSR, host_csr);
+                       return EXIT_FAILURE;
+               }
+
+               if (host_csr & MUSB_VAL_HOST_TXCSR_NAK_TIMEOUT) {
+                       USB_MSG("HOST_TXCSR NAK_TIMEOUT: %04X", host_csr);
+                       HCD_CLR(host_csr, MUSB_VAL_HOST_TXCSR_NAK_TIMEOUT);
+                       HCD_WR2(r, MUSB_REG_HOST_TXCSR, host_csr);
+                       return EXIT_FAILURE;
+               }
+
+               return EXIT_SUCCESS;
        }
 
-       if (host_csr0 & MUSB_VAL_HOST_CSR0_NAK_TIMEOUT) {
-               USB_MSG("HOST_CSR0 NAK_TIMEOUT: %04X", host_csr0);
-               HCD_CLR(host_csr0, MUSB_VAL_HOST_CSR0_NAK_TIMEOUT);
-               HCD_WR2(r, MUSB_REG_HOST_CSR0, host_csr0);
-               return EXIT_FAILURE;
+       if ((HCD_TRANSFER_BULK == transfer) && (HCD_DIRECTION_IN == dir)) {
+               /* Get RX status register */
+               host_csr = HCD_RD2(r, MUSB_REG_HOST_RXCSR);
+
+               /* Check for common errors */
+               if (host_csr & MUSB_VAL_HOST_RXCSR_ERROR) {
+                       USB_MSG("HOST_RXCSR ERROR: %04X", host_csr);
+                       HCD_CLR(host_csr, MUSB_VAL_HOST_RXCSR_ERROR);
+                       HCD_WR2(r, MUSB_REG_HOST_RXCSR, host_csr);
+                       return EXIT_FAILURE;
+               }
+
+               if (host_csr & MUSB_VAL_HOST_RXCSR_RXSTALL) {
+                       USB_MSG("HOST_RXCSR STALL: %04X", host_csr);
+                       HCD_CLR(host_csr, MUSB_VAL_HOST_RXCSR_RXSTALL);
+                       HCD_WR2(r, MUSB_REG_HOST_RXCSR, host_csr);
+                       return EXIT_FAILURE;
+               }
+
+               if (host_csr & MUSB_VAL_HOST_RXCSR_NAKTIMEOUT) {
+                       USB_MSG("HOST_RXCSR NAK_TIMEOUT: %04X", host_csr);
+                       HCD_CLR(host_csr, MUSB_VAL_HOST_RXCSR_NAKTIMEOUT);
+                       HCD_WR2(r, MUSB_REG_HOST_RXCSR, host_csr);
+                       return EXIT_FAILURE;
+               }
+
+               return EXIT_SUCCESS;
        }
 
-       return EXIT_SUCCESS;
+       USB_MSG("Invalid USB transfer 0x%X:0x%X", (int)transfer, (int)dir);
+       return EXIT_FAILURE;
 }
index c85aa184831d04dc4edfe51d979f0cbabecce1ca..e51f15988c8f17a81e2a9d7e8de462048e804ab5 100755 (executable)
@@ -29,19 +29,20 @@ musb_core_config;
 /* Only to be used outside generic HCD code */
 void musb_core_start(void *);
 void musb_core_stop(void *);
-void musb_ep0_config(void *);
 
 
 /* For HCD interface */
 void musb_setup_device(void *, hcd_reg1, hcd_reg1);
-void musb_reset_device(void *);
+int musb_reset_device(void *, hcd_speed *);
 void musb_setup_stage(void *, hcd_ctrlrequest *);
+void musb_bulk_in_stage(void *, hcd_bulkrequest *);
+void musb_bulk_out_stage(void *, hcd_bulkrequest *);
 void musb_in_data_stage(void *);
 void musb_out_data_stage(void *);
 void musb_in_status_stage(void *);
 void musb_out_status_stage(void *);
 int musb_read_data(void *, hcd_reg1 *, int);
-int musb_check_error(void *);
+int musb_check_error(void *, hcd_transfer, hcd_direction);
 
 
 #endif /* !_MUSB_CORE_H_ */
index 15fd554d915887fea03a393b243bfd993c31cc79..ad56cfce96259ded6c6143693b5a53e041d67b6e 100755 (executable)
 #define MUSB_REG_HOST_TXCSR                            MUSB_REG_PERI_CSR0
 #define MUSB_REG_RXMAXP                                0x14u
 #define MUSB_REG_PERI_RXCSR                    0x16u
-#define MUSB_REG_HOST_RXCSR                            MUSB_PERI_RXCSR
+#define MUSB_REG_HOST_RXCSR                            MUSB_REG_PERI_RXCSR
 #define MUSB_REG_COUNT0                                0x18u
-#define MUSB_REG_RXCOUNT                               MUSB_COUNT0
+#define MUSB_REG_RXCOUNT                               MUSB_REG_COUNT0
 #define MUSB_REG_HOST_TYPE0                    0x1Au
-#define MUSB_REG_HOST_TXTYPE                           MUSB_HOST_TYPE0
+#define MUSB_REG_HOST_TXTYPE                           MUSB_REG_HOST_TYPE0
 #define MUSB_REG_HOST_NAKLIMIT0                        0x1Bu
-#define MUSB_REG_HOST_TXINTERVAL                       MUSB_HOST_NAKLIMIT0
+#define MUSB_REG_HOST_TXINTERVAL                       MUSB_REG_HOST_NAKLIMIT0
 #define MUSB_REG_HOST_RXTYPE                   0x1Cu
 #define MUSB_REG_HOST_RXINTERVAL               0x1Du
-#define MUSB_REG_CONFIGDATA                    0x1Fu
 
 #define MUSB_REG_FIFO0                         0x20u
 #define MUSB_REG_FIFO1                         0x24u
 #define MUSB_REG_TXFIFOADDR                    0x64u
 #define MUSB_REG_RXFIFOADDR                    0x66u
 
-#define MUSB_REG_TXFUNCADDR                    0x80u
-#define MUSB_REG_TXHUBADDR                     0x82u
-#define MUSB_REG_TXHUBPORT                     0x83u
-#define MUSB_REG_RXFUNCADDR                    0x84u
-#define MUSB_REG_RXHUBADDR                     0x86u
-#define MUSB_REG_RXHUBPORT                     0x87u
+#define MUSB_REG_EP_CONFIG_BASE                        0x80u
+#define MUSB_REG_TXFUNCADDR                    0x00u
+#define MUSB_REG_TXHUBADDR                     0x02u
+#define MUSB_REG_TXHUBPORT                     0x03u
+#define MUSB_REG_RXFUNCADDR                    0x04u
+#define MUSB_REG_RXHUBADDR                     0x06u
+#define MUSB_REG_RXHUBPORT                     0x07u
+#define MUSB_REG_EP_CONFIG_LEN                 0x08u
+#define MUSB_REG_CONFIG(ep,reg)                        \
+       (MUSB_REG_EP_CONFIG_BASE + (MUSB_REG_EP_CONFIG_LEN * (ep)) + (reg))
 
 
 /*===========================================================================*
 #define MUSB_VAL_HOST_CSR0_NAK_TIMEOUT         HCD_BIT(7)
 #define MUSB_VAL_HOST_CSR0_FLUSHFIFO           HCD_BIT(8)
 
+/* HOST_RXTYPE/HOST_TXTYPE */
+#define MUSB_VAL_HOST_XXTYPE_SPEED_MASK                (HCD_BIT(6) | HCD_BIT(7))
+#define MUSB_VAL_HOST_XXTYPE_HIGH_SPEED                HCD_BIT(6)
+#define MUSB_VAL_HOST_XXTYPE_FULL_SPEED                HCD_BIT(7)
+#define MUSB_VAL_HOST_XXTYPE_LOW_SPEED         (HCD_BIT(6) | HCD_BIT(7))
+#define MUSB_VAL_HOST_XXTYPE_PROT_MASK         (HCD_BIT(4) | HCD_BIT(5))
+#define MUSB_VAL_HOST_XXTYPE_ISOCHRONOUS       HCD_BIT(4)
+#define MUSB_VAL_HOST_XXTYPE_BULK              HCD_BIT(5)
+#define MUSB_VAL_HOST_XXTYPE_INTERRUPT         (HCD_BIT(4) | HCD_BIT(5))
+#define MUSB_VAL_HOST_XXTYPE_RENDPN_MASK       (HCD_BIT(0) |           \
+                                                HCD_BIT(1) |           \
+                                                HCD_BIT(2) |           \
+                                                HCD_BIT(3))
+
+/* HOST_RXINTERVAL/HOST_TXINTERVAL */
+/* TODO: Default NAK limit */
+#define MUSB_VAL_HOST_XXINTERVAL_DEFAULT       0x10u
+
+/* HOST_RXCSR */
+#define MUSB_VAL_HOST_RXCSR_RXPKTRDY           HCD_BIT(0)
+#define MUSB_VAL_HOST_RXCSR_FIFOFULL           HCD_BIT(1)
+#define MUSB_VAL_HOST_RXCSR_ERROR              HCD_BIT(2)
+#define MUSB_VAL_HOST_RXCSR_NAKTIMEOUT         HCD_BIT(3)
+#define MUSB_VAL_HOST_RXCSR_FLUSHFIFO          HCD_BIT(4)
+#define MUSB_VAL_HOST_RXCSR_REQPKT             HCD_BIT(5)
+#define MUSB_VAL_HOST_RXCSR_RXSTALL            HCD_BIT(6)
+#define MUSB_VAL_HOST_RXCSR_CLRDATATOG         HCD_BIT(7)
+#define MUSB_VAL_HOST_RXCSR_DATATOG            HCD_BIT(9)
+#define MUSB_VAL_HOST_RXCSR_DATATOGWREN                HCD_BIT(10)
+#define MUSB_VAL_HOST_RXCSR_DISNYET            HCD_BIT(12)
+#define MUSB_VAL_HOST_RXCSR_DMAEN              HCD_BIT(13)
+
+/* HOST_TXCSR */
+#define MUSB_VAL_HOST_TXCSR_TXPKTRDY           HCD_BIT(0)
+#define MUSB_VAL_HOST_TXCSR_FIFONOTEMPTY       HCD_BIT(1)
+#define MUSB_VAL_HOST_TXCSR_ERROR              HCD_BIT(2)
+#define MUSB_VAL_HOST_TXCSR_FLUSHFIFO          HCD_BIT(3)
+#define MUSB_VAL_HOST_TXCSR_SETUPPKT           HCD_BIT(4)
+#define MUSB_VAL_HOST_TXCSR_RXSTALL            HCD_BIT(5)
+#define MUSB_VAL_HOST_TXCSR_CLRDATATOG         HCD_BIT(6)
+#define MUSB_VAL_HOST_TXCSR_NAK_TIMEOUT                HCD_BIT(7)
+#define MUSB_VAL_HOST_TXCSR_DATATOG            HCD_BIT(8)
+#define MUSB_VAL_HOST_TXCSR_DATATOGWREN                HCD_BIT(9)
+#define MUSB_VAL_HOST_TXCSR_DMAMODE            HCD_BIT(10)
+#define MUSB_VAL_HOST_TXCSR_FRCDATATOG         HCD_BIT(11)
+#define MUSB_VAL_HOST_TXCSR_DMAEN              HCD_BIT(12)
+#define MUSB_VAL_HOST_TXCSR_MODE               HCD_BIT(13)
+#define MUSB_VAL_HOST_TXCSR_ISO                        HCD_BIT(14)
+#define MUSB_VAL_HOST_TXCSR_AUTOSET            HCD_BIT(15)
+
+/* RXFIFOADDR/TXFIFOADDR */
+#define MUSB_VAL_XXFIFOADDR_EP0_END            0x08u
+
+/* RXFIFOSZ/TXFIFOSZ */
+#define MUSB_VAL_XXFIFOSZ_16                   0x01u
+#define MUSB_VAL_XXFIFOSZ_32                   0x02u
+#define MUSB_VAL_XXFIFOSZ_64                   0x03u
+#define MUSB_VAL_XXFIFOSZ_128                  0x04u
+#define MUSB_VAL_XXFIFOSZ_256                  0x05u
+#define MUSB_VAL_XXFIFOSZ_512                  0x06u
+#define MUSB_VAL_XXFIFOSZ_1024                 0x07u
+#define MUSB_VAL_XXFIFOSZ_2048                 0x08u
+#define MUSB_VAL_XXFIFOSZ_4096                 0x09u
+
 #endif /* !_MUSB_REGS_H_ */
index 0bb0299703e1505c845e5c53d52dd74fc418b66e..44336fc0049af724f55d30756db03be06e626ff6 100755 (executable)
@@ -62,7 +62,6 @@ typedef unsigned char                         hcd_reg1;
 /*===========================================================================*
  *    USB descriptor types                                                   *
  *===========================================================================*/
-typedef struct usb_ctrlrequest                 hcd_ctrlrequest;
 typedef usb_descriptor_t                       hcd_descriptor;
 typedef usb_device_descriptor_t                        hcd_device_descriptor;
 typedef usb_config_descriptor_t                        hcd_config_descriptor;
@@ -114,13 +113,21 @@ typedef enum {
 }
 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;
+       hcd_driver_state * driver;      /* Specific HCD driver object */
        hcd_thread * thread;
        hcd_lock * lock;
        hcd_urb * urb;
@@ -129,11 +136,13 @@ typedef struct hcd_device_state {
        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;
+
        /* TODO: forcefully align buffer to make things clear? */
        /* Buffer for each device to hold transfered data */
        hcd_reg1 buffer[MAX_WTOTALLENGTH];
@@ -141,12 +150,68 @@ typedef struct hcd_device_state {
 hcd_device_state;
 
 
+/*===========================================================================*
+ *    HCD transfer requests                                                  *
+ *===========================================================================*/
+struct hcd_bulkrequest {
+
+       char * data;
+       int size;
+       int endpoint;
+       unsigned int max_packet_size;
+       hcd_speed speed;
+};
+
+typedef struct usb_ctrlrequest         hcd_ctrlrequest;
+typedef struct hcd_bulkrequest         hcd_bulkrequest;
+
+
+/*===========================================================================*
+ *    HCD event handling                                                     *
+ *===========================================================================*/
+/* Possible USB transfer types */
+typedef enum {
+
+       HCD_TRANSFER_CONTROL            = UE_CONTROL,
+       HCD_TRANSFER_ISOCHRONOUS        = UE_ISOCHRONOUS,
+       HCD_TRANSFER_BULK               = UE_BULK,
+       HCD_TRANSFER_INTERRUPT          = UE_INTERRUPT
+}
+hcd_transfer;
+
+/* Possible USB transfer directions */
+typedef enum {
+
+       HCD_DIRECTION_OUT               = 0,
+       HCD_DIRECTION_IN                = 1,
+       HCD_DIRECTION_UNUSED            = 0xFF
+}
+hcd_direction;
+
+/* Possible asynchronous HCD events */
+typedef enum {
+
+       HCD_EVENT_CONNECTED,
+       HCD_EVENT_DISCONNECTED,
+       HCD_EVENT_ENDPOINT,
+       HCD_EVENT_URB
+}
+hcd_event;
+
+/* EP event constants */
+#define HCD_NO_ENDPOINT                        -1
+#define HCD_ENDPOINT_0                 0
+
+
 /*===========================================================================*
  *    Other definitions                                                      *
  *===========================================================================*/
-#define HCD_NANOSLEEP_SEC(sec)         ((sec)  * 1000000000)
-#define HCD_NANOSLEEP_MSEC(msec)       ((msec) * 1000000)
-#define HCD_NANOSLEEP_USEC(usec)       ((usec) * 1000)
+#define HCD_MILI                       1000
+#define HCD_MICRO                      1000000
+#define HCD_NANO                       1000000000
+#define HCD_NANOSLEEP_SEC(sec)         ((sec)  * HCD_NANO)
+#define HCD_NANOSLEEP_MSEC(msec)       ((msec) * HCD_MICRO)
+#define HCD_NANOSLEEP_USEC(usec)       ((usec) * HCD_MILI)
 
 /* Default USB communication parameters */
 #define HCD_DEFAULT_EP         0x00
@@ -184,6 +249,9 @@ int hcd_os_clkconf(unsigned long, unsigned long, unsigned long);
 /* Release clocking */
 int hcd_os_clkconf_release(void);
 
+/* OS's sleep wrapper */
+void hcd_os_nanosleep(int);
+
 
 /*===========================================================================*
  *    Device handling calls                                                  *
@@ -195,7 +263,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 *);
+void hcd_device_wait(hcd_device_state *, hcd_event, int);
 
 /* Unlocks device thread halted by 'hcd_device_wait' */
 void hcd_device_continue(hcd_device_state *);
@@ -210,5 +278,8 @@ int hcd_buffer_to_tree(hcd_reg1 *, int, hcd_configuration *);
 /* Frees descriptor tree */
 void hcd_tree_cleanup(hcd_configuration *);
 
+/* Find EP in a tree */
+hcd_endpoint * hcd_tree_find_ep(hcd_configuration *, int);
+
 
 #endif /* !_HCD_COMMON_H_ */
index 20ee3babead6dee6ca2a81f7f5504525a0a83564..c59d6e62f523299eebaa05484e8c47836936c933 100755 (executable)
 #include <usb/hcd_common.h>
 
 
-/*===========================================================================*
- *    HCD event handling types                                               *
- *===========================================================================*/
-/* Possible HCD events */
-typedef enum {
-
-       HCD_EVENT_CONNECTED,
-       HCD_EVENT_DISCONNECTED,
-       HCD_EVENT_ENDPOINT
-}
-hcd_event;
-
-/* Possible HCD sub-events */
-typedef enum {
-
-       HCD_SUBEVENT_NONE,
-       HCD_SUBEVENT_EP0,
-}
-hcd_subevent;
-
-
 /*===========================================================================*
  *    HCD additional defines                                                 *
  *===========================================================================*/
+/* Can be returned by 'read_data' to indicate error */
 #define HCD_READ_ERR -1
 
 
@@ -43,22 +23,26 @@ hcd_subevent;
  *===========================================================================*/
 struct hcd_driver_state {
        /* Standard USB controller procedures */
-       void            (*setup_device)         (void *, hcd_reg1, hcd_reg1);
-       void            (*reset_device)         (void *);
-       void            (*setup_stage)          (void *, hcd_ctrlrequest *);
-       void            (*in_data_stage)        (void *);
-       void            (*out_data_stage)       (void *);
-       void            (*in_status_stage)      (void *);
-       void            (*out_status_stage)     (void *);
-       int             (*read_data)            (void *, hcd_reg1 *, int);
-       int             (*check_error)          (void *);
+       void    (*setup_device)         (void *, hcd_reg1, hcd_reg1);
+       int     (*reset_device)         (void *, hcd_speed *);
+       void    (*setup_stage)          (void *, hcd_ctrlrequest *);
+       void    (*bulk_in_stage)        (void *, hcd_bulkrequest *);
+       void    (*bulk_out_stage)       (void *, hcd_bulkrequest *);
+       void    (*in_data_stage)        (void *);
+       void    (*out_data_stage)       (void *);
+       void    (*in_status_stage)      (void *);
+       void    (*out_status_stage)     (void *);
+       int     (*read_data)            (void *, hcd_reg1 *, int);
+       int     (*check_error)          (void *, hcd_transfer, hcd_direction);
 
        /* Controller's private data (like mapped registers) */
        void *          private_data;
 
        /* Current state to be handled by driver */
-       hcd_event       event;
-       hcd_subevent    subevent;
+       hcd_event       current_event;
+       int             current_endpoint;
+       hcd_event       expected_event;
+       int             expected_endpoint;
 };