USBAudio example using a microphone

Dependencies:   USBDevice mbed

Files at this revision

API Documentation at this revision

Comitter:
samux
Date:
Wed Dec 21 10:43:57 2011 +0000
Parent:
7:6b0012b8fd01
Child:
9:9de252a14cde
Commit message:
we can have audioIN and audioOUT in the same usbdevice

Changed in this revision

USBDevice/USBAudio/USBAudio.cpp Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBAudio/USBAudio.h Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBAudio/USBAudio_Types.h Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBDevice/USBDevice.cpp Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/USBAudio/USBAudio.cpp	Wed Dec 21 10:43:57 2011 +0000
@@ -0,0 +1,567 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBAudio.h"
+#include "USBBusInterface.h"
+#include "USBAudio_Types.h"
+
+
+
+USBAudio::USBAudio(uint32_t frequency, uint8_t channel_nb, uint16_t vendor_id, uint16_t product_id, uint16_t product_release): USBDevice(vendor_id, product_id, product_release) {
+    mute = 0;
+    volCur = 0x0080;
+    volMin = 0x0000;
+    volMax = 0x0100;
+    volRes = 0x0004;
+    available = false;
+
+    FREQ = frequency;
+
+    this->channel_nb = channel_nb;
+
+    // stereo -> *2, mono -> *1
+    PACKET_SIZE_ISO = (FREQ / 500) * channel_nb;
+
+    // STEREO -> left and right
+    channel_config = (channel_nb == 1) ? CHANNEL_M : CHANNEL_L + CHANNEL_R;
+
+    SOF_handler = false;
+
+    buf_stream = NULL;
+
+    interrupt = false;
+
+    volume = 0;
+
+    // connect the device
+    USBDevice::connect();
+}
+
+bool USBAudio::read(uint8_t * buf) {
+    buf_stream = buf;
+    SOF_handler = false;
+    while (!available && !SOF_handler);
+    available = false;
+    buf_stream = NULL;
+    return true;
+}
+
+bool USBAudio::readNB(uint8_t * buf) {
+    buf_stream = buf;
+    SOF_handler = false;
+    while (!SOF_handler);
+    if (available) {
+        available = false;
+        buf_stream = NULL;
+        return true;
+    }
+    buf_stream = NULL;
+    return false;
+}
+
+
+float USBAudio::getVolume() {
+    return (mute) ? 0.0 : volume;
+}
+
+
+bool USBAudio::EP3_OUT_callback() {
+    uint16_t size = 0;
+    interrupt = true;
+    if (buf_stream != NULL) {
+        readEP(EP3OUT, (uint8_t *)buf_stream, &size, PACKET_SIZE_ISO);
+        available = true;
+    }
+    readStart(EP3OUT, PACKET_SIZE_ISO);
+    return false;
+}
+
+
+
+// Called in ISR context on each start of frame
+void USBAudio::SOF(int frameNumber) {
+    uint16_t size = 0;
+
+    if (interrupt) {
+        return;
+    }
+
+
+    // read the isochronous endpoint
+    if (buf_stream != NULL) {
+        if (USBDevice::readEP_NB(EP3OUT, (uint8_t *)buf_stream, &size, PACKET_SIZE_ISO)) {
+            available = true;
+        }
+    }
+
+    readStart(EP3OUT, PACKET_SIZE_ISO);
+
+    SOF_handler = true;
+}
+
+
+// Called in ISR context
+// Set configuration. Return false if the configuration is not supported.
+bool USBAudio::USBCallback_setConfiguration(uint8_t configuration) {
+    if (configuration != DEFAULT_CONFIGURATION) {
+        return false;
+    }
+
+    // Configure isochronous endpoint
+    realiseEndpoint(EP3OUT, PACKET_SIZE_ISO, ISOCHRONOUS);
+    realiseEndpoint(EP3IN, PACKET_SIZE_ISO, ISOCHRONOUS);
+
+    // activate readings on this endpoint
+    readStart(EP3OUT, PACKET_SIZE_ISO);
+    return true;
+}
+
+
+// Called in ISR context
+// Set alternate setting. Return false if the alternate setting is not supported
+bool USBAudio::USBCallback_setInterface(uint16_t interface, uint8_t alternate) {
+    if (interface == 0 && alternate == 0) {
+        return true;
+    }
+    if (interface == 1 && (alternate == 0 || alternate == 1)) {
+        return true;
+    }
+    if (interface == 2 && (alternate == 0 || alternate == 1)) {
+        return true;
+    }
+    return false;
+}
+
+
+
+// Called in ISR context
+// Called by USBDevice on Endpoint0 request
+// This is used to handle extensions to standard requests and class specific requests.
+// Return true if class handles this request
+bool USBAudio::USBCallback_request() {
+    bool success = false;
+    CONTROL_TRANSFER * transfer = getTransferPtr();
+
+    // Process class-specific requests
+    if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
+
+        // Feature Unit: Interface = 0, ID = 2
+        if (transfer->setup.wIndex == 0x0200) {
+
+            // Master Channel
+            if ((transfer->setup.wValue & 0xff) == 0) {
+
+                switch (transfer->setup.wValue >> 8) {
+                    case MUTE_CONTROL:
+                        switch (transfer->setup.bRequest) {
+                            case REQUEST_GET_CUR:
+                                transfer->remaining = 1;
+                                transfer->ptr = &mute;
+                                transfer->direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+
+                            case REQUEST_SET_CUR:
+                                transfer->remaining = 1;
+                                transfer->notify = true;
+                                transfer->direction = HOST_TO_DEVICE;
+                                success = true;
+                                break;
+                            default:
+                                break;
+                        }
+                        break;
+                    case VOLUME_CONTROL:
+                        switch (transfer->setup.bRequest) {
+                            case REQUEST_GET_CUR:
+                                transfer->remaining = 2;
+                                transfer->ptr = (uint8_t *)&volCur;
+                                transfer->direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+                            case REQUEST_GET_MIN:
+                                transfer->remaining = 2;
+                                transfer->ptr = (uint8_t *)&volMin;
+                                transfer->direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+                            case REQUEST_GET_MAX:
+                                transfer->remaining = 2;
+                                transfer->ptr = (uint8_t *)&volMax;
+                                transfer->direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+                            case REQUEST_GET_RES:
+                                transfer->remaining = 2;
+                                transfer->ptr = (uint8_t *)&volRes;
+                                transfer->direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+
+                            case REQUEST_SET_CUR:
+                                transfer->remaining = 2;
+                                transfer->notify = true;
+                                transfer->direction = HOST_TO_DEVICE;
+                                success = true;
+                                break;
+                            case REQUEST_SET_MIN:
+                                transfer->remaining = 2;
+                                transfer->notify = true;
+                                transfer->direction = HOST_TO_DEVICE;
+                                success = true;
+                                break;
+                            case REQUEST_SET_MAX:
+                                transfer->remaining = 2;
+                                transfer->notify = true;
+                                transfer->direction = HOST_TO_DEVICE;
+                                success = true;
+                                break;
+                            case REQUEST_SET_RES:
+                                transfer->remaining = 2;
+                                transfer->notify = true;
+                                transfer->direction = HOST_TO_DEVICE;
+                                success = true;
+                                break;
+                        }
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+    }
+    return success;
+}
+
+
+// Called in ISR context when a data OUT stage has been performed
+void USBAudio::USBCallback_requestCompleted(uint8_t * buf, uint16_t length) {
+    uint16_t data = *((uint16_t *)buf);
+    CONTROL_TRANSFER * transfer = getTransferPtr();
+    switch (transfer->setup.wValue >> 8) {
+        case MUTE_CONTROL:
+            switch (transfer->setup.bRequest) {
+                case REQUEST_SET_CUR:
+                    mute = data & 0xff;
+                    updateVol.call();
+                    break;
+                default:
+                    break;
+            }
+            break;
+        case VOLUME_CONTROL:
+            switch (transfer->setup.bRequest) {
+                case REQUEST_SET_CUR:
+                    volCur = data;
+                    volume = (float)volCur/(float)volMax;
+                    updateVol.call();
+                    break;
+                default:
+                    break;
+            }
+            break;
+        default:
+            break;
+    }
+}
+
+
+
+#define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
+                               + (5 * INTERFACE_DESCRIPTOR_LENGTH) \
+                               + (1 * CONTROL_INTERFACE_DESCRIPTOR_LENGTH + 1) \
+                               + (2 * INPUT_TERMINAL_DESCRIPTOR_LENGTH) \
+                               + (1 * FEATURE_UNIT_DESCRIPTOR_LENGTH) \
+                               + (2 * OUTPUT_TERMINAL_DESCRIPTOR_LENGTH) \
+                               + (2 * STREAMING_INTERFACE_DESCRIPTOR_LENGTH) \
+                               + (2 * FORMAT_TYPE_I_DESCRIPTOR_LENGTH) \
+                               + (2 * (ENDPOINT_DESCRIPTOR_LENGTH + 2)) \
+                               + (2 * STREAMING_ENDPOINT_DESCRIPTOR_LENGTH) )
+
+#define TOTAL_CONTROL_INTF_LENGTH    (CONTROL_INTERFACE_DESCRIPTOR_LENGTH + 1 + \
+                                      2*INPUT_TERMINAL_DESCRIPTOR_LENGTH     + \
+                                      FEATURE_UNIT_DESCRIPTOR_LENGTH    + \
+                                      2*OUTPUT_TERMINAL_DESCRIPTOR_LENGTH)
+
+uint8_t * USBAudio::configurationDesc() {
+    static uint8_t configDescriptor[] = {
+        // Configuration 1
+        CONFIGURATION_DESCRIPTOR_LENGTH,        // bLength
+        CONFIGURATION_DESCRIPTOR,               // bDescriptorType
+        LSB(TOTAL_DESCRIPTOR_LENGTH),           // wTotalLength (LSB)
+        MSB(TOTAL_DESCRIPTOR_LENGTH),           // wTotalLength (MSB)
+        0x03,                                   // bNumInterfaces
+        DEFAULT_CONFIGURATION,                  // bConfigurationValue
+        0x00,                                   // iConfiguration
+        0x80,                                   // bmAttributes
+        50,                                     // bMaxPower
+
+        // Interface 0, Alternate Setting 0, Audio Control
+        INTERFACE_DESCRIPTOR_LENGTH,            // bLength
+        INTERFACE_DESCRIPTOR,                   // bDescriptorType
+        0x00,                                   // bInterfaceNumber
+        0x00,                                   // bAlternateSetting
+        0x00,                                   // bNumEndpoints
+        AUDIO_CLASS,                            // bInterfaceClass
+        SUBCLASS_AUDIOCONTROL,                  // bInterfaceSubClass
+        0x00,                                   // bInterfaceProtocol
+        0x00,                                   // iInterface
+
+
+        // Audio Control Interface
+        CONTROL_INTERFACE_DESCRIPTOR_LENGTH + 1,    // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        CONTROL_HEADER,                         // bDescriptorSubtype
+        LSB(0x0100),                            // bcdADC (LSB)
+        MSB(0x0100),                            // bcdADC (MSB)
+        LSB(TOTAL_CONTROL_INTF_LENGTH),         // wTotalLength
+        MSB(TOTAL_CONTROL_INTF_LENGTH),         // wTotalLength
+        0x02,                                   // bInCollection
+        0x01,                                   // baInterfaceNr
+        0x02,                                   // baInterfaceNr
+
+        // Audio Input Terminal (Speaker)
+        INPUT_TERMINAL_DESCRIPTOR_LENGTH,       // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        CONTROL_INPUT_TERMINAL,                 // bDescriptorSubtype
+        0x01,                                   // bTerminalID
+        LSB(TERMINAL_USB_STREAMING),            // wTerminalType
+        MSB(TERMINAL_USB_STREAMING),            // wTerminalType
+        0x00,                                   // bAssocTerminal
+        channel_nb,                             // bNrChannels
+        LSB(channel_config),                    // wChannelConfig
+        MSB(channel_config),                    // wChannelConfig
+        0x00,                                   // iChannelNames
+        0x00,                                   // iTerminal
+
+        // Audio Feature Unit (Speaker)
+        FEATURE_UNIT_DESCRIPTOR_LENGTH,         // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        CONTROL_FEATURE_UNIT,                   // bDescriptorSubtype
+        0x02,                                   // bUnitID
+        0x01,                                   // bSourceID
+        0x01,                                   // bControlSize
+        CONTROL_MUTE |
+        CONTROL_VOLUME,                         // bmaControls(0)
+        0x00,                                   // bmaControls(1)
+        0x00,                                   // iTerminal
+
+        // Audio Output Terminal (Speaker)
+        OUTPUT_TERMINAL_DESCRIPTOR_LENGTH,      // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        CONTROL_OUTPUT_TERMINAL,                // bDescriptorSubtype
+        0x03,                                   // bTerminalID
+        LSB(TERMINAL_SPEAKER),                  // wTerminalType
+        MSB(TERMINAL_SPEAKER),                  // wTerminalType
+        0x00,                                   // bAssocTerminal
+        0x02,                                   // bSourceID
+        0x00,                                   // iTerminal
+        
+        
+        // Audio Input Terminal (Microphone)
+        INPUT_TERMINAL_DESCRIPTOR_LENGTH,       // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        CONTROL_INPUT_TERMINAL,                 // bDescriptorSubtype
+        0x04,                                   // bTerminalID
+        LSB(TERMINAL_MICROPHONE),               // wTerminalType
+        MSB(TERMINAL_MICROPHONE),               // wTerminalType
+        0x00,                                   // bAssocTerminal
+        channel_nb,                             // bNrChannels
+        LSB(channel_config),                    // wChannelConfig
+        MSB(channel_config),                    // wChannelConfig
+        0x00,                                   // iChannelNames
+        0x00,                                   // iTerminal
+
+        // Audio Output Terminal (Microphone)
+        OUTPUT_TERMINAL_DESCRIPTOR_LENGTH,      // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        CONTROL_OUTPUT_TERMINAL,                // bDescriptorSubtype
+        0x05,                                   // bTerminalID
+        LSB(TERMINAL_USB_STREAMING),            // wTerminalType
+        MSB(TERMINAL_USB_STREAMING),            // wTerminalType
+        0x00,                                   // bAssocTerminal
+        0x04,                                   // bSourceID
+        0x00,                                   // iTerminal
+
+
+
+
+
+
+        // Interface 1, Alternate Setting 0, Audio Streaming - Zero Bandwith
+        INTERFACE_DESCRIPTOR_LENGTH,            // bLength
+        INTERFACE_DESCRIPTOR,                   // bDescriptorType
+        0x01,                                   // bInterfaceNumber
+        0x00,                                   // bAlternateSetting
+        0x00,                                   // bNumEndpoints
+        AUDIO_CLASS,                            // bInterfaceClass
+        SUBCLASS_AUDIOSTREAMING,                // bInterfaceSubClass
+        0x00,                                   // bInterfaceProtocol
+        0x00,                                   // iInterface
+
+        // Interface 1, Alternate Setting 1, Audio Streaming - Operational
+        INTERFACE_DESCRIPTOR_LENGTH,            // bLength
+        INTERFACE_DESCRIPTOR,                   // bDescriptorType
+        0x01,                                   // bInterfaceNumber
+        0x01,                                   // bAlternateSetting
+        0x01,                                   // bNumEndpoints
+        AUDIO_CLASS,                            // bInterfaceClass
+        SUBCLASS_AUDIOSTREAMING,                // bInterfaceSubClass
+        0x00,                                   // bInterfaceProtocol
+        0x00,                                   // iInterface
+
+        // Audio Streaming Interface
+        STREAMING_INTERFACE_DESCRIPTOR_LENGTH,  // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        STREAMING_GENERAL,                      // bDescriptorSubtype
+        0x01,                                   // bTerminalLink
+        0x00,                                   // bDelay
+        LSB(FORMAT_PCM),                        // wFormatTag
+        MSB(FORMAT_PCM),                        // wFormatTag
+
+        // Audio Type I Format
+        FORMAT_TYPE_I_DESCRIPTOR_LENGTH,        // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        STREAMING_FORMAT_TYPE,                  // bDescriptorSubtype
+        FORMAT_TYPE_I,                          // bFormatType
+        channel_nb,                             // bNrChannels
+        0x02,                                   // bSubFrameSize
+        16,                                     // bBitResolution
+        0x01,                                   // bSamFreqType
+        LSB(FREQ),                              // tSamFreq
+        (FREQ >> 8) & 0xff,                     // tSamFreq
+        (FREQ >> 16) & 0xff,                    // tSamFreq
+
+        // Endpoint - Standard Descriptor
+        ENDPOINT_DESCRIPTOR_LENGTH + 2,         // bLength
+        ENDPOINT_DESCRIPTOR,                    // bDescriptorType
+        PHY_TO_DESC(EPISO_OUT),                 // bEndpointAddress
+        E_ISOCHRONOUS,                          // bmAttributes
+        LSB(PACKET_SIZE_ISO),                   // wMaxPacketSize
+        MSB(PACKET_SIZE_ISO),                   // wMaxPacketSize
+        0x01,                                   // bInterval
+        0x00,                                   // bRefresh
+        0x00,                                   // bSynchAddress
+
+        // Endpoint - Audio Streaming
+        STREAMING_ENDPOINT_DESCRIPTOR_LENGTH,   // bLength
+        ENDPOINT_DESCRIPTOR_TYPE,               // bDescriptorType
+        ENDPOINT_GENERAL,                       // bDescriptor
+        0x00,                                   // bmAttributes
+        0x00,                                   // bLockDelayUnits
+        LSB(0x0000),                            // wLockDelay
+        MSB(0x0000),                            // wLockDelay
+        
+        
+        
+        
+        
+        
+        
+        // Interface 1, Alternate Setting 0, Audio Streaming - Zero Bandwith
+        INTERFACE_DESCRIPTOR_LENGTH,            // bLength
+        INTERFACE_DESCRIPTOR,                   // bDescriptorType
+        0x02,                                   // bInterfaceNumber
+        0x00,                                   // bAlternateSetting
+        0x00,                                   // bNumEndpoints
+        AUDIO_CLASS,                            // bInterfaceClass
+        SUBCLASS_AUDIOSTREAMING,                // bInterfaceSubClass
+        0x00,                                   // bInterfaceProtocol
+        0x00,                                   // iInterface
+
+        // Interface 1, Alternate Setting 1, Audio Streaming - Operational
+        INTERFACE_DESCRIPTOR_LENGTH,            // bLength
+        INTERFACE_DESCRIPTOR,                   // bDescriptorType
+        0x02,                                   // bInterfaceNumber
+        0x01,                                   // bAlternateSetting
+        0x01,                                   // bNumEndpoints
+        AUDIO_CLASS,                            // bInterfaceClass
+        SUBCLASS_AUDIOSTREAMING,                // bInterfaceSubClass
+        0x00,                                   // bInterfaceProtocol
+        0x00,                                   // iInterface
+
+        // Audio Streaming Interface
+        STREAMING_INTERFACE_DESCRIPTOR_LENGTH,  // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        SUBCLASS_AUDIOCONTROL,                  // bDescriptorSubtype
+        0x05,                                   // bTerminalLink (output terminal microphone)
+        0x01,                                   // bDelay
+        0x01,                                   // wFormatTag
+        0x00,                                   // wFormatTag
+
+        // Audio Type I Format
+        FORMAT_TYPE_I_DESCRIPTOR_LENGTH,        // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        SUBCLASS_AUDIOSTREAMING,                // bDescriptorSubtype
+        FORMAT_TYPE_I,                          // bFormatType
+        channel_nb,                             // bNrChannels
+        0x02,                                   // bSubFrameSize
+        0x10,                                   // bBitResolution
+        0x01,                                   // bSamFreqType
+        LSB(FREQ),                              // tSamFreq
+        (FREQ >> 8) & 0xff,                     // tSamFreq
+        (FREQ >> 16) & 0xff,                    // tSamFreq
+
+        // Endpoint - Standard Descriptor
+        ENDPOINT_DESCRIPTOR_LENGTH + 2,         // bLength
+        ENDPOINT_DESCRIPTOR,                    // bDescriptorType
+        PHY_TO_DESC(EPISO_IN),                  // bEndpointAddress
+        E_ISOCHRONOUS,                          // bmAttributes
+        LSB(PACKET_SIZE_ISO),                   // wMaxPacketSize
+        MSB(PACKET_SIZE_ISO),                   // wMaxPacketSize
+        0x01,                                   // bInterval
+        0x00,                                   // bRefresh
+        0x00,                                   // bSynchAddress
+
+        // Endpoint - Audio Streaming
+        STREAMING_ENDPOINT_DESCRIPTOR_LENGTH,   // bLength
+        ENDPOINT_DESCRIPTOR_TYPE,               // bDescriptorType
+        ENDPOINT_GENERAL,                       // bDescriptor
+        0x00,                                   // bmAttributes
+        0x00,                                   // bLockDelayUnits
+        LSB(0x0000),                            // wLockDelay
+        MSB(0x0000),                            // wLockDelay
+        
+        
+        
+        
+
+        // Terminator
+        0                                       // bLength
+    };
+    return configDescriptor;
+}
+
+uint8_t * USBAudio::stringIinterfaceDesc() {
+    static uint8_t stringIinterfaceDescriptor[] = {
+        0x0c,                           //bLength
+        STRING_DESCRIPTOR,              //bDescriptorType 0x03
+        'A',0,'u',0,'d',0,'i',0,'o',0   //bString iInterface - Audio
+    };
+    return stringIinterfaceDescriptor;
+}
+
+uint8_t * USBAudio::stringIproductDesc() {
+    static uint8_t stringIproductDescriptor[] = {
+        0x16,                                                       //bLength
+        STRING_DESCRIPTOR,                                          //bDescriptorType 0x03
+        'M',0,'b',0,'e',0,'d',0,' ',0,'A',0,'u',0,'d',0,'i',0,'o',0 //bString iProduct - Mbed Audio
+    };
+    return stringIproductDescriptor;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/USBAudio/USBAudio.h	Wed Dec 21 10:43:57 2011 +0000
@@ -0,0 +1,243 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBAudio_H
+#define USBAudio_H
+
+/* These headers are included for child class. */
+#include "USBEndpoints.h"
+#include "USBDescriptor.h"
+#include "USBDevice_Types.h"
+
+#include "USBDevice.h"
+
+
+/**
+* USBAudio example
+*
+* #include "mbed.h"
+* #include "USBAudio.h"
+*
+* Serial pc(USBTX, USBRX);
+*
+* // frequency: 48 kHz
+* #define FREQ 48000
+*
+* // 1 channel: mono
+* #define NB_CHA 1
+*
+* // length of an audio packet: each ms, we receive 48 * 16bits ->48 * 2 bytes. as there is one channel, the length will be 48 * 2 * 1
+* #define AUDIO_LENGTH_PACKET 48 * 2 * 1
+*
+* // USBAudio
+* USBAudio audio(FREQ, NB_CHA);
+*
+* int main() {
+*    int16_t buf[AUDIO_LENGTH_PACKET/2];
+*    
+*    while (1) {
+*        // read an audio packet
+*        audio.read((uint8_t *)buf);
+*
+*
+*        // print packet received
+*        pc.printf("recv: ");
+*        for(int i = 0; i < AUDIO_LENGTH_PACKET/2; i++) {
+*            pc.printf("%d ", buf[i]);
+*        }
+*        pc.printf("\r\n");
+*    }
+* }
+* @endcode
+*/
+class USBAudio: public USBDevice {
+public:
+
+    /**
+    * Constructor
+    *
+    * @param frequency frequency in Hz (default: 48000)
+    * @param channel_nb channel number (1 or 2) (default: 1)
+    * @param vendor_id Your vendor_id
+    * @param product_id Your product_id
+    * @param product_release Your preoduct_release
+    */
+    USBAudio(uint32_t frequency = 48000, uint8_t channel_nb = 1, uint16_t vendor_id = 0x7bb8, uint16_t product_id = 0x1111, uint16_t product_release = 0x0100);
+
+    /**
+    * Get current volume between 0.0 and 1.0
+    *
+    * @returns volume
+    */
+    float getVolume();
+    
+    /**
+    * Read an audio packet. warning: blocking
+    *
+    * @param buf pointer on a buffer which will be filled with an audio packet
+    *
+    * @returns true if successfull
+    */
+    bool read(uint8_t * buf);
+    
+    /**
+    * Try to read an audio packet. warning: non blocking
+    *
+    * @param buf pointer on a buffer which will be filled if an audio packet is available
+    *
+    * @returns true if successfull
+    */
+    bool readNB(uint8_t * buf);
+    
+
+    /** attach a handler to update the volume
+     *
+     * @param function Function to attach
+     *
+     */
+    void attach(void(*fptr)(void)) {
+        updateVol.attach(fptr);
+    }
+
+    /** Attach a nonstatic void/void member function to update the volume
+     *
+     * @param tptr Object pointer
+     * @param mptr Member function pointer
+     *
+     */
+    template<typename T>
+    void attach(T *tptr, void(T::*mptr)(void)) {
+        updateVol.attach(tptr, mptr);
+    }
+
+
+protected:
+
+    /*
+    * Called by USBDevice layer. Set configuration of the device.
+    * For instance, you can add all endpoints that you need on this function.
+    *
+    * @param configuration Number of the configuration
+    * @returns true if class handles this request
+    */
+    virtual bool USBCallback_setConfiguration(uint8_t configuration);
+
+    /*
+    * Called by USBDevice on Endpoint0 request. Warning: Called in ISR context
+    * This is used to handle extensions to standard requests
+    * and class specific requests
+    *
+    * @returns true if class handles this request
+    */
+    virtual bool USBCallback_request();
+
+    /*
+    * Get string product descriptor
+    *
+    * @returns pointer to the string product descriptor
+    */
+    virtual uint8_t * stringIproductDesc();
+
+    /*
+    * Get string interface descriptor
+    *
+    * @returns pointer to the string interface descriptor
+    */
+    virtual uint8_t * stringIinterfaceDesc();
+
+    /*
+    * Get configuration descriptor
+    *
+    * @returns pointer to the configuration descriptor
+    */
+    virtual uint8_t * configurationDesc();
+
+    /*
+     * Called by USBDevice layer. Set interface/alternate of the device.
+     *
+     * @param interface Number of the interface to be configured
+     * @param alternate Number of the alternate to be configured
+     * @returns true if class handles this request
+     */
+    virtual bool USBCallback_setInterface(uint16_t interface, uint8_t alternate);
+
+    /*
+    * Called by USBDevice on Endpoint0 request completion
+    * if the 'notify' flag has been set to true. Warning: Called in ISR context
+    *
+    * In this case it is used to indicate that a HID report has
+    * been received from the host on endpoint 0
+    *
+    * @param buf buffer received on endpoint 0
+    * @param length length of this buffer
+    */
+    virtual void USBCallback_requestCompleted(uint8_t * buf, uint16_t length);
+
+    /*
+    * Callback called on each Start of Frame event
+    */
+    virtual void SOF(int frameNumber);
+    virtual bool EP3_OUT_callback();
+
+private:
+
+    // stream available ?
+    volatile bool available;
+    volatile bool interrupt;
+
+    // FREQ
+    uint32_t FREQ;
+
+    // size of the maximum packet for the isochronous endpoint
+    uint32_t PACKET_SIZE_ISO;
+
+    // mono, stereo,...
+    uint8_t channel_nb;
+    
+    // channel config: master, left, right
+    uint8_t channel_config;
+
+    // mute state
+    uint8_t mute;
+
+    // Volume Current Value
+    uint16_t volCur;
+
+    // Volume Minimum Value
+    uint16_t volMin;
+
+    // Volume Maximum Value
+    uint16_t volMax;
+
+    // Volume Resolution
+    uint16_t volRes;
+
+    // Buffer containing one audio packet
+    volatile uint8_t * buf_stream;
+    
+    // callback to update volume
+    FunctionPointer updateVol;
+    
+    // boolean showing that the SOF handler has been called. Useful for readNB.
+    volatile bool SOF_handler;
+    
+    volatile float volume;
+
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/USBAudio/USBAudio_Types.h	Wed Dec 21 10:43:57 2011 +0000
@@ -0,0 +1,97 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBAUDIO_TYPES_H
+#define USBAUDIO_TYPES_H
+
+
+#define DEFAULT_CONFIGURATION (1)
+
+// Audio Request Codes
+#define REQUEST_SET_CUR     0x01
+#define REQUEST_GET_CUR     0x81
+#define REQUEST_SET_MIN     0x02
+#define REQUEST_GET_MIN     0x82
+#define REQUEST_SET_MAX     0x03
+#define REQUEST_GET_MAX     0x83
+#define REQUEST_SET_RES     0x04
+#define REQUEST_GET_RES     0x84
+
+#define MUTE_CONTROL        0x01
+#define VOLUME_CONTROL      0x02
+
+
+// Audio Descriptor Sizes
+#define CONTROL_INTERFACE_DESCRIPTOR_LENGTH       0x09
+#define STREAMING_INTERFACE_DESCRIPTOR_LENGTH     0x07
+#define INPUT_TERMINAL_DESCRIPTOR_LENGTH          0x0C
+#define OUTPUT_TERMINAL_DESCRIPTOR_LENGTH         0x09
+#define FEATURE_UNIT_DESCRIPTOR_LENGTH            0x09
+#define STREAMING_ENDPOINT_DESCRIPTOR_LENGTH      0x07
+
+// Audio Format Type Descriptor Sizes
+#define FORMAT_TYPE_I_DESCRIPTOR_LENGTH   0x0b
+
+#define AUDIO_CLASS                       0x01
+#define SUBCLASS_AUDIOCONTROL             0x01
+#define SUBCLASS_AUDIOSTREAMING           0x02
+
+// Audio Descriptor Types
+#define INTERFACE_DESCRIPTOR_TYPE         0x24
+#define ENDPOINT_DESCRIPTOR_TYPE          0x25
+
+// Audio Control Interface Descriptor Subtypes
+#define CONTROL_HEADER                    0x01
+#define CONTROL_INPUT_TERMINAL            0x02
+#define CONTROL_OUTPUT_TERMINAL           0x03
+#define CONTROL_FEATURE_UNIT              0x06
+
+// USB Terminal Types
+#define TERMINAL_USB_STREAMING            0x0101
+
+// Predefined Audio Channel Configuration Bits
+// Mono
+#define CHANNEL_M                         0x0000
+#define CHANNEL_L                         0x0001  /* Left Front */
+#define CHANNEL_R                         0x0002  /* Right Front */
+
+// Feature Unit Control Bits
+#define CONTROL_MUTE                      0x0001
+#define CONTROL_VOLUME                    0x0002
+
+/*  Input Terminal Types */
+#define TERMINAL_MICROPHONE               0x0201
+
+// Output Terminal Types
+#define TERMINAL_SPEAKER                  0x0301
+#define TERMINAL_HEADPHONES               0x0302
+
+// Audio Streaming Interface Descriptor Subtypes
+#define STREAMING_GENERAL                 0x01
+#define STREAMING_FORMAT_TYPE             0x02
+
+// Audio Data Format Type I Codes
+#define FORMAT_PCM                        0x0001
+
+// Audio Format Types
+#define FORMAT_TYPE_I                     0x01
+
+// Audio Endpoint Descriptor Subtypes
+#define ENDPOINT_GENERAL                  0x01
+
+#endif
--- a/USBDevice/USBDevice/USBDevice.cpp	Tue Dec 20 11:41:31 2011 +0000
+++ b/USBDevice/USBDevice/USBDevice.cpp	Wed Dec 21 10:43:57 2011 +0000
@@ -12,6 +12,8 @@
 #include "USBDescriptor.h"
 #include "USBHID_Types.h"
 
+//#define DEBUG
+
 
 /* Device status */
 #define DEVICE_STATUS_SELF_POWERED  (1U<<0)
@@ -32,7 +34,9 @@
 bool USBDevice::requestGetDescriptor(void)
 {
     bool success = false;
-
+#ifdef DEBUG
+    printf("get descr: type: %d\r\n", DESCRIPTOR_TYPE(transfer.setup.wValue));
+#endif
     switch (DESCRIPTOR_TYPE(transfer.setup.wValue))
     {
         case DEVICE_DESCRIPTOR:
@@ -41,6 +45,9 @@
                 if ((deviceDesc()[0] == DEVICE_DESCRIPTOR_LENGTH) \
                     && (deviceDesc()[1] == DEVICE_DESCRIPTOR))
                 {
+#ifdef DEBUG
+                    printf("device descr\r\n");
+#endif
                     transfer.remaining = DEVICE_DESCRIPTOR_LENGTH;
                     transfer.ptr = deviceDesc();
                     transfer.direction = DEVICE_TO_HOST;
@@ -54,6 +61,9 @@
                 if ((configurationDesc()[0] == CONFIGURATION_DESCRIPTOR_LENGTH) \
                     && (configurationDesc()[1] == CONFIGURATION_DESCRIPTOR))
                 {
+#ifdef DEBUG
+                    printf("conf descr request\r\n");
+#endif
                     /* Get wTotalLength */
                     transfer.remaining = configurationDesc()[2] \
                         | (configurationDesc()[3] << 8);
@@ -65,39 +75,60 @@
             }
             break;
         case STRING_DESCRIPTOR:
+#ifdef DEBUG
+            printf("str descriptor\r\n");
+#endif
             switch (DESCRIPTOR_INDEX(transfer.setup.wValue))
             {
                             case STRING_OFFSET_LANGID:
+#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:
+#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:
+#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:
+#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:
+#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:
+#ifdef DEBUG
+                                printf("6\r\n");
+#endif
                                 transfer.remaining = stringIinterfaceDesc()[0];
                                 transfer.ptr = stringIinterfaceDesc();
                                 transfer.direction = DEVICE_TO_HOST;
@@ -106,10 +137,19 @@
             }
             break;
         case INTERFACE_DESCRIPTOR:
+#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 */
             break;
         default:
+#ifdef DEBUG
+            printf("ERROR\r\n");
+#endif
             break;
     }
 
@@ -496,6 +536,16 @@
     transfer.direction = 0;
     transfer.zlp = false;
     transfer.notify = false;
+    
+#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();
@@ -505,6 +555,9 @@
         /* Standard requests */
         if (!requestSetup())
         {
+#ifdef DEBUG
+            printf("fail!!!!\r\n");
+#endif
             return false;
         }
     }
@@ -623,6 +676,7 @@
 
 void USBDevice::EP0in(void)
 {
+    printf("EP0IN\r\n");
     /* Endpoint 0 IN data event */
     if (!controlIn())
     {
--- a/main.cpp	Tue Dec 20 11:41:31 2011 +0000
+++ b/main.cpp	Wed Dec 21 10:43:57 2011 +0000
@@ -1,5 +1,5 @@
 #include "mbed.h"
-#include "USBAudioOUT.h"
+#include "USBAudio.h"
 
 // frequency: 8 kHz
 #define FREQ 8000
@@ -10,14 +10,15 @@
 // length of an audio packet: each ms, we receive 48 * 16bits ->48 * 2 bytes. as there is one channel, the length will be 48 * 2 * 1
 #define AUDIO_LENGTH_PACKET (FREQ/500) * NB_CHA
 
-USBAudioOUT audio(FREQ, NB_CHA, 0x1111, 0x78ab);
+USBAudio audio(FREQ, NB_CHA, 0x1007, 0xa455);
 
 AnalogIn mic(p20);
 
 int16_t buf[AUDIO_LENGTH_PACKET/2];
 
 int main() {
-    double mic_mean = 0.0;
+    while(1);
+    /*double mic_mean = 0.0;
     double mic_value;
 
     // compute average value of the microphone. We can then center the audio signal sent to the computer
@@ -34,5 +35,5 @@
             }
         }
         audio.write((uint8_t *)buf);
-    }
+    }*/
 }