Pinscape Controller version 1 fork. This is a fork to allow for ongoing bug fixes to the original controller version, from before the major changes for the expansion board project.

Dependencies:   FastIO FastPWM SimpleDMA mbed

Fork of Pinscape_Controller by Mike R

Files at this revision

API Documentation at this revision

Comitter:
mjr
Date:
Thu Feb 11 18:31:05 2016 +0000
Parent:
52:63f0a9b45f0c
Child:
54:af65c577a563
Commit message:
Full reversion to v33 baseline for all USB code - new starting point to find USB compatibility regression

Changed in this revision

USBDevice/USBDevice/USBDevice.cpp Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBDevice/USBEndpoints.h Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBDevice/USBHAL.h Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBDevice/USBHAL_KL25Z.cpp Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBHID/USBHID.cpp Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBHID/USBHID.h Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBHID/USBHID_Types.h Show annotated file Show diff for this revision Revisions of this file
--- a/USBDevice/USBDevice/USBDevice.cpp	Thu Feb 11 18:12:52 2016 +0000
+++ b/USBDevice/USBDevice/USBDevice.cpp	Thu Feb 11 18:31:05 2016 +0000
@@ -23,11 +23,6 @@
 #include "USBDescriptor.h"
 
 //#define DEBUG
-#ifdef DEBUG
-#define printd(fmt, ...)  printf(fmt, __VA_ARGS__)
-#else
-#define printd(fmt, ...)
-#endif
 
 /* Device status */
 #define DEVICE_STATUS_SELF_POWERED  (1U<<0)
@@ -48,7 +43,9 @@
 bool USBDevice::requestGetDescriptor(void)
 {
     bool success = false;
-    printd("get descr: type: %d\r\n", DESCRIPTOR_TYPE(transfer.setup.wValue));
+#ifdef DEBUG
+    printf("get descr: type: %d\r\n", DESCRIPTOR_TYPE(transfer.setup.wValue));
+#endif
     switch (DESCRIPTOR_TYPE(transfer.setup.wValue))
     {
         case DEVICE_DESCRIPTOR:
@@ -57,7 +54,9 @@
                 if ((deviceDesc()[0] == DEVICE_DESCRIPTOR_LENGTH) \
                     && (deviceDesc()[1] == DEVICE_DESCRIPTOR))
                 {
-                    printd("device descr\r\n");
+#ifdef DEBUG
+                    printf("device descr\r\n");
+#endif
                     transfer.remaining = DEVICE_DESCRIPTOR_LENGTH;
                     transfer.ptr = deviceDesc();
                     transfer.direction = DEVICE_TO_HOST;
@@ -71,8 +70,9 @@
                 if ((configurationDesc()[0] == CONFIGURATION_DESCRIPTOR_LENGTH) \
                     && (configurationDesc()[1] == CONFIGURATION_DESCRIPTOR))
                 {
-                    printd("conf descr request\r\n");
-
+#ifdef DEBUG
+                    printf("conf descr request\r\n");
+#endif
                     /* Get wTotalLength */
                     transfer.remaining = configurationDesc()[2] \
                         | (configurationDesc()[3] << 8);
@@ -84,46 +84,60 @@
             }
             break;
         case STRING_DESCRIPTOR:
-            printd("str descriptor\r\n");
+#ifdef DEBUG
+            printf("str descriptor\r\n");
+#endif
             switch (DESCRIPTOR_INDEX(transfer.setup.wValue))
             {
                             case STRING_OFFSET_LANGID:
-                                printd("1\r\n");
+#ifdef DEBUG
+                                printf("1\r\n");
+#endif
                                 transfer.remaining = stringLangidDesc()[0];
                                 transfer.ptr = stringLangidDesc();
                                 transfer.direction = DEVICE_TO_HOST;
                                 success = true;
                                 break;
                             case STRING_OFFSET_IMANUFACTURER:
-                                printd("2\r\n");
+#ifdef DEBUG
+                                printf("2\r\n");
+#endif
                                 transfer.remaining =  stringImanufacturerDesc()[0];
                                 transfer.ptr = stringImanufacturerDesc();
                                 transfer.direction = DEVICE_TO_HOST;
                                 success = true;
                                 break;
                             case STRING_OFFSET_IPRODUCT:
-                                printd("3\r\n");
+#ifdef DEBUG
+                                printf("3\r\n");
+#endif
                                 transfer.remaining = stringIproductDesc()[0];
                                 transfer.ptr = stringIproductDesc();
                                 transfer.direction = DEVICE_TO_HOST;
                                 success = true;
                                 break;
                             case STRING_OFFSET_ISERIAL:
-                                printd("4\r\n");
+#ifdef DEBUG
+                                printf("4\r\n");
+#endif
                                 transfer.remaining = stringIserialDesc()[0];
                                 transfer.ptr = stringIserialDesc();
                                 transfer.direction = DEVICE_TO_HOST;
                                 success = true;
                                 break;
                             case STRING_OFFSET_ICONFIGURATION:
-                                printd("5\r\n");
+#ifdef DEBUG
+                                printf("5\r\n");
+#endif
                                 transfer.remaining = stringIConfigurationDesc()[0];
                                 transfer.ptr = stringIConfigurationDesc();
                                 transfer.direction = DEVICE_TO_HOST;
                                 success = true;
                                 break;
                             case STRING_OFFSET_IINTERFACE:
-                                printd("6\r\n");
+#ifdef DEBUG
+                                printf("6\r\n");
+#endif
                                 transfer.remaining = stringIinterfaceDesc()[0];
                                 transfer.ptr = stringIinterfaceDesc();
                                 transfer.direction = DEVICE_TO_HOST;
@@ -131,18 +145,20 @@
                                 break;
             }
             break;
-            
         case INTERFACE_DESCRIPTOR:
-            printd("interface descr\r\n");
-            break;
-
+#ifdef DEBUG
+            printf("interface descr\r\n");
+#endif
         case ENDPOINT_DESCRIPTOR:
+#ifdef DEBUG
+            printf("endpoint descr\r\n");
+#endif
             /* TODO: Support is optional, not implemented here */
-            printd("endpoint descr\r\n");
             break;
-
         default:
-            printd("ERROR - unknown descriptor type in GET DESCRIPTOR\r\n");
+#ifdef DEBUG
+            printf("ERROR\r\n");
+#endif
             break;
     }
 
@@ -176,18 +192,18 @@
          * We seem to have a pending device-to-host transfer.  The host must have
          * sent a new control request without waiting for us to finish processing
          * the previous one.  This appears to happen when we're connected to certain 
-         * USB 3.0 host chip sets.  Do a zero-length send to tell the host we're not
+         * USB 3.0 host chip set. Do a zeor-length send to tell the host we're not
          * ready for the new request - that'll make it resend - and then just
          * pretend we were successful here so that the pending transfer can finish.
          */
         uint8_t buf[1] = { 0 };
         EP0write(buf, 0);
                   
-        /* execute our pending transfer */
+        /* execute our pending ttransfer */
         controlIn();
 
-        /* indicate failure so that the host retries */
-        return false;//$$$ was return true
+        /* indicate success */
+        return false;
  #else
         /* for other platforms, count on the HAL to handle this case */
         return false;
@@ -257,7 +273,6 @@
         EP0readStage();
 
         /* Completed */
-        //$$$ transfer.direction = HOST_TO_DEVICE;
         return true;
     }
 
@@ -280,12 +295,7 @@
     /* Update transfer */
     transfer.ptr += packetSize;
     transfer.remaining -= packetSize;
-    
-    /* are we done? */
-    //$$$ if (transfer.remaining == 0)
-    //$$$    transfer.direction = HOST_TO_DEVICE;
 
-    /* success */
     return true;
 }
 
@@ -511,7 +521,7 @@
                  success = requestSetFeature();
                  break;
              case SET_ADDRESS:
-                 success = requestSetAddress();
+                success = requestSetAddress();
                  break;
              case GET_DESCRIPTOR:
                  success = requestGetDescriptor();
@@ -553,18 +563,19 @@
     decodeSetupPacket(buffer, &transfer.setup);
     transfer.ptr = NULL;
     transfer.remaining = 0;
-    transfer.direction = HOST_TO_DEVICE;
+    transfer.direction = 0;
     transfer.zlp = false;
     transfer.notify = false;
 
-    printd("dataTransferDirection: %d\r\nType: %d\r\nRecipient: %d\r\nbRequest: %d\r\nwValue: %d\r\nwIndex: %d\r\nwLength: %d\r\n",
-        transfer.setup.bmRequestType.dataTransferDirection,
-        transfer.setup.bmRequestType.Type,
-        transfer.setup.bmRequestType.Recipient,
-        transfer.setup.bRequest,
-        transfer.setup.wValue,
-        transfer.setup.wIndex,
-        transfer.setup.wLength);
+#ifdef DEBUG
+    printf("dataTransferDirection: %d\r\nType: %d\r\nRecipient: %d\r\nbRequest: %d\r\nwValue: %d\r\nwIndex: %d\r\nwLength: %d\r\n",transfer.setup.bmRequestType.dataTransferDirection,
+                                                                                                                                   transfer.setup.bmRequestType.Type,
+                                                                                                                                   transfer.setup.bmRequestType.Recipient,
+                                                                                                                                   transfer.setup.bRequest,
+                                                                                                                                   transfer.setup.wValue,
+                                                                                                                                   transfer.setup.wIndex,
+                                                                                                                                   transfer.setup.wLength);
+#endif
 
     /* Class / vendor specific */
     success = USBCallback_request();
@@ -574,13 +585,15 @@
         /* Standard requests */
         if (!requestSetup())
         {
-            printd("requestSetup() failed: type=%d, req=%d\r\n", (int)transfer.setup.bmRequestType.Type, (int)transfer.setup.bRequest);
+#ifdef DEBUG
+            printf("fail!!!!\r\n");
+#endif
             return false;
         }
     }
 
     /* Check transfer size and direction */
-    if (transfer.setup.wLength > 0)
+    if (transfer.setup.wLength>0)
     {
         if (transfer.setup.bmRequestType.dataTransferDirection \
             == DEVICE_TO_HOST)
@@ -588,7 +601,6 @@
             /* IN data stage is required */
             if (transfer.direction != DEVICE_TO_HOST)
             {
-                printd("controlSetup transfer direction wrong 1\r\n");
                 return false;
             }
 
@@ -605,15 +617,12 @@
             /* OUT data stage is required */
             if (transfer.direction != HOST_TO_DEVICE)
             {
-                printd("controlSetup transfer direction wrong 2: type=%d, req=%d\r\n", (int)transfer.setup.bmRequestType.Type, (int)transfer.setup.bRequest);
                 return false;
             }
 
             /* Transfer must be equal to the size requested by the host */
             if (transfer.remaining != transfer.setup.wLength)
             {
-                printd("controlSetup remaining length wrong: return len=%d, type=%d, req=%d, wvalue=%d, windex=%x, wlength=%d\r\n", 
-                    transfer.remaining, transfer.setup.bmRequestType.Type, transfer.setup.bRequest, transfer.setup.wValue, transfer.setup.wIndex, transfer.setup.wLength);
                 return false;
             }
         }
@@ -623,14 +632,12 @@
         /* No data stage; transfer size must be zero */
         if (transfer.remaining != 0)
         {
-            printd("controlSetup remaining length must be zero: return len=%d, type=%d, req=%d, wvalue=%d, windex=%x, wlength=%d\r\n", 
-               (int)transfer.remaining, (int)transfer.setup.bmRequestType.Type, (int)transfer.setup.bRequest, (int)transfer.setup.wValue, (int)transfer.setup.wIndex, (int)transfer.setup.wLength);
             return false;
         }
     }
 
     /* Data or status stage if applicable */
-    if (transfer.setup.wLength > 0)
+    if (transfer.setup.wLength>0)
     {
         if (transfer.setup.bmRequestType.dataTransferDirection \
             == DEVICE_TO_HOST)
@@ -683,6 +690,8 @@
         /* Protocol stall */
         EP0stall();
     }
+
+    /* Return true if an OUT data stage is expected */
 }
 
 void USBDevice::EP0out(void)
@@ -697,6 +706,9 @@
 
 void USBDevice::EP0in(void)
 {
+#ifdef DEBUG
+    printf("EP0IN\r\n");
+#endif
     /* Endpoint 0 IN data event */
     if (!controlIn())
     {
@@ -717,8 +729,8 @@
     USBHAL::connect();
 
     if (blocking) {
-        /* Block until configured */
-        while (!configured()) { }
+        /* Block if not configured */
+        while (!configured());
     }
 }
 
@@ -783,12 +795,12 @@
     do {
         if (ptr[1] /* bDescriptorType */ == descriptorType)
         {
-//$$$            // Found - if the index has reached zero, it's the one we're
-//$$$            // looking for; if not, just decrement the index and keep looking.
-//$$$            if (idx == 0)
+            // Found - if the index has reached zero, it's the one we're
+            // looking for; if not, just decrement the index and keep looking.
+            if (idx == 0)
                 return ptr;
-//$$$            else
-//$$$                --idx;
+            else
+                --idx;
         }
 
         /* Skip to next descriptor */
@@ -897,10 +909,10 @@
     if(!configured()) {
         return false;
     }
-    
+
     /* Send report */
     result = endpointWrite(endpoint, buffer, size);
-    
+
     if (result != EP_PENDING)
     {
         return false;
@@ -918,6 +930,9 @@
     return (result == EP_COMPLETED);
 }
 
+
+
+
 bool USBDevice::readEP(uint8_t endpoint, uint8_t * buffer, uint32_t * size, uint32_t maxSize)
 {
     EP_STATUS result;
--- a/USBDevice/USBDevice/USBEndpoints.h	Thu Feb 11 18:12:52 2016 +0000
+++ b/USBDevice/USBDevice/USBEndpoints.h	Thu Feb 11 18:31:05 2016 +0000
@@ -33,7 +33,7 @@
     EP_COMPLETED,   /* Transfer completed */
     EP_PENDING,     /* Transfer in progress */
     EP_INVALID,     /* Invalid parameter */
-    EP_STALLED      /* Endpoint stalled */
+    EP_STALLED,     /* Endpoint stalled */
 } EP_STATUS;
 
 /* Include configuration for specific target */
--- a/USBDevice/USBDevice/USBHAL.h	Thu Feb 11 18:12:52 2016 +0000
+++ b/USBDevice/USBDevice/USBHAL.h	Thu Feb 11 18:31:05 2016 +0000
@@ -58,7 +58,7 @@
     bool realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options);
     bool getEndpointStallState(unsigned char endpoint);
     uint32_t endpointReadcore(uint8_t endpoint, uint8_t *buffer);
-    
+
 protected:
     virtual void busReset(void){};
     virtual void EP0setupCallback(void){};
@@ -112,11 +112,6 @@
         bool (USBHAL::*epCallback[10 - 2])(void);
 #elif defined(TARGET_STM32F4XX)
         bool (USBHAL::*epCallback[8 - 2])(void);
-#elif defined(TARGET_KL25Z)
-        bool (USBHAL::*epCallback[32])(void);
-        bool EP0_IN_callback();
-        bool EP0_OUT_callback();
-        void EP0_SETUP_callback();
 #else
         bool (USBHAL::*epCallback[32 - 2])(void);
 #endif
--- a/USBDevice/USBDevice/USBHAL_KL25Z.cpp	Thu Feb 11 18:12:52 2016 +0000
+++ b/USBDevice/USBDevice/USBHAL_KL25Z.cpp	Thu Feb 11 18:31:05 2016 +0000
@@ -18,90 +18,42 @@
 
 #if defined(TARGET_KL25Z) | defined(TARGET_KL46Z) | defined(TARGET_K20D5M) | defined(TARGET_K64F)
 
-//#define DEBUG
-#ifdef DEBUG
-#define printd(fmt, ...) printf(fmt, __VA_ARGS__)
-#else
-#define printd(fmt, ...)
-#endif
-
-
 #include "USBHAL.h"
 
-// Critical section controls.  This module uses a bunch of static variables,
-// and much of the code that accesses the statics can be called from either
-// normal application context or IRQ context.  Whenever a shared variable is
-// accessed from code that can run in an application context, we have to
-// protect against interrupts by entering a critical section.  These macros
-// enable and disable the USB IRQ if we're running in application context.
-// (They do nothing if we're already in interrupt context, because the
-// hardware interrupt controller won't generated another of the same IRQ
-// that we're already handling.  We could still be interrupted by a different,
-// higher-priority IRQ, but our shared variables are only shared within this
-// module, so they won't be affected by other interrupt handlers.)
-static int inIRQ;
-#define ENTER_CRITICAL_SECTION \
-    if (!inIRQ) \
-        NVIC_DisableIRQ(USB0_IRQn);
-#define EXIT_CRITICAL_SECTION \
-    if (!inIRQ) \
-        NVIC_EnableIRQ(USB0_IRQn);
+USBHAL * USBHAL::instance;
 
-// static singleton instance pointer
-USBHAL * USBHAL::instance;
+static volatile int epComplete = 0;
 
 // Convert physical endpoint number to register bit
 #define EP(endpoint) (1<<(endpoint))
 
-// Convert physical endpoint number to logical endpoint number.
-// Each logical endpoint has two physical endpoints, one RX and 
-// one TX.  The physical endpoints are numbered in RX,TX pairs,
-// so the logical endpoint number is simply the physical endpoint
-// number divided by 2 (discarding the remainder).
+// Convert physical to logical
 #define PHY_TO_LOG(endpoint)    ((endpoint)>>1)
 
-// Get a physical endpoint's direction.  IN and OUT are from
-// the host's perspective, so from our perspective on the device,
-// IN == TX and OUT == RX.  The physical endpoints are in RX,TX
-// pairs, so the OUT/RX is the even numbered element of a pair
-// and the IN/TX is the odd numbered element.
+// Get endpoint direction
 #define IN_EP(endpoint)     ((endpoint) & 1U ? true : false)
 #define OUT_EP(endpoint)    ((endpoint) & 1U ? false : true)
 
-// BDT status flags, defined by the SIE hardware.  These are
-// bits packed into the 'info' byte of a BDT entry.
-#define BD_OWN_MASK        (1<<7)       // OWN - hardware SIE owns the BDT (TX/RX in progress)
-#define BD_DATA01_MASK     (1<<6)       // DATA01 - DATA0/DATA1 bit for current TX/RX on endpoint
-#define BD_KEEP_MASK       (1<<5)       // KEEP - hardware keeps BDT ownership after token completes
-#define BD_NINC_MASK       (1<<4)       // NO INCREMENT - buffer location is a FIFO, so use same address for all bytes
-#define BD_DTS_MASK        (1<<3)       // DATA TOGGLE SENSING - hardware SIE checks for DATA0/DATA1 match during RX/TX
-#define BD_STALL_MASK      (1<<2)       // STALL - SIE issues STALL handshake in reply to any host access to endpoint
+#define BD_OWN_MASK        (1<<7)
+#define BD_DATA01_MASK     (1<<6)
+#define BD_KEEP_MASK       (1<<5)
+#define BD_NINC_MASK       (1<<4)
+#define BD_DTS_MASK        (1<<3)
+#define BD_STALL_MASK      (1<<2)
 
-// Endpoint direction
 #define TX    1
 #define RX    0
-
-// Buffer parity.  The hardware has a double-buffering scheme where each
-// physical endpoint has two associated BDT entries, labeled EVEN and ODD.
-// We disable the double buffering, so only the EVEN buffers are used in
-// this implementation.
-#define EVEN  0
-#define ODD   1
+#define ODD   0
+#define EVEN  1
+// this macro waits a physical endpoint number
+#define EP_BDT_IDX(ep, dir, odd) (((ep * 4) + (2 * dir) + (1 *  odd)))
 
-// Get the BDT index for a given logical endpoint, direction, and buffer parity
-#define EP_BDT_IDX(logep, dir, odd) (((logep) * 4) + (2 * (dir)) + (1 *  (odd)))
-
-// Get the BDT index for a given physical endpoint and buffer parity
-#define PEP_BDT_IDX(phyep, odd)  (((phyep) * 2) + (1 * (odd)))
-
-// Token types reported in the BDT 'info' flags.  
-#define TOK_PID(idx)   ((bdt[idx].info >> 2) & 0x0F)
 #define SETUP_TOKEN    0x0D
 #define IN_TOKEN       0x09
 #define OUT_TOKEN      0x01
+#define TOK_PID(idx)   ((bdt[idx].info >> 2) & 0x0F)
 
-// Buffer Descriptor Table (BDT) entry.  This is the hardware-defined
-// memory structure for the shared memory block controlling an endpoint.
+// for each endpt: 8 bytes
 typedef struct BDT {
     uint8_t   info;       // BD[0:7]
     uint8_t   dummy;      // RSVD: BD[8:15]
@@ -109,51 +61,24 @@
     uint32_t  address;    // Addr
 } BDT;
 
-// There are:
-//    * 16 bidirectional logical endpoints -> 32 physical endpoints
-//    * 2 BDT entries per endpoint (EVEN/ODD) -> 64 BDT entries
-__attribute__((__aligned__(512))) BDT bdt[NUMBER_OF_PHYSICAL_ENDPOINTS * 2];
-
-// Transfer buffers.  We allocate the transfer buffers and point the
-// SIE hardware to them via the BDT.  We disable hardware SIE's
-// double-buffering (EVEN/ODD) scheme, so we only allocate one buffer
-// per physical endpoint.
-uint8_t *endpoint_buffer[NUMBER_OF_PHYSICAL_ENDPOINTS];
 
-// Allocated size of each endpoint buffer
-size_t epMaxPacket[NUMBER_OF_PHYSICAL_ENDPOINTS];
+// there are:
+//    * 16 bidirectionnal endpt -> 32 physical endpt
+//    * as there are ODD and EVEN buffer -> 32*2 bdt
+__attribute__((__aligned__(512))) BDT bdt[NUMBER_OF_PHYSICAL_ENDPOINTS * 2];
+uint8_t * endpoint_buffer[(NUMBER_OF_PHYSICAL_ENDPOINTS - 2) * 2];
+uint8_t * endpoint_buffer_iso[2*2];
 
-// SET ADDRESS mode tracking.  The address assignment has to be done in a
-// specific order and with specific timing defined by the USB setup protocol 
-// standards.  To get the sequencing right, we set a flag when we get the
-// address message, and then set the address in the SIE when we're at the 
-// right subsequent packet step in the protocol exchange.  These variables
-// are just a place to stash the information between the time we receive the
-// data and the time we're ready to update the SIE register.
 static uint8_t set_addr = 0;
 static uint8_t addr = 0;
 
-// Endpoint DATA0/DATA1 bits, packed as a bit vector.  Each endpoint's
-// bit is at (1 << endpoint number).  These track the current bit value
-// on the endpoint.  For TX endpoints, this is the bit for the LAST
-// packet we sent (so the next packet will be the inverse).  For RX
-// endpoints, this is the bit value we expect for the NEXT packet.
-// (Yes, it's inconsistent.)
 static uint32_t Data1  = 0x55555555;
 
-// Endpoint read/write completion flags, packed as a bit vector.  Each 
-// endpoint's bit is at (1 << endpoint number).  A 1 bit signifies that
-// the last read or write has completed (and hasn't had its result 
-// consumed yet).
-static volatile int epComplete = 0;
-
-static uint32_t frameNumber() 
-{
+static uint32_t frameNumber() {
     return((USB0->FRMNUML | (USB0->FRMNUMH << 8)) & 0x07FF);
 }
 
-uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) 
-{
+uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
     return 0;
 }
 
@@ -165,38 +90,37 @@
     MPU->CESR=0;
 #endif
     // fill in callback array
-    epCallback[0] = &USBHAL::EP0_OUT_callback;
-    epCallback[1] = &USBHAL::EP0_IN_callback;
-    epCallback[2] = &USBHAL::EP1_OUT_callback;
-    epCallback[3] = &USBHAL::EP1_IN_callback;
-    epCallback[4] = &USBHAL::EP2_OUT_callback;
-    epCallback[5] = &USBHAL::EP2_IN_callback;
-    epCallback[6] = &USBHAL::EP3_OUT_callback;
-    epCallback[7] = &USBHAL::EP3_IN_callback;
-    epCallback[8] = &USBHAL::EP4_OUT_callback;
-    epCallback[9] = &USBHAL::EP4_IN_callback;
-    epCallback[10] = &USBHAL::EP5_OUT_callback;
-    epCallback[11] = &USBHAL::EP5_IN_callback;
-    epCallback[12] = &USBHAL::EP6_OUT_callback;
-    epCallback[13] = &USBHAL::EP6_IN_callback;
-    epCallback[14] = &USBHAL::EP7_OUT_callback;
-    epCallback[15] = &USBHAL::EP7_IN_callback;
-    epCallback[16] = &USBHAL::EP8_OUT_callback;
-    epCallback[17] = &USBHAL::EP8_IN_callback;
-    epCallback[18] = &USBHAL::EP9_OUT_callback;
-    epCallback[19] = &USBHAL::EP9_IN_callback;
-    epCallback[20] = &USBHAL::EP10_OUT_callback;
-    epCallback[21] = &USBHAL::EP10_IN_callback;
-    epCallback[22] = &USBHAL::EP11_OUT_callback;
-    epCallback[23] = &USBHAL::EP11_IN_callback;
-    epCallback[24] = &USBHAL::EP12_OUT_callback;
-    epCallback[25] = &USBHAL::EP12_IN_callback;
-    epCallback[26] = &USBHAL::EP13_OUT_callback;
-    epCallback[27] = &USBHAL::EP13_IN_callback;
-    epCallback[28] = &USBHAL::EP14_OUT_callback;
-    epCallback[29] = &USBHAL::EP14_IN_callback;
-    epCallback[30] = &USBHAL::EP15_OUT_callback;
-    epCallback[31] = &USBHAL::EP15_IN_callback;
+    epCallback[0] = &USBHAL::EP1_OUT_callback;
+    epCallback[1] = &USBHAL::EP1_IN_callback;
+    epCallback[2] = &USBHAL::EP2_OUT_callback;
+    epCallback[3] = &USBHAL::EP2_IN_callback;
+    epCallback[4] = &USBHAL::EP3_OUT_callback;
+    epCallback[5] = &USBHAL::EP3_IN_callback;
+    epCallback[6] = &USBHAL::EP4_OUT_callback;
+    epCallback[7] = &USBHAL::EP4_IN_callback;
+    epCallback[8] = &USBHAL::EP5_OUT_callback;
+    epCallback[9] = &USBHAL::EP5_IN_callback;
+    epCallback[10] = &USBHAL::EP6_OUT_callback;
+    epCallback[11] = &USBHAL::EP6_IN_callback;
+    epCallback[12] = &USBHAL::EP7_OUT_callback;
+    epCallback[13] = &USBHAL::EP7_IN_callback;
+    epCallback[14] = &USBHAL::EP8_OUT_callback;
+    epCallback[15] = &USBHAL::EP8_IN_callback;
+    epCallback[16] = &USBHAL::EP9_OUT_callback;
+    epCallback[17] = &USBHAL::EP9_IN_callback;
+    epCallback[18] = &USBHAL::EP10_OUT_callback;
+    epCallback[19] = &USBHAL::EP10_IN_callback;
+    epCallback[20] = &USBHAL::EP11_OUT_callback;
+    epCallback[21] = &USBHAL::EP11_IN_callback;
+    epCallback[22] = &USBHAL::EP12_OUT_callback;
+    epCallback[23] = &USBHAL::EP12_IN_callback;
+    epCallback[24] = &USBHAL::EP13_OUT_callback;
+    epCallback[25] = &USBHAL::EP13_IN_callback;
+    epCallback[26] = &USBHAL::EP14_OUT_callback;
+    epCallback[27] = &USBHAL::EP14_IN_callback;
+    epCallback[28] = &USBHAL::EP15_OUT_callback;
+    epCallback[29] = &USBHAL::EP15_IN_callback;
+
 
     // choose usb src as PLL
     SIM->SOPT2 |= (SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK);
@@ -236,51 +160,41 @@
     USB0->USBTRC0 |= 0x40;
 }
 
-USBHAL::~USBHAL(void) 
-{ 
-}
+USBHAL::~USBHAL(void) { }
 
-void USBHAL::connect(void) 
-{
+void USBHAL::connect(void) {
     // enable USB
     USB0->CTL |= USB_CTL_USBENSOFEN_MASK;
-
     // Pull up enable
     USB0->CONTROL |= USB_CONTROL_DPPULLUPNONOTG_MASK;
 }
 
-void USBHAL::disconnect(void) 
-{
+void USBHAL::disconnect(void) {
     // disable USB
     USB0->CTL &= ~USB_CTL_USBENSOFEN_MASK;
-
     // Pull up disable
     USB0->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK;
 
     //Free buffers if required:
-    for (int i = 0 ; i < NUMBER_OF_PHYSICAL_ENDPOINTS ; i++) 
-    {
-        if (endpoint_buffer[i] != NULL)
-        {
-            free(endpoint_buffer[i]);
-            endpoint_buffer[i] = NULL;
-            epMaxPacket[i] = 0;
-        }
+    for (int i = 0; i<(NUMBER_OF_PHYSICAL_ENDPOINTS - 2) * 2; i++) {
+        free(endpoint_buffer[i]);
+        endpoint_buffer[i] = NULL;
     }
+    free(endpoint_buffer_iso[2]);
+    endpoint_buffer_iso[2] = NULL;
+    free(endpoint_buffer_iso[0]);
+    endpoint_buffer_iso[0] = NULL;
 }
 
-void USBHAL::configureDevice(void) 
-{
+void USBHAL::configureDevice(void) {
     // not needed
 }
 
-void USBHAL::unconfigureDevice(void) 
-{
+void USBHAL::unconfigureDevice(void) {
     // not needed
 }
 
-void USBHAL::setAddress(uint8_t address) 
-{
+void USBHAL::setAddress(uint8_t address) {
     // we don't set the address now otherwise the usb controller does not ack
     // we set a flag instead
     // see usbisr when an IN token is received
@@ -288,381 +202,250 @@
     addr = address;
  }
 
-bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) 
-{
-    // validate the endpoint number
-    if (endpoint >= NUMBER_OF_PHYSICAL_ENDPOINTS)
+bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) {
+    uint32_t handshake_flag = 0;
+    uint8_t * buf;
+
+    if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) {
         return false;
+    }
 
-    // get the logical endpoint
     uint32_t log_endpoint = PHY_TO_LOG(endpoint);
-    
-    // Constrain the requested packet size to the maximum for the endpoint type.
-    // Full Speed USB allows up to 1023 bytes for isochronous endpoints and 64 bytes
-    // for bulk and interrupt endpoints.
-    uint32_t realMaxPacket = ((flags & ISOCHRONOUS) ? 1023 : 64);
-    if (maxPacket > realMaxPacket)
-        maxPacket = realMaxPacket;
-
-    // Use the HANDSHAKE flag for non-isochronous endpoints.  Don't use handshaking
-    // for an iso endpoint, since this type of endpoint is for applications like
-    // audio and video streaming where it's preferable to ignore lost packets and
-    // just carry on with the latest data.
-    uint32_t ctlFlags = 0;
-    if (!(flags & ISOCHRONOUS))
-        ctlFlags |= USB_ENDPT_EPHSHK_MASK;
-        
-    // figure the RX/TX based on the endpoint direction
-    ctlFlags |= (IN_EP(endpoint) ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK);
 
-    ENTER_CRITICAL_SECTION
-    {
-        // if we don't already have a buffer that's big enough, allocate a new one
-        uint8_t *buf = endpoint_buffer[endpoint];
-        if (buf == 0 || maxPacket > epMaxPacket[endpoint])
-        {
-            // free any existing buffer
-            if (buf != 0)
-                free(buf);
-                
-            // allocate a new one
-            epMaxPacket[endpoint] = maxPacket;
-            endpoint_buffer[endpoint] = buf = (uint8_t *)malloc(maxPacket);
+    if ((flags & ISOCHRONOUS) == 0) {
+        handshake_flag = USB_ENDPT_EPHSHK_MASK;
+        if (IN_EP(endpoint)) {
+            if (endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD)] == NULL)
+                endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD)] = (uint8_t *) malloc (64*2);
+            buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD)][0];
+        } else {
+            if (endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD)] == NULL)
+                endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD)] = (uint8_t *) malloc (64*2);
+            buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD)][0];
+        }
+    } else {
+        if (IN_EP(endpoint)) {
+            if (endpoint_buffer_iso[2] == NULL)
+                endpoint_buffer_iso[2] = (uint8_t *) malloc (1023*2);
+            buf = &endpoint_buffer_iso[2][0];
+        } else {
+            if (endpoint_buffer_iso[0] == NULL)
+                endpoint_buffer_iso[0] = (uint8_t *) malloc (1023*2);
+            buf = &endpoint_buffer_iso[0][0];
         }
-        
-        // Set up the BDT entry.  Note that we disable the hardware double-buffering
-        // scheme, so we only use the EVEN buffer for the endpoint.
-        int idx = PEP_BDT_IDX(endpoint, EVEN);
-        bdt[idx].info = 0;
-        bdt[idx].address = (uint32_t)buf;
-        
-        // Set the endpoint flags.  Note that these bits are additive, since the
-        // endpoint register represents the logical endpoint, which is the combination
-        // of the physical IN and OUT endpoints.
-        USB0->ENDPOINT[log_endpoint].ENDPT |= ctlFlags;
-    
-        // If this is an OUT endpoint, queue the first read on the endpoint by
-        // handing ownership of the BDT to the SIE.
-        if (OUT_EP(endpoint))
-        {
-            bdt[idx].byte_count = maxPacket;
-            bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK;
-        }
-    
-        // Set DATA1 on the endpoint.  For RX endpoints, we just queued up our first
-        // read, which will always be a DATA0 packet, so the next read will use DATA1.
-        // For TX endpoints, we always flip the bit *before* sending the packet, so
-        // (counterintuitively) we need to set the DATA1 bit now to send DATA0 in the
-        // next packet.  So in either case, we want DATA1 initially.
-        Data1 |= (1 << endpoint);
+    }
+
+    // IN endpt -> device to host (TX)
+    if (IN_EP(endpoint)) {
+        USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag |        // ep handshaking (not if iso endpoint)
+                                              USB_ENDPT_EPTXEN_MASK;  // en TX (IN) tran
+        bdt[EP_BDT_IDX(log_endpoint, TX, ODD )].address = (uint32_t) buf;
+        bdt[EP_BDT_IDX(log_endpoint, TX, EVEN)].address = 0;
     }
-    EXIT_CRITICAL_SECTION
-    
-    // success
+    // OUT endpt -> host to device (RX)
+    else {
+        USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag |        // ep handshaking (not if iso endpoint)
+                                              USB_ENDPT_EPRXEN_MASK;  // en RX (OUT) tran.
+        bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].byte_count = maxPacket;
+        bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].address    = (uint32_t) buf;
+        bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].info       = BD_OWN_MASK | BD_DTS_MASK;
+        bdt[EP_BDT_IDX(log_endpoint, RX, EVEN)].info       = 0;
+    }
+
+    Data1 |= (1 << endpoint);
+
     return true;
 }
 
 // read setup packet
-void USBHAL::EP0setup(uint8_t *buffer) 
-{
+void USBHAL::EP0setup(uint8_t *buffer) {
     uint32_t sz;
     endpointReadResult(EP0OUT, buffer, &sz);
 }
 
-void USBHAL::EP0readStage(void) 
-{
-    // set DATA0 for the next packet
-    Data1 &= ~1UL;
-    
-    // if we haven't already, give the BDT to the SIE to read the packet
-    if (!(bdt[0].info & BD_OWN_MASK))
-        bdt[0].info = (BD_DTS_MASK | BD_OWN_MASK);
+void USBHAL::EP0readStage(void) {
+    Data1 &= ~1UL;  // set DATA0
+    bdt[0].info = (BD_DTS_MASK | BD_OWN_MASK);
 }
 
-void USBHAL::EP0read(void) 
-{
-    if (!(bdt[0].info & BD_OWN_MASK))
-        bdt[0].byte_count = MAX_PACKET_SIZE_EP0;
+void USBHAL::EP0read(void) {
+    uint32_t idx = EP_BDT_IDX(PHY_TO_LOG(EP0OUT), RX, 0);
+    bdt[idx].byte_count = MAX_PACKET_SIZE_EP0;
 }
 
-uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) 
-{
+uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
     uint32_t sz;
     endpointReadResult(EP0OUT, buffer, &sz);
     return sz;
 }
 
-void USBHAL::EP0write(uint8_t *buffer, uint32_t size) 
-{
+void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
     endpointWrite(EP0IN, buffer, size);
 }
 
-void USBHAL::EP0getWriteResult(void) 
-{
+void USBHAL::EP0getWriteResult(void) {
 }
 
-void USBHAL::EP0stall(void) 
-{
-    printd("EP0 stall!\r\n");
+void USBHAL::EP0stall(void) {
     stallEndpoint(EP0OUT);
 }
 
-EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) 
-{
-    // We always start a new read when we fetch the result of the
-    // previous read, so we don't have to do anything here.  Simply
-    // indicate that the read is pending so that the caller can proceed
-    // to check the results.
+EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
+    endpoint = PHY_TO_LOG(endpoint);
+    uint32_t idx = EP_BDT_IDX(endpoint, RX, 0);
+    bdt[idx].byte_count = maximumSize;
     return EP_PENDING;
 }
 
-EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *buffer, uint32_t *bytesRead) 
-{
-    // validate the endpoint number and direction
-    if (endpoint >= NUMBER_OF_PHYSICAL_ENDPOINTS || !OUT_EP(endpoint))
-        return EP_INVALID;
+EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) {
+    uint32_t n, sz, idx, setup = 0;
+    uint8_t not_iso;
+    uint8_t * ep_buf;
 
-    // get the logical endpoint
     uint32_t log_endpoint = PHY_TO_LOG(endpoint);
-    
-    // get the mode - it's isochronous if it doesn't have the handshake flag
-    bool iso = !(USB0->ENDPOINT[log_endpoint].ENDPT & USB_ENDPT_EPHSHK_MASK);
-    
-    // get the BDT index
-    int idx = EP_BDT_IDX(log_endpoint, RX, 0);
-        
-    // If the "complete" flag isn't set, the read is still pending in the SIE.
-    // This doesn't apply the isochronous endpoints, since we don't get TOKDNE
-    // interrupts on those (we use the SOF signal instead).  It also doesn't
-    // apply to endpoint 0, since that doesn't use the epComplete mechanism
-    // at all (necessary because we handle all transactions on this endpoint
-    // in IRQ context).  For EP0, just make sure the hardware doesn't still
-    // own the BDT - if it does, the last read hasn't completed yet.
-    if (log_endpoint == 0)
-    {
-        // control endpoint - just make sure we own the BDT
- //$$$       if (bdt[idx].info & BD_OWN_MASK)
- //$$$           return EP_PENDING;
+
+    if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) {
+        return EP_INVALID;
+    }
+
+    // if read on a IN endpoint -> error
+    if (IN_EP(endpoint)) {
+        return EP_INVALID;
     }
-    else if (!iso && !(epComplete & EP(endpoint)))
+
+    idx = EP_BDT_IDX(log_endpoint, RX, 0);
+    sz  = bdt[idx].byte_count;
+    not_iso = USB0->ENDPOINT[log_endpoint].ENDPT & USB_ENDPT_EPHSHK_MASK;
+
+    //for isochronous endpoint, we don't wait an interrupt
+    if ((log_endpoint != 0) && not_iso && !(epComplete & EP(endpoint))) {
         return EP_PENDING;
-    
-    // get the buffer
-    uint8_t *ep_buf = endpoint_buffer[endpoint];
+    }
+
+    if ((log_endpoint == 0) && (TOK_PID(idx) == SETUP_TOKEN)) {
+        setup = 1;
+    }
 
-    ENTER_CRITICAL_SECTION
-    {
-        // get the packet size from the BDT
-        uint32_t sz  = bdt[idx].byte_count;
-    
-        // note if it's a SETUP token    
-        bool setup = (log_endpoint == 0 && TOK_PID(idx) == SETUP_TOKEN);
-    
-        // copy the data
-        memcpy(buffer, ep_buf, sz);
-        *bytesRead = sz;
+    // non iso endpoint
+    if (not_iso) {
+        ep_buf = endpoint_buffer[idx];
+    } else {
+        ep_buf = endpoint_buffer_iso[0];
+    }
+
+    for (n = 0; n < sz; n++) {
+        buffer[n] = ep_buf[n];
+    }
 
-        // Figure the DATA0/DATA1 bit for the next packet received on this
-        // endpoint.  The bit normally toggles on each packet, but it's
-        // special for SETUP packets on endpoint 0.  The next OUT packet
-        // after a SETUP packet with no data stage is always DATA0, even
-        // if the SETUP packet was also DATA0.
-        if (((Data1 >> endpoint) & 1) == ((bdt[idx].info >> 6) & 1)) 
-        {
-            if (setup && (buffer[6] == 0))  // if no setup data stage,
-                Data1 &= ~1UL;              // set DATA0
-            else
-                Data1 ^= (1 << endpoint);   // otherwise just toggle the last bit
-        }
+    if (((Data1 >> endpoint) & 1) == ((bdt[idx].info >> 6) & 1)) {
+        if (setup && (buffer[6] == 0))  // if no setup data stage,
+            Data1 &= ~1UL;              // set DATA0
+        else
+            Data1 ^= (1 << endpoint);
+    }
 
-        // set up the BDT entry to receive the next packet, and hand it to the SIE to fill    
-        bdt[idx].byte_count = epMaxPacket[endpoint];
-        bdt[idx].info = BD_DTS_MASK | BD_OWN_MASK | (((Data1 >> endpoint) & 1) << 6);
-    
-        // clear the SUSPEND TOKEN BUSY flag to allow the SIE to continue processing tokens
-        USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
-    
-        // clear the completion flag
-        epComplete &= ~EP(endpoint);
+    if (((Data1 >> endpoint) & 1)) {
+        bdt[idx].info = BD_DTS_MASK | BD_DATA01_MASK | BD_OWN_MASK;
+    }
+    else {
+        bdt[idx].info = BD_DTS_MASK | BD_OWN_MASK;
     }
-    EXIT_CRITICAL_SECTION
-        
-    // the read is completed
+
+    USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
+    *bytesRead = sz;
+
+    epComplete &= ~EP(endpoint);
     return EP_COMPLETED;
 }
 
-EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) 
-{
-    // validate the endpoint number and direction
-    if (endpoint >= NUMBER_OF_PHYSICAL_ENDPOINTS || !IN_EP(endpoint))
+EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
+    uint32_t idx, n;
+    uint8_t * ep_buf;
+
+    if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) {
         return EP_INVALID;
+    }
 
-    // get the BDT index
-    int idx = EP_BDT_IDX(PHY_TO_LOG(endpoint), TX, 0);
-    
-    // get the buffer pointer
-    uint8_t *buf = endpoint_buffer[endpoint];
+    // if write on a OUT endpoint -> error
+    if (OUT_EP(endpoint)) {
+        return EP_INVALID;
+    }
+
+    idx = EP_BDT_IDX(PHY_TO_LOG(endpoint), TX, 0);
+    bdt[idx].byte_count = size;
+
 
-    ENTER_CRITICAL_SECTION
-    {
-        // copy the data to the hardware buffer
-        bdt[idx].byte_count = size;
-        memcpy(buf, data, size);
+    // non iso endpoint
+    if (USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT & USB_ENDPT_EPHSHK_MASK) {
+        ep_buf = endpoint_buffer[idx];
+    } else {
+        ep_buf = endpoint_buffer_iso[2];
+    }
 
-        // flip the DATA1 bit before sending    
-        Data1 ^= (1 << endpoint);
+    for (n = 0; n < size; n++) {
+        ep_buf[n] = data[n];
+    }
 
-        // hand the BDT to the SIE hardware, and set the current DATA1 bit
-        bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK | (((Data1 >> endpoint) & 1) << 6);
+    if ((Data1 >> endpoint) & 1) {
+        bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK;
+    } else {
+        bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK;
     }
-    EXIT_CRITICAL_SECTION
 
-    // the operation is now pending
+    Data1 ^= (1 << endpoint);
+
     return EP_PENDING;
 }
 
-EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) 
-{
-    EP_STATUS result = EP_PENDING;
+EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
+    if (epComplete & EP(endpoint)) {
+        epComplete &= ~EP(endpoint);
+        return EP_COMPLETED;
+    }
 
-    ENTER_CRITICAL_SECTION
-    {
-        if (epComplete & EP(endpoint)) {
-            epComplete &= ~EP(endpoint);
-            result = EP_COMPLETED;
-        }
-    }
-    EXIT_CRITICAL_SECTION
-    
-    return result;
+    return EP_PENDING;
 }
 
-void USBHAL::stallEndpoint(uint8_t endpoint) 
-{
+void USBHAL::stallEndpoint(uint8_t endpoint) {
     USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT |= USB_ENDPT_EPSTALL_MASK;
 }
 
-void USBHAL::unstallEndpoint(uint8_t endpoint) 
-{
-    printd("unstall endpoint %d %s\r\n", endpoint>>1,endpoint&1?"TX":"RX");
-    ENTER_CRITICAL_SECTION
-    {
-        USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT &= ~USB_ENDPT_EPSTALL_MASK;
-        int idx = PEP_BDT_IDX(endpoint, 0);
-        bdt[idx].info &= ~(BD_OWN_MASK | BD_STALL_MASK | BD_DATA01_MASK);
-        
-        if (OUT_EP(endpoint))
-            Data1 &= ~(1 << endpoint);
-        else
-            Data1 |= (1 << endpoint);
-    }
-    EXIT_CRITICAL_SECTION
+void USBHAL::unstallEndpoint(uint8_t endpoint) {
+    USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT &= ~USB_ENDPT_EPSTALL_MASK;
 }
 
-bool USBHAL::getEndpointStallState(uint8_t endpoint) 
-{
+bool USBHAL::getEndpointStallState(uint8_t endpoint) {
     uint8_t stall = (USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT & USB_ENDPT_EPSTALL_MASK);
     return (stall) ? true : false;
 }
 
-void USBHAL::remoteWakeup(void) 
-{
+void USBHAL::remoteWakeup(void) {
     // [TODO]
 }
 
-// Handle SETUP packet on EP0 IN or OUT
-void USBHAL::EP0_SETUP_callback(void)
-{
-    // Set DATA1 on Control IN endpoint for next packet (recall that we
-    // toggle the bit before a send, so clearing the bit sets DATA1 for
-    // the next send).  If there's a data IN stage for the SETUP packet,
-    // it must always be DATA1, regardless of the prior state of the IN
-    // endpoint.
-    Data1 &= ~0x02;
-    
-    // make sure we own the IN enpdoint now, in preparation for the reply
-    bdt[PEP_BDT_IDX(EP0IN, EVEN)].info &= ~BD_OWN_MASK;
-    
-    // process the SETUP packet through the portable protocol code
-    EP0setupCallback();
-}
 
-// Control endpoint OUT/SETUP callback.  Called from ISR context only.
-bool USBHAL::EP0_OUT_callback(void)
-{
-    int idx = PEP_BDT_IDX(EP0OUT, EVEN);
-    if (TOK_PID(idx) == SETUP_TOKEN) 
-    {
-        // SETUP packet on EP0
-        EP0_SETUP_callback();
-    } 
-    else 
-    {
-        // OUT packet on EP0 - process it through the protocol code
-        EP0out();
-    }
-    
-    // success
-    return true;
-}
-
-// Control endpoint IN packet handler.  This is only called from ISR context.
-bool USBHAL::EP0_IN_callback(void)
-{
-    int idx = PEP_BDT_IDX(EP0OUT, EVEN);
-    if (TOK_PID(idx) == SETUP_TOKEN) 
-    {
-        // SETUP packet on EP0
-        EP0_SETUP_callback();
-    } 
-    else 
-    {
-        // process the IN packet through the portable protocol code
-        EP0in();
-    }
-    
-    // If we have a SET ADDRESS command outstanding, put it into effect now.
-    // The USB spec requires an address change to be made immediately (within 
-    // 2ms) after the reply to the SET ADDRESS SETUP packet.  If the flag is
-    // set, it means that the EP0in() call above just sent the response, so
-    // now is the time to make the address change in the SIE hardware register.
-    if (set_addr == 1) 
-    {
-        USB0->ADDR = addr & 0x7F;
-        set_addr = 0;
-    }
-    
-    // success
-    return true;
+void USBHAL::_usbisr(void) {
+    instance->usbisr();
 }
 
 
-void USBHAL::_usbisr(void) 
-{
-    inIRQ = true;
-    instance->usbisr();
-    inIRQ = false;
-}
-
-
-void USBHAL::usbisr(void) 
-{
+void USBHAL::usbisr(void) {
     uint8_t i;
     uint8_t istat = USB0->ISTAT;
 
     // reset interrupt
-    if (istat & USB_ISTAT_USBRST_MASK) 
-    {
+    if (istat & USB_ISTAT_USBRST_MASK) {
+        
         // disable all endpt
-        for(i = 0 ; i < 16 ; i++)
+        for(i = 0; i < 16; i++) {
             USB0->ENDPOINT[i].ENDPT = 0x00;
+        }
 
         // enable control endpoint
         realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0);
         realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0);
 
         Data1 = 0x55555555;
-        epComplete = 0;
         USB0->CTL |=  USB_CTL_ODDRST_MASK;
 
         USB0->ISTAT   =  0xFF;  // clear all interrupt status flags
@@ -675,83 +458,91 @@
         
         // we're not suspended
         suspendStateChanged(0);
-        
-        // return now - do no more processing on a RESET interrupt
+
         return;
     }
 
     // resume interrupt
-    if (istat & USB_ISTAT_RESUME_MASK) 
-    {
+    if (istat & USB_ISTAT_RESUME_MASK) {
+        USB0->ISTAT = USB_ISTAT_RESUME_MASK;
         suspendStateChanged(0);
-        USB0->ISTAT = USB_ISTAT_RESUME_MASK;
     }
 
     // SOF interrupt
-    if (istat & USB_ISTAT_SOFTOK_MASK) 
-    {
-        // Read frame number and signal the SOF event to the callback
+    if (istat & USB_ISTAT_SOFTOK_MASK) {
+        USB0->ISTAT = USB_ISTAT_SOFTOK_MASK;
+        // SOF event, read frame number
         SOF(frameNumber());
-        USB0->ISTAT = USB_ISTAT_SOFTOK_MASK;
     }
 
     // stall interrupt
-    if (istat & USB_ISTAT_STALL_MASK)
-    {
-        // if the control endpoint (EP 0) is stalled, unstall it
+    if (istat & 1<<7) {
         if (USB0->ENDPOINT[0].ENDPT & USB_ENDPT_EPSTALL_MASK)
-        {
-            unstallEndpoint(EP0OUT);
-            unstallEndpoint(EP0IN);
-        }
-        
-        // clear the SUSPEND flag to allow token processing to continue
-        USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
-        USB0->ISTAT = USB_ISTAT_STALL_MASK;
+            USB0->ENDPOINT[0].ENDPT &= ~USB_ENDPT_EPSTALL_MASK;
+        USB0->ISTAT |= USB_ISTAT_STALL_MASK;
     }
 
     // token interrupt
-    if (istat & USB_ISTAT_TOKDNE_MASK) 
-    {
+    if (istat & 1<<3) {
         uint32_t num  = (USB0->STAT >> 4) & 0x0F;
         uint32_t dir  = (USB0->STAT >> 3) & 0x01;
-        int endpoint = (num << 1) | dir;
-        // uint32_t ev_odd = (USB0->STAT >> 2) & 0x01;  // we only use EVEN buffers, so this is always 0
+        uint32_t ev_odd = (USB0->STAT >> 2) & 0x01;
+
+        // setup packet
+        if ((num == 0) && (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == SETUP_TOKEN)) {
+            Data1 &= ~0x02;
+            bdt[EP_BDT_IDX(0, TX, EVEN)].info &= ~BD_OWN_MASK;
+            bdt[EP_BDT_IDX(0, TX, ODD)].info  &= ~BD_OWN_MASK;
+
+            // EP0 SETUP event (SETUP data received)
+            EP0setupCallback();
 
-        // set the Completed bit for the endpoint to indicate that we've
-        // finished this send/receive request
-        epComplete |= EP(endpoint);
-        
-        // Call the endpoint packet callback.  If that returns true, it means
-        // that the callback handled the packet.  That consumes the packet, so
-        // clear the Completed flag to indicate that we're on to the next
-        // transaction on the endpoint.
-        if ((instance->*(epCallback[endpoint]))())
-            epComplete &= ~EP(endpoint);
+        } else {
+            // OUT packet
+            if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == OUT_TOKEN) {
+                if (num == 0)
+                    EP0out();
+                else {
+                    epComplete |= (1 << EP(num));
+                    if ((instance->*(epCallback[EP(num) - 2]))()) {
+                        epComplete &= ~(1 << EP(num));
+                    }
+                }
+            }
 
-        // allow token processing to resume
-        USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
-        
-        // reset the TOKDNE interrupt status flag
+            // IN packet
+            if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == IN_TOKEN) {
+                if (num == 0) {
+                    EP0in();
+                    if (set_addr == 1) {
+                        USB0->ADDR = addr & 0x7F;
+                        set_addr = 0;
+                    }
+                }
+                else {
+                    epComplete |= (1 << (EP(num) + 1));
+                    if ((instance->*(epCallback[EP(num) + 1 - 2]))()) {
+                        epComplete &= ~(1 << (EP(num) + 1));
+                    }
+                }
+            }
+        }
+
         USB0->ISTAT = USB_ISTAT_TOKDNE_MASK;
     }
 
     // sleep interrupt
-    if (istat & USB_ISTAT_SLEEP_MASK) 
-    {
+    if (istat & 1<<4) {
+        USB0->ISTAT |= USB_ISTAT_SLEEP_MASK;
         suspendStateChanged(1);
-        USB0->ISTAT = USB_ISTAT_SLEEP_MASK;
     }
 
     // error interrupt
-    if (istat & USB_ISTAT_ERROR_MASK) 
-    {
-        // reset all error status bits, and clear the SUSPEND flag to allow
-        // token processing to continue
+    if (istat & USB_ISTAT_ERROR_MASK) {
         USB0->ERRSTAT = 0xFF;
-        USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
-        USB0->ISTAT = USB_ISTAT_ERROR_MASK;
+        USB0->ISTAT |= USB_ISTAT_ERROR_MASK;
     }
 }
 
+
 #endif
--- a/USBDevice/USBHID/USBHID.cpp	Thu Feb 11 18:12:52 2016 +0000
+++ b/USBDevice/USBHID/USBHID.cpp	Thu Feb 11 18:31:05 2016 +0000
@@ -112,19 +112,16 @@
                             // multiple interfaces, this is used to identify which interface
                             // is being queried.  The base mbed implementation ignores this,
                             // which makes it impossible to implement multiple interfaces.
-                            int idx = DESCRIPTOR_INDEX(transfer->setup.wValue);
+                            int idx = transfer->setup.wIndex;
                             transfer->remaining = reportDescLengthN(idx);
                             transfer->ptr = reportDescN(idx);
                             transfer->direction = DEVICE_TO_HOST;
                             success = true;
                         }
                         break;
-                        
                     case HID_DESCRIPTOR:
-                        {
                             // Find the HID descriptor, after the configuration descriptor
-                            int idx = DESCRIPTOR_INDEX(transfer->setup.wValue);
-                            hidDescriptor = findDescriptor(HID_DESCRIPTOR, idx);
+                            hidDescriptor = findDescriptor(HID_DESCRIPTOR, transfer->setup.wIndex);
                             if (hidDescriptor != NULL)
                             {
                                 transfer->remaining = HID_DESCRIPTOR_LENGTH;
@@ -132,8 +129,7 @@
                                 transfer->direction = DEVICE_TO_HOST;
                                 success = true;
                             }
-                        }
-                        break;
+                            break;
 
                     default:
                         break;
@@ -150,26 +146,7 @@
     {
         switch (transfer->setup.bRequest)
         {
-            case GET_REPORT:
-                // not implemented
-                break;
-                
-            case GET_IDLE:
-#if 0 // $$$
-                // retrieve the idle rate from an interface
-                idleData = getIdleTime(transfer->setup.wIndex, LSB(transfer->setup.wValue));
-                transfer->ptr = &idleData;
-                transfer->remaining = 1;
-                transfer->direction = DEVICE_TO_HOST;
-                success = true;
-#endif // $$$
-                break;
-                
-            case GET_PROTOCOL:
-                // not implemented
-                break;
-                
-            case SET_REPORT:
+             case SET_REPORT:
                 // First byte will be used for report ID
                 outputReport.data[0] = transfer->setup.wValue & 0xff;
                 outputReport.length = transfer->setup.wLength + 1;
@@ -179,25 +156,6 @@
                 transfer->direction = HOST_TO_DEVICE;
                 transfer->notify = true;
                 success = true;
-                
-            case SET_IDLE:
-#if 0 // $$$
-                // Set idle time - time between INTERRUPT IN reports from the
-                // device when there are no changes to report.  setup.wIndex
-                // is the interface index (we're setting the idle time for the
-                // given interface only).  MSB(setup.wValue) gives the interval
-                // in 4ms units, with the special case that 0 means infinity.
-                setIdleTime(transfer->setup.wIndex, LSB(transfer->setup.wValue), MSB(transfer->setup.wValue));
-                transfer->remaining = 0;
-                transfer->direction = DEVICE_TO_HOST;
-                success = true;
-#endif // $$$
-                break;
-                
-            case SET_PROTOCOL:
-                // not implemented
-                break;
-                
             default:
                 break;
         }
--- a/USBDevice/USBHID/USBHID.h	Thu Feb 11 18:12:52 2016 +0000
+++ b/USBDevice/USBHID/USBHID.h	Thu Feb 11 18:31:05 2016 +0000
@@ -115,7 +115,7 @@
     * @returns pointer to the report descriptor
     */
     virtual uint8_t * reportDesc();
-    virtual uint8_t * reportDescN(int idx) { return reportDesc(); /*$$$idx == 0 ? reportDesc() : 0;*/ }
+    virtual uint8_t * reportDescN(int idx) { return idx == 0 ? reportDesc() : 0; }
 
     /*
     * Get the length of the report descriptor
@@ -149,39 +149,7 @@
     * @returns pointer to the configuration descriptor
     */
     virtual uint8_t * configurationDesc();
-    
-    /*
-    * Set the idle time on the given interface.  The idle time is the time between
-    * INTERRUPT IN reports sent from the device to the host in the absence of any
-    * updates in values.  E.g., for a keyboard, this is the time between reports
-    * when there's no new key up/down activity to report.  An infinite idle time
-    * means that reports are sent only when new activity occurs.
-    *
-    * @param ifc Interface index (this specifies which interface is affected, in
-    * cases where the device has multiple interfaces)
-    *
-    * @param reportID Report ID (specifies which report type is affected, in cases
-    * where the device has multiple report types)
-    *
-    * @param t Idle time in 4ms units, with the special case that 0 means infinity.
-    * The maximum value is 255 units (1.02s).
-    */
-    virtual void setIdleTime(int ifc, int reportId, int t) { }
-    
-    /*
-    * Get the idle time on the given interface.  Returns the idle time information
-    * previously set with setIdleTime().
-    *
-    * @param ifc Interface index (specifies which interface is being queried, in
-    * cases where the device has multiple interfaces)
-    *
-    * @param reportID Report ID (specifies which report type is being queried, in
-    * cases where the device has multiple report types)
-    *
-    * @return The idle time currently set on the interface, in 4ms units.  0 means
-    * infinity (so reports will only be sent when there's new data)
-    */
-    virtual uint8_t getIdleTime(int ifc, int reportId) { return 0; }
+
 
     /*
     * HID Report received by SET_REPORT request. Warning: Called in ISR context
@@ -215,7 +183,6 @@
     HID_REPORT outputReport;
     uint8_t output_length;
     uint8_t input_length;
-    uint8_t idleData;
 };
 
 #endif
--- a/USBDevice/USBHID/USBHID_Types.h	Thu Feb 11 18:12:52 2016 +0000
+++ b/USBDevice/USBHID/USBHID_Types.h	Thu Feb 11 18:31:05 2016 +0000
@@ -35,12 +35,10 @@
 #define REPORT_DESCRIPTOR       (34)
 
 /* Class requests */
-#define GET_REPORT    (0x01)
-#define GET_IDLE      (0x02)
-#define GET_PROTOCOL  (0x03)
-#define SET_REPORT    (0x09)
-#define SET_IDLE      (0x0a)
-#define SET_PROTOCOL  (0x0b)
+#define GET_REPORT (0x1)
+#define GET_IDLE   (0x2)
+#define SET_REPORT (0x9)
+#define SET_IDLE   (0xa)
 
 /* HID Class Report Descriptor */
 /* Short items: size is 0, 1, 2 or 3 specifying 0, 1, 2 or 4 (four) bytes */