Adds class implementation for use STM32F4xx OTG_HS in FS mode

Dependents:   IGLOO_board

Fork of USBDevice by mbed official

Files at this revision

API Documentation at this revision

Comitter:
ua1arn
Date:
Mon Jul 30 13:56:22 2018 +0000
Parent:
76:a791d5373beb
Child:
78:b881d8ac258a
Commit message:
prepare to multi-configuration USB - added parameter to configDescriptor()

Changed in this revision

USBAudio/USBAudio.cpp Show annotated file Show diff for this revision Revisions of this file
USBAudio/USBAudio.h Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBDevice.cpp Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBDevice.h Show annotated file Show diff for this revision Revisions of this file
USBHID/USBHID.cpp Show annotated file Show diff for this revision Revisions of this file
USBHID/USBHID.h Show annotated file Show diff for this revision Revisions of this file
USBHID/USBKeyboard.cpp Show annotated file Show diff for this revision Revisions of this file
USBHID/USBKeyboard.h Show annotated file Show diff for this revision Revisions of this file
USBMIDI/USBMIDI.cpp Show annotated file Show diff for this revision Revisions of this file
USBMIDI/USBMIDI.h Show annotated file Show diff for this revision Revisions of this file
USBMSD/USBMSD.cpp Show annotated file Show diff for this revision Revisions of this file
USBMSD/USBMSD.h Show annotated file Show diff for this revision Revisions of this file
USBSerial/USBCDC.cpp Show annotated file Show diff for this revision Revisions of this file
USBSerial/USBCDC.h Show annotated file Show diff for this revision Revisions of this file
--- a/USBAudio/USBAudio.cpp	Mon Jul 30 12:30:04 2018 +0000
+++ b/USBAudio/USBAudio.cpp	Mon Jul 30 13:56:22 2018 +0000
@@ -130,7 +130,7 @@
 }
 
 float USBAudio::getVolume() {
-    return (mute) ? 0.0 : volume;
+    return (mute) ? (float) 0.0 : volume;
 }
 
 
@@ -377,7 +377,7 @@
                                       FEATURE_UNIT_DESCRIPTOR_LENGTH    + \
                                       2*OUTPUT_TERMINAL_DESCRIPTOR_LENGTH)
 
-uint8_t * USBAudio::configurationDesc() {
+uint8_t * USBAudio::configurationDesc(uint_fast8_t cfgidx) {
     static uint8_t configDescriptor[] = {
         // Configuration 1
         CONFIGURATION_DESCRIPTOR_LENGTH,        // bLength
--- a/USBAudio/USBAudio.h	Mon Jul 30 12:30:04 2018 +0000
+++ b/USBAudio/USBAudio.h	Mon Jul 30 13:56:22 2018 +0000
@@ -230,7 +230,7 @@
     *
     * @returns pointer to the configuration descriptor
     */
-    virtual uint8_t * configurationDesc();
+    virtual uint8_t * configurationDesc(uint_fast8_t cfgidx);
 
     /*
      * Called by USBDevice layer. Set interface/alternate of the device.
--- a/USBDevice/USBDevice.cpp	Mon Jul 30 12:30:04 2018 +0000
+++ b/USBDevice/USBDevice.cpp	Mon Jul 30 13:56:22 2018 +0000
@@ -46,14 +46,11 @@
 #ifdef DEBUG
     printf("get descr: type: %d\r\n", DESCRIPTOR_TYPE(transfer.setup.wValue));
 #endif
-    switch (DESCRIPTOR_TYPE(transfer.setup.wValue))
-    {
+    switch (DESCRIPTOR_TYPE(transfer.setup.wValue)) {
         case DEVICE_DESCRIPTOR:
-            if (deviceDesc() != NULL)
-            {
+            if (deviceDesc() != NULL) {
                 if ((deviceDesc()[0] == DEVICE_DESCRIPTOR_LENGTH) \
-                    && (deviceDesc()[1] == DEVICE_DESCRIPTOR))
-                {
+                        && (deviceDesc()[1] == DEVICE_DESCRIPTOR)) {
 #ifdef DEBUG
                     printf("device descr\r\n");
 #endif
@@ -64,85 +61,82 @@
                 }
             }
             break;
-        case CONFIGURATION_DESCRIPTOR:
-            if (configurationDesc() != NULL)
-            {
-                if ((configurationDesc()[0] == CONFIGURATION_DESCRIPTOR_LENGTH) \
-                    && (configurationDesc()[1] == CONFIGURATION_DESCRIPTOR))
-                {
+        case CONFIGURATION_DESCRIPTOR: {
+            const uint_fast8_t cfgidx = DESCRIPTOR_INDEX(transfer.setup.wValue);
+            if (configurationDesc(cfgidx) != NULL) {
 #ifdef DEBUG
-                    printf("conf descr request\r\n");
+                printf("conf descr request\r\n");
 #endif
-                    /* Get wTotalLength */
-                    transfer.remaining = configurationDesc()[2] \
-                        | (configurationDesc()[3] << 8);
+                /* Get wTotalLength */
+                transfer.remaining = configurationDesc(cfgidx)[2] \
+                                     | (configurationDesc(cfgidx)[3] << 8);
 
-                    transfer.ptr = configurationDesc();
-                    transfer.direction = DEVICE_TO_HOST;
-                    success = true;
-                }
+                transfer.ptr = configurationDesc(cfgidx);
+                transfer.direction = DEVICE_TO_HOST;
+                success = true;
             }
-            break;
+        }
+
+        break;
         case STRING_DESCRIPTOR:
 #ifdef DEBUG
             printf("str descriptor\r\n");
 #endif
-            switch (DESCRIPTOR_INDEX(transfer.setup.wValue))
-            {
-                            case STRING_OFFSET_LANGID:
+            switch (DESCRIPTOR_INDEX(transfer.setup.wValue)) {
+                case STRING_OFFSET_LANGID:
 #ifdef DEBUG
-                                printf("1\r\n");
+                    printf("1\r\n");
 #endif
-                                transfer.remaining = stringLangidDesc()[0];
-                                transfer.ptr = stringLangidDesc();
-                                transfer.direction = DEVICE_TO_HOST;
-                                success = true;
-                                break;
-                            case STRING_OFFSET_IMANUFACTURER:
+                    transfer.remaining = stringLangidDesc()[0];
+                    transfer.ptr = stringLangidDesc();
+                    transfer.direction = DEVICE_TO_HOST;
+                    success = true;
+                    break;
+                case STRING_OFFSET_IMANUFACTURER:
 #ifdef DEBUG
-                                printf("2\r\n");
+                    printf("2\r\n");
 #endif
-                                transfer.remaining =  stringImanufacturerDesc()[0];
-                                transfer.ptr = stringImanufacturerDesc();
-                                transfer.direction = DEVICE_TO_HOST;
-                                success = true;
-                                break;
-                            case STRING_OFFSET_IPRODUCT:
+                    transfer.remaining =  stringImanufacturerDesc()[0];
+                    transfer.ptr = stringImanufacturerDesc();
+                    transfer.direction = DEVICE_TO_HOST;
+                    success = true;
+                    break;
+                case STRING_OFFSET_IPRODUCT:
 #ifdef DEBUG
-                                printf("3\r\n");
+                    printf("3\r\n");
 #endif
-                                transfer.remaining = stringIproductDesc()[0];
-                                transfer.ptr = stringIproductDesc();
-                                transfer.direction = DEVICE_TO_HOST;
-                                success = true;
-                                break;
-                            case STRING_OFFSET_ISERIAL:
+                    transfer.remaining = stringIproductDesc()[0];
+                    transfer.ptr = stringIproductDesc();
+                    transfer.direction = DEVICE_TO_HOST;
+                    success = true;
+                    break;
+                case STRING_OFFSET_ISERIAL:
 #ifdef DEBUG
-                                printf("4\r\n");
+                    printf("4\r\n");
 #endif
-                                transfer.remaining = stringIserialDesc()[0];
-                                transfer.ptr = stringIserialDesc();
-                                transfer.direction = DEVICE_TO_HOST;
-                                success = true;
-                                break;
-                            case STRING_OFFSET_ICONFIGURATION:
+                    transfer.remaining = stringIserialDesc()[0];
+                    transfer.ptr = stringIserialDesc();
+                    transfer.direction = DEVICE_TO_HOST;
+                    success = true;
+                    break;
+                case STRING_OFFSET_ICONFIGURATION:
 #ifdef DEBUG
-                                printf("5\r\n");
+                    printf("5\r\n");
 #endif
-                                transfer.remaining = stringIConfigurationDesc()[0];
-                                transfer.ptr = stringIConfigurationDesc();
-                                transfer.direction = DEVICE_TO_HOST;
-                                success = true;
-                                break;
-                            case STRING_OFFSET_IINTERFACE:
+                    transfer.remaining = stringIConfigurationDesc()[0];
+                    transfer.ptr = stringIConfigurationDesc();
+                    transfer.direction = DEVICE_TO_HOST;
+                    success = true;
+                    break;
+                case STRING_OFFSET_IINTERFACE:
 #ifdef DEBUG
-                                printf("6\r\n");
+                    printf("6\r\n");
 #endif
-                                transfer.remaining = stringIinterfaceDesc()[0];
-                                transfer.ptr = stringIinterfaceDesc();
-                                transfer.direction = DEVICE_TO_HOST;
-                                success = true;
-                                break;
+                    transfer.remaining = stringIinterfaceDesc()[0];
+                    transfer.ptr = stringIinterfaceDesc();
+                    transfer.direction = DEVICE_TO_HOST;
+                    success = true;
+                    break;
             }
             break;
         case INTERFACE_DESCRIPTOR:
@@ -185,37 +179,35 @@
     uint32_t packetSize;
 
     /* Check we should be transferring data OUT */
-    if (transfer.direction != HOST_TO_DEVICE)
-    {
+    if (transfer.direction != HOST_TO_DEVICE) {
 #if defined(TARGET_KL25Z) | defined(TARGET_KL43Z) | defined(TARGET_KL46Z) | defined(TARGET_K20D5M) | defined(TARGET_K64F) | defined(TARGET_K22F) | defined(TARGET_TEENSY3_1)
         /*
          * 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 
+         * the previous one.  This appears to happen when we're connected to certain
          * 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 ttransfer */
-         controlIn();
-         
-         /* indicate success */
-         return true;
- #else
-         /* for other platforms, count on the HAL to handle this case */
-         return false;
- #endif
+        uint8_t buf[1] = { 0 };
+        EP0write(buf, 0);
+
+        /* execute our pending ttransfer */
+        controlIn();
+
+        /* indicate success */
+        return true;
+#else
+        /* for other platforms, count on the HAL to handle this case */
+        return false;
+#endif
     }
 
     /* Read from endpoint */
     packetSize = EP0getReadResult(buffer);
 
     /* Check if transfer size is valid */
-    if (packetSize > transfer.remaining)
-    {
+    if (packetSize > transfer.remaining) {
         /* Too big */
         return false;
     }
@@ -225,20 +217,16 @@
     transfer.remaining -= packetSize;
 
     /* Check if transfer has completed */
-    if (transfer.remaining == 0)
-    {
+    if (transfer.remaining == 0) {
         /* Transfer completed */
-        if (transfer.notify)
-        {
+        if (transfer.notify) {
             /* Notify class layer. */
             USBCallback_requestCompleted(buffer, packetSize);
             transfer.notify = false;
         }
         /* Status stage */
         EP0write(NULL, 0);
-    }
-    else
-    {
+    } else {
         EP0read();
     }
 
@@ -252,18 +240,15 @@
 
     /* Check if transfer has completed (status stage transactions */
     /* also have transfer.remaining == 0) */
-    if (transfer.remaining == 0)
-    {
-        if (transfer.zlp)
-        {
+    if (transfer.remaining == 0) {
+        if (transfer.zlp) {
             /* Send zero length packet */
             EP0write(NULL, 0);
             transfer.zlp = false;
         }
 
         /* Transfer completed */
-        if (transfer.notify)
-        {
+        if (transfer.notify) {
             /* Notify class layer. */
             USBCallback_requestCompleted(NULL, 0);
             transfer.notify = false;
@@ -277,15 +262,13 @@
     }
 
     /* Check we should be transferring data IN */
-    if (transfer.direction != DEVICE_TO_HOST)
-    {
+    if (transfer.direction != DEVICE_TO_HOST) {
         return false;
     }
 
     packetSize = transfer.remaining;
 
-    if (packetSize > MAX_PACKET_SIZE_EP0)
-    {
+    if (packetSize > MAX_PACKET_SIZE_EP0) {
         packetSize = MAX_PACKET_SIZE_EP0;
     }
 
@@ -304,12 +287,9 @@
     /* Set the device address */
     setAddress(transfer.setup.wValue);
 
-    if (transfer.setup.wValue == 0)
-    {
+    if (transfer.setup.wValue == 0) {
         device.state = DEFAULT;
-    }
-    else
-    {
+    } else {
         device.state = ADDRESS;
     }
 
@@ -321,22 +301,16 @@
 
     device.configuration = transfer.setup.wValue;
     /* Set the device configuration */
-    if (device.configuration == 0)
-    {
+    if (device.configuration == 0) {
         /* Not configured */
         unconfigureDevice();
         device.state = ADDRESS;
-    }
-    else
-    {
-        if (USBCallback_setConfiguration(device.configuration))
-        {
+    } else {
+        if (USBCallback_setConfiguration(device.configuration)) {
             /* Valid configuration */
             configureDevice();
             device.state = CONFIGURED;
-        }
-        else
-        {
+        } else {
             return false;
         }
     }
@@ -357,8 +331,7 @@
 {
     /* Return the selected alternate setting for an interface */
 
-    if (device.state != CONFIGURED)
-    {
+    if (device.state != CONFIGURED) {
         return false;
     }
 
@@ -373,8 +346,7 @@
 bool USBDevice::requestSetInterface(void)
 {
     bool success = false;
-    if(USBCallback_setInterface(transfer.setup.wIndex, transfer.setup.wValue))
-    {
+    if(USBCallback_setInterface(transfer.setup.wIndex, transfer.setup.wValue)) {
         success = true;
         currentInterface = transfer.setup.wIndex;
         currentAlternate = transfer.setup.wValue;
@@ -386,23 +358,19 @@
 {
     bool success = false;
 
-    if (device.state != CONFIGURED)
-    {
+    if (device.state != CONFIGURED) {
         /* Endpoint or interface must be zero */
-        if (transfer.setup.wIndex != 0)
-        {
+        if (transfer.setup.wIndex != 0) {
             return false;
         }
     }
 
-    switch (transfer.setup.bmRequestType.Recipient)
-    {
+    switch (transfer.setup.bmRequestType.Recipient) {
         case DEVICE_RECIPIENT:
             /* TODO: Remote wakeup feature not supported */
             break;
         case ENDPOINT_RECIPIENT:
-            if (transfer.setup.wValue == ENDPOINT_HALT)
-            {
+            if (transfer.setup.wValue == ENDPOINT_HALT) {
                 /* TODO: We should check that the endpoint number is valid */
                 stallEndpoint(
                     WINDEX_TO_PHYSICAL(transfer.setup.wIndex));
@@ -420,24 +388,20 @@
 {
     bool success = false;
 
-    if (device.state != CONFIGURED)
-    {
+    if (device.state != CONFIGURED) {
         /* Endpoint or interface must be zero */
-        if (transfer.setup.wIndex != 0)
-        {
+        if (transfer.setup.wIndex != 0) {
             return false;
         }
     }
 
-    switch (transfer.setup.bmRequestType.Recipient)
-    {
+    switch (transfer.setup.bmRequestType.Recipient) {
         case DEVICE_RECIPIENT:
             /* TODO: Remote wakeup feature not supported */
             break;
         case ENDPOINT_RECIPIENT:
             /* TODO: We should check that the endpoint number is valid */
-            if (transfer.setup.wValue == ENDPOINT_HALT)
-            {
+            if (transfer.setup.wValue == ENDPOINT_HALT) {
                 unstallEndpoint( WINDEX_TO_PHYSICAL(transfer.setup.wIndex));
                 success = true;
             }
@@ -454,17 +418,14 @@
     static uint16_t status;
     bool success = false;
 
-    if (device.state != CONFIGURED)
-    {
+    if (device.state != CONFIGURED) {
         /* Endpoint or interface must be zero */
-        if (transfer.setup.wIndex != 0)
-        {
+        if (transfer.setup.wIndex != 0) {
             return false;
         }
     }
 
-    switch (transfer.setup.bmRequestType.Recipient)
-    {
+    switch (transfer.setup.bmRequestType.Recipient) {
         case DEVICE_RECIPIENT:
             /* TODO: Currently only supports self powered devices */
             status = DEVICE_STATUS_SELF_POWERED;
@@ -477,12 +438,9 @@
         case ENDPOINT_RECIPIENT:
             /* TODO: We should check that the endpoint number is valid */
             if (getEndpointStallState(
-                WINDEX_TO_PHYSICAL(transfer.setup.wIndex)))
-            {
+                        WINDEX_TO_PHYSICAL(transfer.setup.wIndex))) {
                 status = ENDPOINT_STATUS_HALT;
-            }
-            else
-            {
+            } else {
                 status = 0;
             }
             success = true;
@@ -491,8 +449,7 @@
             break;
     }
 
-    if (success)
-    {
+    if (success) {
         /* Send the status */
         transfer.ptr = (uint8_t *)&status; /* Assumes little endian */
         transfer.remaining = sizeof(status);
@@ -507,43 +464,41 @@
     bool success = false;
 
     /* Process standard requests */
-    if ((transfer.setup.bmRequestType.Type == STANDARD_TYPE))
-    {
-        switch (transfer.setup.bRequest)
-        {
-             case GET_STATUS:
-                 success = requestGetStatus();
-                 break;
-             case CLEAR_FEATURE:
-                 success = requestClearFeature();
-                 break;
-             case SET_FEATURE:
-                 success = requestSetFeature();
-                 break;
-             case SET_ADDRESS:
+    if ((transfer.setup.bmRequestType.Type == STANDARD_TYPE)) {
+        switch (transfer.setup.bRequest) {
+            case GET_STATUS:
+                success = requestGetStatus();
+                break;
+            case CLEAR_FEATURE:
+                success = requestClearFeature();
+                break;
+            case SET_FEATURE:
+                success = requestSetFeature();
+                break;
+            case SET_ADDRESS:
                 success = requestSetAddress();
-                 break;
-             case GET_DESCRIPTOR:
-                 success = requestGetDescriptor();
-                 break;
-             case SET_DESCRIPTOR:
-                 /* TODO: Support is optional, not implemented here */
-                 success = false;
-                 break;
-             case GET_CONFIGURATION:
-                 success = requestGetConfiguration();
-                 break;
-             case SET_CONFIGURATION:
-                 success = requestSetConfiguration();
-                 break;
-             case GET_INTERFACE:
-                 success = requestGetInterface();
-                 break;
-             case SET_INTERFACE:
-                 success = requestSetInterface();
-                 break;
-             default:
-                 break;
+                break;
+            case GET_DESCRIPTOR:
+                success = requestGetDescriptor();
+                break;
+            case SET_DESCRIPTOR:
+                /* TODO: Support is optional, not implemented here */
+                success = false;
+                break;
+            case GET_CONFIGURATION:
+                success = requestGetConfiguration();
+                break;
+            case SET_CONFIGURATION:
+                success = requestSetConfiguration();
+                break;
+            case GET_INTERFACE:
+                success = requestGetInterface();
+                break;
+            case SET_INTERFACE:
+                success = requestSetInterface();
+                break;
+            default:
+                break;
         }
     }
 
@@ -569,22 +524,20 @@
 
 #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);
+           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();
 
-    if (!success)
-    {
+    if (!success) {
         /* Standard requests */
-        if (!requestSetup())
-        {
+        if (!requestSetup()) {
 #ifdef DEBUG
             printf("fail!!!!\r\n");
 #endif
@@ -593,62 +546,47 @@
     }
 
     /* Check transfer size and direction */
-    if (transfer.setup.wLength>0)
-    {
+    if (transfer.setup.wLength>0) {
         if (transfer.setup.bmRequestType.dataTransferDirection \
-            == DEVICE_TO_HOST)
-        {
+                == DEVICE_TO_HOST) {
             /* IN data stage is required */
-            if (transfer.direction != DEVICE_TO_HOST)
-            {
+            if (transfer.direction != DEVICE_TO_HOST) {
                 return false;
             }
 
             /* Transfer must be less than or equal to the size */
             /* requested by the host */
-            if (transfer.remaining > transfer.setup.wLength)
-            {
+            if (transfer.remaining > transfer.setup.wLength) {
                 transfer.remaining = transfer.setup.wLength;
             }
-        }
-        else
-        {
+        } else {
 
             /* OUT data stage is required */
-            if (transfer.direction != HOST_TO_DEVICE)
-            {
+            if (transfer.direction != HOST_TO_DEVICE) {
                 return false;
             }
 
             /* Transfer must be equal to the size requested by the host */
-            if (transfer.remaining != transfer.setup.wLength)
-            {
+            if (transfer.remaining != transfer.setup.wLength) {
                 return false;
             }
         }
-    }
-    else
-    {
+    } else {
         /* No data stage; transfer size must be zero */
-        if (transfer.remaining != 0)
-        {
+        if (transfer.remaining != 0) {
             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)
-        {
+                == DEVICE_TO_HOST) {
             /* Check if we'll need to send a zero length packet at */
             /* the end of this transfer */
-            if (transfer.setup.wLength > transfer.remaining)
-            {
+            if (transfer.setup.wLength > transfer.remaining) {
                 /* Device wishes to transfer less than host requested */
-                if ((transfer.remaining % MAX_PACKET_SIZE_EP0) == 0)
-                {
+                if ((transfer.remaining % MAX_PACKET_SIZE_EP0) == 0) {
                     /* Transfer is a multiple of EP0 max packet size */
                     transfer.zlp = true;
                 }
@@ -656,15 +594,11 @@
 
             /* IN stage */
             controlIn();
-        }
-        else
-        {
+        } else {
             /* OUT stage */
             EP0read();
         }
-    }
-    else
-    {
+    } else {
         /* Status stage */
         EP0write(NULL, 0);
     }
@@ -685,8 +619,7 @@
 void USBDevice::EP0setupCallback(void)
 {
     /* Endpoint 0 setup event */
-    if (!controlSetup())
-    {
+    if (!controlSetup()) {
         /* Protocol stall */
         EP0stall();
     }
@@ -697,8 +630,7 @@
 void USBDevice::EP0out(void)
 {
     /* Endpoint 0 OUT data event */
-    if (!controlOut())
-    {
+    if (!controlOut()) {
         /* Protocol stall; this will stall both endpoints */
         EP0stall();
     }
@@ -710,8 +642,7 @@
     printf("EP0IN\r\n");
 #endif
     /* Endpoint 0 IN data event */
-    if (!controlIn())
-    {
+    if (!controlIn()) {
         /* Protocol stall; this will stall both endpoints */
         EP0stall();
     }
@@ -738,7 +669,7 @@
 {
     /* Disconnect device */
     USBHAL::disconnect();
-    
+
     /* Set initial device state */
     device.state = POWERED;
     device.configuration = 0;
@@ -761,47 +692,45 @@
     return realiseEndpoint(endpoint, maxPacket, RATE_FEEDBACK_MODE);
 }
 
-uint8_t * USBDevice::findDescriptor(uint8_t descriptorType)
+// Call only for descriptorType == HID_DESCRIPTOR
+uint8_t * USBDevice::findDescriptor(uint8_t descriptorType, uint_fast8_t cfgidx)
 {
-    /* Find a descriptor within the list of descriptors */
+     /* Find a descriptor within the list of descriptors */
     /* following a configuration descriptor. */
     uint16_t wTotalLength;
     uint8_t *ptr;
 
-    if (configurationDesc() == NULL)
-    {
+    if (configurationDesc(cfgidx) == NULL) {
         return NULL;
     }
 
     /* Check this is a configuration descriptor */
-    if ((configurationDesc()[0] != CONFIGURATION_DESCRIPTOR_LENGTH) \
-            || (configurationDesc()[1] != CONFIGURATION_DESCRIPTOR))
-    {
+    if ((configurationDesc(cfgidx)[0] != CONFIGURATION_DESCRIPTOR_LENGTH) \
+            || (configurationDesc(cfgidx)[1] != CONFIGURATION_DESCRIPTOR)) {
         return NULL;
     }
 
-    wTotalLength = configurationDesc()[2] | (configurationDesc()[3] << 8);
+    wTotalLength = configurationDesc(cfgidx)[2] | (configurationDesc(cfgidx)[3] << 8);
 
     /* Check there are some more descriptors to follow */
     if (wTotalLength <= (CONFIGURATION_DESCRIPTOR_LENGTH+2))
-    /* +2 is for bLength and bDescriptorType of next descriptor */
+        /* +2 is for bLength and bDescriptorType of next descriptor */
     {
         return NULL;
     }
 
     /* Start at first descriptor after the configuration descriptor */
-    ptr = &(configurationDesc()[CONFIGURATION_DESCRIPTOR_LENGTH]);
+    ptr = &(configurationDesc(cfgidx)[CONFIGURATION_DESCRIPTOR_LENGTH]);
 
     do {
-        if (ptr[1] /* bDescriptorType */ == descriptorType)
-        {
+        if (ptr[1] /* bDescriptorType */ == descriptorType) {
             /* Found */
             return ptr;
         }
 
         /* Skip to next descriptor */
         ptr += ptr[0]; /* bLength */
-    } while (ptr < (configurationDesc() + wTotalLength));
+    } while (ptr < (configurationDesc(cfgidx) + wTotalLength));
 
     /* Reached end of the descriptors - not found */
     return NULL;
@@ -817,7 +746,8 @@
 }
 
 
-USBDevice::USBDevice(uint16_t vendor_id, uint16_t product_id, uint16_t product_release){
+USBDevice::USBDevice(uint16_t vendor_id, uint16_t product_id, uint16_t product_release)
+{
     VENDOR_ID = vendor_id;
     PRODUCT_ID = product_id;
     PRODUCT_RELEASE = product_release;
@@ -839,8 +769,7 @@
 {
     EP_STATUS result;
 
-    if (size > maxSize)
-    {
+    if (size > maxSize) {
         return false;
     }
 
@@ -852,8 +781,7 @@
     /* Send report */
     result = endpointWrite(endpoint, buffer, size);
 
-    if (result != EP_PENDING)
-    {
+    if (result != EP_PENDING) {
         return false;
     }
 
@@ -870,8 +798,7 @@
 {
     EP_STATUS result;
 
-    if (size > maxSize)
-    {
+    if (size > maxSize) {
         return false;
     }
 
@@ -882,8 +809,7 @@
     /* Send report */
     result = endpointWrite(endpoint, buffer, size);
 
-    if (result != EP_PENDING)
-    {
+    if (result != EP_PENDING) {
         return false;
     }
 
@@ -926,7 +852,8 @@
 
 
 
-uint8_t * USBDevice::deviceDesc() {
+uint8_t * USBDevice::deviceDesc()
+{
     static uint8_t deviceDescriptor[] = {
         DEVICE_DESCRIPTOR_LENGTH,       /* bLength */
         DEVICE_DESCRIPTOR,              /* bDescriptorType */
@@ -950,7 +877,8 @@
     return deviceDescriptor;
 }
 
-uint8_t * USBDevice::stringLangidDesc() {
+uint8_t * USBDevice::stringLangidDesc()
+{
     static uint8_t stringLangidDescriptor[] = {
         0x04,               /*bLength*/
         STRING_DESCRIPTOR,  /*bDescriptorType 0x03*/
@@ -959,7 +887,8 @@
     return stringLangidDescriptor;
 }
 
-uint8_t * USBDevice::stringImanufacturerDesc() {
+uint8_t * USBDevice::stringImanufacturerDesc()
+{
     static uint8_t stringImanufacturerDescriptor[] = {
         0x12,                                            /*bLength*/
         STRING_DESCRIPTOR,                               /*bDescriptorType 0x03*/
@@ -968,7 +897,8 @@
     return stringImanufacturerDescriptor;
 }
 
-uint8_t * USBDevice::stringIserialDesc() {
+uint8_t * USBDevice::stringIserialDesc()
+{
     static uint8_t stringIserialDescriptor[] = {
         0x16,                                                           /*bLength*/
         STRING_DESCRIPTOR,                                              /*bDescriptorType 0x03*/
@@ -977,7 +907,8 @@
     return stringIserialDescriptor;
 }
 
-uint8_t * USBDevice::stringIConfigurationDesc() {
+uint8_t * USBDevice::stringIConfigurationDesc()
+{
     static uint8_t stringIconfigurationDescriptor[] = {
         0x06,               /*bLength*/
         STRING_DESCRIPTOR,  /*bDescriptorType 0x03*/
@@ -986,7 +917,8 @@
     return stringIconfigurationDescriptor;
 }
 
-uint8_t * USBDevice::stringIinterfaceDesc() {
+uint8_t * USBDevice::stringIinterfaceDesc()
+{
     static uint8_t stringIinterfaceDescriptor[] = {
         0x08,               /*bLength*/
         STRING_DESCRIPTOR,  /*bDescriptorType 0x03*/
@@ -995,7 +927,8 @@
     return stringIinterfaceDescriptor;
 }
 
-uint8_t * USBDevice::stringIproductDesc() {
+uint8_t * USBDevice::stringIproductDesc()
+{
     static uint8_t stringIproductDescriptor[] = {
         0x16,                                                       /*bLength*/
         STRING_DESCRIPTOR,                                          /*bDescriptorType 0x03*/
--- a/USBDevice/USBDevice.h	Mon Jul 30 12:30:04 2018 +0000
+++ b/USBDevice/USBDevice.h	Mon Jul 30 13:56:22 2018 +0000
@@ -176,7 +176,7 @@
     *
     * @returns pointer to the configuration descriptor
     */
-    virtual uint8_t * configurationDesc(){return NULL;};
+    virtual uint8_t * configurationDesc(uint_fast8_t cfgidx){return NULL;};
 
     /*
     * Get string lang id descriptor
@@ -236,7 +236,7 @@
     virtual void EP0in(void);
     virtual void connectStateChanged(unsigned int connected);
     virtual void suspendStateChanged(unsigned int suspended);
-    uint8_t * findDescriptor(uint8_t descriptorType);
+    uint8_t * findDescriptor(uint8_t descriptorType, uint_fast8_t cfgidx);
     CONTROL_TRANSFER * getTransferPtr(void);
 
     uint16_t VENDOR_ID;
--- a/USBHID/USBHID.cpp	Mon Jul 30 12:30:04 2018 +0000
+++ b/USBHID/USBHID.cpp	Mon Jul 30 13:56:22 2018 +0000
@@ -112,7 +112,7 @@
                         break;
                     case HID_DESCRIPTOR:
                             // Find the HID descriptor, after the configuration descriptor
-                            hidDescriptor = findDescriptor(HID_DESCRIPTOR);
+                            hidDescriptor = findDescriptor(HID_DESCRIPTOR, 0);
                             if (hidDescriptor != NULL)
                             {
                                 transfer->remaining = HID_DESCRIPTOR_LENGTH;
@@ -227,7 +227,7 @@
                                + (1 * HID_DESCRIPTOR_LENGTH) \
                                + (2 * ENDPOINT_DESCRIPTOR_LENGTH))
 
-uint8_t * USBHID::configurationDesc() {
+uint8_t * USBHID::configurationDesc(uint_fast8_t cfgidx) {
     static uint8_t configurationDescriptor[] = {
         CONFIGURATION_DESCRIPTOR_LENGTH,    // bLength
         CONFIGURATION_DESCRIPTOR,           // bDescriptorType
--- a/USBHID/USBHID.h	Mon Jul 30 12:30:04 2018 +0000
+++ b/USBHID/USBHID.h	Mon Jul 30 13:56:22 2018 +0000
@@ -132,7 +132,7 @@
     *
     * @returns pointer to the configuration descriptor
     */
-    virtual uint8_t * configurationDesc();
+    virtual uint8_t * configurationDesc(uint_fast8_t cfgidx);
 
 
     /*
@@ -170,3 +170,4 @@
 };
 
 #endif
+
--- a/USBHID/USBKeyboard.cpp	Mon Jul 30 12:30:04 2018 +0000
+++ b/USBHID/USBKeyboard.cpp	Mon Jul 30 13:56:22 2018 +0000
@@ -501,7 +501,7 @@
                                + (1 * HID_DESCRIPTOR_LENGTH) \
                                + (2 * ENDPOINT_DESCRIPTOR_LENGTH))
 
-uint8_t * USBKeyboard::configurationDesc() {
+uint8_t * USBKeyboard::configurationDesc(uint_fast8_t cfgidx) {
     static uint8_t configurationDescriptor[] = {
         CONFIGURATION_DESCRIPTOR_LENGTH,    // bLength
         CONFIGURATION_DESCRIPTOR,           // bDescriptorType
@@ -551,3 +551,4 @@
     };
     return configurationDescriptor;
 }
+
--- a/USBHID/USBKeyboard.h	Mon Jul 30 12:30:04 2018 +0000
+++ b/USBHID/USBKeyboard.h	Mon Jul 30 13:56:22 2018 +0000
@@ -173,7 +173,7 @@
     *
     * @returns pointer to the configuration descriptor
     */
-    virtual uint8_t * configurationDesc();
+    virtual uint8_t * configurationDesc(uint_fast8_t cfgidx);
 
 private:
     //dummy otherwise it doesn,t compile (we must define all methods of an abstract class)
@@ -186,3 +186,4 @@
 };
 
 #endif
+
--- a/USBMIDI/USBMIDI.cpp	Mon Jul 30 12:30:04 2018 +0000
+++ b/USBMIDI/USBMIDI.cpp	Mon Jul 30 13:56:22 2018 +0000
@@ -176,7 +176,7 @@
 }
 
 
-uint8_t * USBMIDI::configurationDesc() {
+uint8_t * USBMIDI::configurationDesc(uint_fast8_t cfgidx) {
     static uint8_t configDescriptor[] = {
         // configuration descriptor
         0x09, 0x02, 0x65, 0x00, 0x02, 0x01, 0x00, 0xc0, 0x50,
@@ -205,3 +205,4 @@
     };
     return configDescriptor;
 }
+
--- a/USBMIDI/USBMIDI.h	Mon Jul 30 12:30:04 2018 +0000
+++ b/USBMIDI/USBMIDI.h	Mon Jul 30 13:56:22 2018 +0000
@@ -99,7 +99,7 @@
     *
     * @returns pointer to the configuration descriptor
     */
-    virtual uint8_t * configurationDesc();
+    virtual uint8_t * configurationDesc(uint_fast8_t cfgidx);
 
 private:
     uint8_t data[MAX_MIDI_MESSAGE_SIZE+1];
@@ -110,3 +110,4 @@
 };
 
 #endif
+
--- a/USBMSD/USBMSD.cpp	Mon Jul 30 12:30:04 2018 +0000
+++ b/USBMSD/USBMSD.cpp	Mon Jul 30 13:56:22 2018 +0000
@@ -608,7 +608,7 @@
 }
 
 
-uint8_t * USBMSD::configurationDesc() {
+uint8_t * USBMSD::configurationDesc(uint_fast8_t cfgidx) {
     static uint8_t configDescriptor[] = {
 
         // Configuration 1
@@ -653,3 +653,4 @@
     };
     return configDescriptor;
 }
+
--- a/USBMSD/USBMSD.h	Mon Jul 30 12:30:04 2018 +0000
+++ b/USBMSD/USBMSD.h	Mon Jul 30 13:56:22 2018 +0000
@@ -153,7 +153,7 @@
     *
     * @returns pointer to the configuration descriptor
     */
-    virtual uint8_t * configurationDesc();
+    virtual uint8_t * configurationDesc(uint_fast8_t cfgidx);
 
     /*
     * Callback called when a packet is received
@@ -249,3 +249,4 @@
 };
 
 #endif
+
--- a/USBSerial/USBCDC.cpp	Mon Jul 30 12:30:04 2018 +0000
+++ b/USBSerial/USBCDC.cpp	Mon Jul 30 13:56:22 2018 +0000
@@ -185,7 +185,7 @@
 
 #define CONFIG1_DESC_SIZE (9+8+9+5+5+4+5+7+9+7+7)
 
-uint8_t * USBCDC::configurationDesc() {
+uint8_t * USBCDC::configurationDesc(uint_fast8_t cfgidx) {
     static uint8_t configDescriptor[] = {
         // configuration descriptor
         9,                      // bLength
@@ -288,3 +288,4 @@
     };
     return configDescriptor;
 }
+
--- a/USBSerial/USBCDC.h	Mon Jul 30 12:30:04 2018 +0000
+++ b/USBSerial/USBCDC.h	Mon Jul 30 13:56:22 2018 +0000
@@ -67,7 +67,7 @@
     *
     * @returns pointer to the configuration descriptor
     */
-    virtual uint8_t * configurationDesc();
+    virtual uint8_t * configurationDesc(uint_fast8_t cfgidx);
 
     /*
     * Send a buffer