summaryrefslogtreecommitdiff
path: root/usblib/host/usbhaudio.c
diff options
context:
space:
mode:
authorYuval Adam <yuv.adm@gmail.com>2014-03-16 14:41:11 +0200
committerYuval Adam <yuv.adm@gmail.com>2014-03-16 14:41:11 +0200
commit990090a4cc9070837d31e66b58d40f0c3d038741 (patch)
treecf1b905082c364e9b223e0c5058566103138dae5 /usblib/host/usbhaudio.c
parent7f4da522479c0f00126219f0c23b804c3a93d7a6 (diff)
Add usblib and utils
Diffstat (limited to 'usblib/host/usbhaudio.c')
-rw-r--r--usblib/host/usbhaudio.c1557
1 files changed, 1557 insertions, 0 deletions
diff --git a/usblib/host/usbhaudio.c b/usblib/host/usbhaudio.c
new file mode 100644
index 0000000..129130c
--- /dev/null
+++ b/usblib/host/usbhaudio.c
@@ -0,0 +1,1557 @@
+//*****************************************************************************
+//
+// usbhaudio.c - USB host audio driver.
+//
+// Copyright (c) 2010-2014 Texas Instruments Incorporated. All rights reserved.
+// Software License Agreement
+//
+// Texas Instruments (TI) is supplying this software for use solely and
+// exclusively on TI's microcontroller products. The software is owned by
+// TI and/or its suppliers, and is protected under applicable copyright
+// laws. You may not combine this software with "viral" open-source
+// software in order to form a larger program.
+//
+// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
+// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
+// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
+// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+// DAMAGES, FOR ANY REASON WHATSOEVER.
+//
+// This is part of revision 2.1.0.12573 of the Tiva USB Library.
+//
+//*****************************************************************************
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "inc/hw_types.h"
+#include "driverlib/usb.h"
+#include "usblib/usblib.h"
+#include "usblib/usblibpriv.h"
+#include "usblib/usbaudio.h"
+#include "usblib/host/usbhost.h"
+#include "usblib/host/usbhostpriv.h"
+#include "usblib/host/usbhaudio.h"
+
+//*****************************************************************************
+//
+//! \addtogroup usblib_host_class
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// These defines are used with the USBHostAudioFormatSet()
+// USBHostAudioFormatGet() to parse out interface number and alternate
+// setting number for an interface.
+//
+//*****************************************************************************
+#define INTERFACE_NUM_M 0x000000FF
+#define INTERFACE_ALTSETTING_M 0x0000FF00
+#define INTERFACE_ALTSETTING_S 8
+
+//*****************************************************************************
+//
+// Used to indicate an invalid interface descriptor number.
+//
+//*****************************************************************************
+#define INVALID_INTERFACE 0xffffffff
+
+//*****************************************************************************
+//
+// Forward declarations for the driver open and close calls.
+//
+//*****************************************************************************
+static void *USBAudioOpen(tUSBHostDevice *psDevice);
+static void USBAudioClose(void *pvInstance);
+
+//*****************************************************************************
+//
+// This is the structure for an instance of a USB host audio driver.
+//
+//*****************************************************************************
+struct tUSBHostAudioInstance
+{
+ //
+ // Save the device instance.
+ //
+ tUSBHostDevice *psDevice;
+
+ //
+ // Used to save the call back.
+ //
+ tUSBHostAudioCallback pfnCallback;
+
+ //
+ // This is the control interface.
+ //
+ uint8_t ui8IControl;
+
+ //
+ // This is the output streaming interface.
+ //
+ uint8_t ui8OutInterface;
+
+ //
+ // This is the currently selected active output interface used with
+ // ui8OutInterface interface.
+ //
+ uint8_t ui8OutAltSetting;
+
+ //
+ // This is the streaming interface.
+ //
+ uint8_t ui8InInterface;
+
+ //
+ // This is the currently selected active input interface used with
+ // ui8InInterface interface.
+ //
+ uint8_t ui8InAltSetting;
+
+ //
+ // The Isochronous endpoint addresses.
+ //
+ uint8_t ui8IsochInAddress;
+ uint8_t ui8IsochOutAddress;
+
+ tACInputTerminal *psInTerminal;
+ tACOutputTerminal *psOutTerminal;
+
+ //
+ // Holds the identifier for the Feature Unit for controlling volume.
+ //
+ uint8_t ui8VolumeID;
+
+ tACFeatureUnit *psFeatureUnit;
+
+ //
+ // Holds what types of controls are enabled on the device.
+ //
+ uint16_t pui16Controls[3];
+
+ //
+ // Isochronous IN pipe.
+ //
+ uint32_t ui32IsochInPipe;
+ uint16_t ui16PipeSizeIn;
+ tUSBHostAudioCallback pfnInCallback;
+ void *pvInBuffer;
+
+ //
+ // Isochronous OUT pipe.
+ //
+ uint32_t ui32IsochOutPipe;
+ uint16_t ui16PipeSizeOut;
+ tUSBHostAudioCallback pfnOutCallback;
+ void *pvOutBuffer;
+
+ //
+ // State flags for this audio instance.
+ //
+ uint32_t ui32Flags;
+};
+
+//*****************************************************************************
+//
+// The internal flags for an audio interface.
+//
+//*****************************************************************************
+#define AUDIO_FLAG_OUT_ACTIVE 1 // Audio output is active.
+#define AUDIO_FLAG_IN_ACTIVE 2 // Audio input is active.
+
+//*****************************************************************************
+//
+// The USB Host audio instance.
+//
+//*****************************************************************************
+static tUSBHostAudioInstance g_sAudioDevice =
+{
+ 0
+};
+
+//*****************************************************************************
+//
+//! This constant global structure defines the Audio Class Driver that is
+//! provided with the USB library.
+//
+//*****************************************************************************
+const tUSBHostClassDriver g_sUSBHostAudioClassDriver =
+{
+ USB_CLASS_AUDIO,
+ USBAudioOpen,
+ USBAudioClose,
+ 0
+};
+
+//*****************************************************************************
+//
+// This is the internal function that handles callbacks from the USB IN pipe.
+//
+//*****************************************************************************
+static void
+PipeCallbackIN(uint32_t ui32Pipe, uint32_t ui32Event)
+{
+ //
+ // Only handle the data available callback and pass it on to the
+ // application.
+ //
+ if(ui32Event == USB_EVENT_RX_AVAILABLE)
+ {
+ if(g_sAudioDevice.pfnInCallback)
+ {
+ g_sAudioDevice.pfnInCallback(&g_sAudioDevice,
+ USB_EVENT_RX_AVAILABLE,
+ USBHCDPipeTransferSizeGet(ui32Pipe),
+ g_sAudioDevice.pvInBuffer);
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// This is the internal function that handles callbacks from the USB OUT pipe.
+//
+//*****************************************************************************
+static void
+PipeCallbackOUT(uint32_t ui32Pipe, uint32_t ui32Event)
+{
+ //
+ // Only handle the transmit complete callback and pass it on to the
+ // application.
+ //
+ if(ui32Event == USB_EVENT_TX_COMPLETE)
+ {
+ if(g_sAudioDevice.pfnOutCallback)
+ {
+ g_sAudioDevice.pfnOutCallback(&g_sAudioDevice,
+ USB_EVENT_TX_COMPLETE, 0,
+ g_sAudioDevice.pvOutBuffer);
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// Finds a given terminal and type in an audio configuration descriptor.
+//
+//*****************************************************************************
+static tDescriptorHeader *
+AudioTerminalGet(tConfigDescriptor *psConfigDesc, uint32_t ui32Terminal,
+ uint32_t ui32TerminalType)
+{
+ tACOutputTerminal *psOutput;
+ tDescriptorHeader *psHeader;
+ int32_t i32BytesRemaining;
+
+ psHeader = (tDescriptorHeader *)psConfigDesc;
+ i32BytesRemaining = psConfigDesc->wTotalLength;
+
+ while(i32BytesRemaining > 0)
+ {
+ //
+ // Output and input terminals are the same past the bDescriptorSubtype
+ // and wTerminalType that are being searched for.
+ //
+ psOutput = (tACOutputTerminal *)psHeader;
+
+ //
+ // Only CS_INTERFACE descriptors can be a terminal.
+ //
+ if((psHeader->bDescriptorType == USB_DTYPE_CS_INTERFACE) &&
+ (ui32Terminal == psOutput->bDescriptorSubtype))
+ {
+ if((psOutput->bDescriptorSubtype == USB_AI_OUTPUT_TERMINAL) ||
+ (psOutput->bDescriptorSubtype == USB_AI_INPUT_TERMINAL))
+
+ {
+ //
+ // If this was the terminal type that was requested, the
+ // return it.
+ //
+ if(psOutput->wTerminalType == ui32TerminalType)
+ {
+ return(psHeader);
+ }
+ }
+ else if(psOutput->bDescriptorSubtype == USB_AI_FEATURE_UNIT)
+ {
+ return(psHeader);
+ }
+ }
+
+ //
+ // Decrease the bytes remaining by the size of this descriptor.
+ //
+ i32BytesRemaining -= psHeader->bLength;
+
+ //
+ // Move the pointer to the next header.
+ //
+ psHeader = (tDescriptorHeader *)((uint32_t)psHeader +
+ psHeader->bLength);
+ }
+ return((tDescriptorHeader *)0);
+}
+
+//*****************************************************************************
+//
+// This function returns the interface number for the control interface
+// in the structure passed in the psConfigDesc.
+//
+// \param psConfigDescriptor is a pointer to the memory containing a valid
+// configuration descriptor for a device.
+//
+// This function searches a configuration descriptor for a control interface
+// descriptor. The function only search for the first descriptor and then
+// returns when it finds one.
+//
+// \return The first control interface descriptor number for an audio device
+// or INVALID_INTERFACE if no control interface descriptor was found.
+//
+//*****************************************************************************
+static uint32_t
+AudioControlGet(tConfigDescriptor *psConfigDesc)
+{
+ tDescriptorHeader *psHeader;
+ tInterfaceDescriptor *psInterface;
+ uint32_t ui32Interface;
+ int32_t i32Bytes;
+
+ psHeader = (tDescriptorHeader *)psConfigDesc;
+ i32Bytes = psConfigDesc->wTotalLength;
+
+ //
+ // Initialize the interface number to an invalid value.
+ //
+ ui32Interface = INVALID_INTERFACE;
+
+ //
+ // Search the whole configuration descriptor.
+ //
+ while(i32Bytes > 0)
+ {
+ //
+ // Find an interface descriptor and see if it is a control interface.
+ //
+ if(psHeader->bDescriptorType == USB_DTYPE_INTERFACE)
+ {
+ psInterface = (tInterfaceDescriptor *)psHeader;
+
+ //
+ // If this is the control interface then return the value to the
+ // caller.
+ //
+ if(psInterface->bInterfaceSubClass == USB_ASC_AUDIO_CONTROL)
+ {
+ ui32Interface = psInterface->bInterfaceNumber;
+
+ break;
+ }
+ }
+
+ //
+ // Decrease the bytes remaining by the size of this descriptor.
+ //
+ i32Bytes -= psHeader->bLength;
+
+ //
+ // Move the pointer to the next header.
+ //
+ psHeader = (tDescriptorHeader*)((uint32_t)psHeader +
+ psHeader->bLength);
+ }
+ return(ui32Interface);
+}
+
+//*****************************************************************************
+//
+// If it exists, finds the correct audio interface for a given audio format.
+//
+//*****************************************************************************
+static uint32_t
+AudioGetInterface(tUSBHostAudioInstance *psAudioDevice, uint16_t ui16Format,
+ uint32_t ui32SampleRate, uint32_t ui32Bytes,
+ uint32_t ui32Channels, uint32_t ui32Flags)
+{
+ tDescriptorHeader *psHeader;
+ tInterfaceDescriptor *psInterface;
+ tEndpointDescriptor *pINEndpoint, *pOUTEndpoint;
+ tACHeader *pACHeader;
+ tACGeneral *pGeneral;
+ tASFormat *pFormat;
+ tEndpointDescriptor *pEndpoint;
+ uint8_t *pui8Value;
+ uint32_t ui32Value;
+ int32_t i32Bytes, i32Idx;
+
+ //
+ // Initialize the Interface pointer to null.
+ //
+ psInterface = 0;
+ pINEndpoint = 0;
+ pOUTEndpoint = 0;
+
+ //
+ // Start at the top of the configuration descriptor.
+ //
+ psHeader = (tDescriptorHeader *)psAudioDevice->psDevice->psConfigDescriptor;
+
+ i32Bytes = psAudioDevice->psDevice->psConfigDescriptor->wTotalLength;
+
+ while(i32Bytes > 0)
+ {
+ if(psHeader->bDescriptorType == USB_DTYPE_INTERFACE)
+ {
+ //
+ // If a new interface was found and the last one satisfied all
+ // requirements then a valid interface was found so break out.
+ //
+ if(psInterface)
+ {
+ break;
+ }
+
+ //
+ // Get the new interface pointer.
+ //
+ psInterface = (tInterfaceDescriptor *)psHeader;
+
+ //
+ // Reset the endpoints on finding a new interface descriptor.
+ //
+ pINEndpoint = 0;
+ pOUTEndpoint = 0;
+
+ //
+ // If this is not a valid audio streaming interface then reset
+ // the interface pointer to null.
+ //
+ if((psInterface->bNumEndpoints == 0) ||
+ (psInterface->bInterfaceClass != USB_CLASS_AUDIO) ||
+ (psInterface->bInterfaceSubClass != USB_ASC_AUDIO_STREAMING))
+ {
+ psInterface = 0;
+ }
+ }
+ if((psInterface) &&
+ (psHeader->bDescriptorType == USB_DTYPE_CS_INTERFACE))
+ {
+ pACHeader = (tACHeader *)psHeader;
+
+ //
+ // If this is a General descriptor the check if the format matches.
+ //
+ if(pACHeader->bDescriptorSubtype == USB_AS_GENERAL)
+ {
+ //
+ // Just save the pointer to the format descriptor.
+ //
+ pGeneral = (tACGeneral *)psHeader;
+
+ //
+ // If this interface has the wrong format then set it to null
+ // so that the rest of this interface is ignored.
+ //
+ if(pGeneral->wFormatTag != ui16Format)
+ {
+ psInterface = 0;
+ }
+ }
+ else if(pACHeader->bDescriptorSubtype == USB_AS_FORMAT_TYPE)
+ {
+ pFormat = (tASFormat *)psHeader;
+
+ //
+ // If the number of bytes per sample and number of channels do
+ // not match then reset the interface pointer so that the rest
+ // of this interface is ignored.
+ //
+ if((pFormat->bNrChannels != ui32Channels) ||
+ (pFormat->bSubFrameSize != ui32Bytes))
+ {
+ psInterface = 0;
+ }
+ else
+ {
+ pui8Value = &pFormat->tSamFreq;
+
+ //
+ // Attempt to find the sample rate in the sample rate
+ // table for this interface.
+ //
+ for(i32Idx = 0; i32Idx < pFormat->bSamFreqType; i32Idx++)
+ {
+ ui32Value = (*((uint32_t *)&pui8Value[i32Idx * 3]) &
+ 0xffffff);
+
+ if(ui32Value == ui32SampleRate)
+ {
+ break;
+ }
+ }
+
+ //
+ // If the sample rate was not found then set the interface
+ // pointer to null so that the rest of this interface is
+ // ignored.
+ //
+ if(i32Idx == pFormat->bSamFreqType)
+ {
+ psInterface = 0;
+ }
+ }
+ }
+ }
+ else if((psInterface) &&
+ (psHeader->bDescriptorType == USB_DTYPE_ENDPOINT))
+ {
+ pEndpoint = (tEndpointDescriptor *)psHeader;
+
+ //
+ // See what direction is being requested.
+ //
+ if(ui32Flags & USBH_AUDIO_FORMAT_IN)
+ {
+ //
+ // If this is an input endpoint and is just a feed back input
+ // then ignore it.
+ //
+ if(pEndpoint->bEndpointAddress & USB_EP_DESC_IN)
+ {
+ if((pEndpoint->bmAttributes & USB_EP_ATTR_USAGE_M)
+ == USB_EP_ATTR_USAGE_FEEDBACK)
+ {
+ psInterface = 0;
+ }
+ else
+ {
+ //
+ // Save this endpoint as a possible valid endpoint
+ //
+ pINEndpoint = pEndpoint;
+ }
+ }
+ }
+ else
+ {
+ //
+ // If this is an output endpoint and is just a feed back input
+ // then ignore it.
+ //
+ if((pEndpoint->bEndpointAddress & USB_EP_DESC_IN) == 0)
+ {
+ if((pEndpoint->bmAttributes & USB_EP_ATTR_USAGE_M)
+ == USB_EP_ATTR_USAGE_FEEDBACK)
+ {
+ psInterface = 0;
+ }
+ else
+ {
+ //
+ // Save this endpoint as a possible valid endpoint;
+ //
+ pOUTEndpoint = pEndpoint;
+ }
+ }
+ }
+ }
+
+ //
+ // Decrease the bytes remaining by the size of this descriptor.
+ //
+ i32Bytes -= psHeader->bLength;
+
+ //
+ // Move the pointer to the next header.
+ //
+ psHeader = (tDescriptorHeader*)((uint32_t)psHeader +
+ psHeader->bLength);
+ }
+
+ //
+ // If there is still a valid interface then return the values.
+ //
+ if(psInterface)
+ {
+ //
+ // Check a valid IN endpoint descriptor.
+ //
+ if(pINEndpoint)
+ {
+ //
+ // Save the endpoint address.
+ //
+ g_sAudioDevice.ui8IsochInAddress = pINEndpoint->bEndpointAddress &
+ USB_EP_DESC_NUM_M;
+
+ //
+ // If there is no current pipe then just allocate a new one with
+ // the settings for this interface.
+ //
+ if(g_sAudioDevice.ui32IsochInPipe == 0)
+ {
+ //
+ // Allocate the USB Pipe for this Isochronous IN end point.
+ //
+ g_sAudioDevice.ui32IsochInPipe =
+ USBHCDPipeAllocSize(0, USBHCD_PIPE_ISOC_IN_DMA,
+ g_sAudioDevice.psDevice,
+ pINEndpoint->wMaxPacketSize,
+ PipeCallbackIN);
+ }
+ else if(g_sAudioDevice.ui16PipeSizeIn < pINEndpoint->wMaxPacketSize)
+ {
+ //
+ // Free the old endpoint and allocate a new one.
+ //
+ USBHCDPipeFree(g_sAudioDevice.ui32IsochInPipe);
+
+ //
+ // Allocate the USB Pipe for this Isochronous IN end point.
+ //
+ g_sAudioDevice.ui32IsochInPipe =
+ USBHCDPipeAllocSize(0, USBHCD_PIPE_ISOC_IN_DMA,
+ g_sAudioDevice.psDevice,
+ pINEndpoint->wMaxPacketSize,
+ PipeCallbackIN);
+
+ //
+ // Save the new size of the maximum packet size for this
+ // USB pipe.
+ //
+ g_sAudioDevice.ui16PipeSizeIn = pINEndpoint->wMaxPacketSize;
+ }
+
+ //
+ // Configure the USB pipe as a Isochronous IN end point.
+ //
+ USBHCDPipeConfig(g_sAudioDevice.ui32IsochInPipe,
+ pINEndpoint->wMaxPacketSize,
+ 0,
+ g_sAudioDevice.ui8IsochInAddress);
+ }
+
+ //
+ // Check a valid OUT endpoint descriptor.
+ //
+ if(pOUTEndpoint)
+ {
+ //
+ // Save the endpoint address.
+ //
+ g_sAudioDevice.ui8IsochOutAddress =
+ pOUTEndpoint->bEndpointAddress & USB_EP_DESC_NUM_M;
+
+ //
+ // If there is no current pipe then just allocate a new one with
+ // the settings for this interface.
+ //
+ if(g_sAudioDevice.ui32IsochOutPipe == 0)
+ {
+ //
+ // Allocate the USB Pipe for this Isochronous OUT end point.
+ //
+ g_sAudioDevice.ui32IsochOutPipe =
+ USBHCDPipeAllocSize(0, USBHCD_PIPE_ISOC_OUT_DMA,
+ g_sAudioDevice.psDevice,
+ pOUTEndpoint->wMaxPacketSize,
+ PipeCallbackOUT);
+ }
+ else if(g_sAudioDevice.ui16PipeSizeOut <
+ pOUTEndpoint->wMaxPacketSize)
+ {
+ //
+ // Free the old endpoint and allocate a new one.
+ //
+ USBHCDPipeFree(g_sAudioDevice.ui32IsochOutPipe);
+
+ //
+ // Allocate the USB Pipe for this Isochronous OUT end point.
+ //
+ g_sAudioDevice.ui32IsochOutPipe =
+ USBHCDPipeAllocSize(0, USBHCD_PIPE_ISOC_OUT_DMA,
+ g_sAudioDevice.psDevice,
+ pOUTEndpoint->wMaxPacketSize,
+ PipeCallbackOUT);
+
+ //
+ // Save the new size of the maximum packet size for this
+ // USB pipe.
+ //
+ g_sAudioDevice.ui16PipeSizeOut = pOUTEndpoint->wMaxPacketSize;
+ }
+
+ //
+ // Configure the USB pipe as a Isochronous OUT end point.
+ //
+ USBHCDPipeConfig(g_sAudioDevice.ui32IsochOutPipe,
+ pOUTEndpoint->wMaxPacketSize, 0,
+ g_sAudioDevice.ui8IsochOutAddress);
+ }
+
+ return(psInterface->bInterfaceNumber |
+ (psInterface->bAlternateSetting << INTERFACE_ALTSETTING_S));
+ }
+ return(INVALID_INTERFACE);
+}
+
+//*****************************************************************************
+//
+// This function is used to open an instance of the USB host audio driver.
+//
+// \param psDevice is a pointer to the device information structure.
+//
+// This function attempts to open an instance of the USB host audio driver
+// based on the information contained in the psDevice structure. This call
+// fails if there are not sufficient resources to open the device. The
+// function returns a value that should be passed back into USBHostAudioClose()
+// when the driver is no longer needed.
+//
+// \return The function returns a pointer to a USB host audio driver
+// instance.
+//
+//*****************************************************************************
+static void *
+USBAudioOpen(tUSBHostDevice *psDevice)
+{
+ uint32_t ui32Temp;
+ tConfigDescriptor *psConfigDesc;
+
+ //
+ // Don't allow the device to be opened without closing first.
+ //
+ if(g_sAudioDevice.psDevice)
+ {
+ return(0);
+ }
+
+ //
+ // Save the Host device pointer.
+ //
+ g_sAudioDevice.psDevice = psDevice;
+
+ //
+ // Save a shorter name for the configuration descriptor.
+ //
+ psConfigDesc = psDevice->psConfigDescriptor;
+
+ //
+ // Find the input terminal.
+ //
+ g_sAudioDevice.psInTerminal =
+ (tACInputTerminal *)AudioTerminalGet(psConfigDesc,
+ USB_AI_INPUT_TERMINAL,
+ USB_TTYPE_STREAMING);
+
+ //
+ // Find the output terminal.
+ //
+ g_sAudioDevice.psOutTerminal =
+ (tACOutputTerminal *)AudioTerminalGet(psConfigDesc,
+ USB_AI_OUTPUT_TERMINAL,
+ USB_TTYPE_STREAMING);
+
+ //
+ // Find the feature unit.
+ g_sAudioDevice.psFeatureUnit =
+ (tACFeatureUnit *)AudioTerminalGet(psConfigDesc,
+ USB_AI_FEATURE_UNIT, 0);
+
+ //
+ // Need some kind of terminal to send or receive audio from.
+ //
+ if((g_sAudioDevice.psOutTerminal == 0) &&
+ (g_sAudioDevice.psInTerminal == 0))
+ {
+ return(0);
+ }
+
+ //
+ // Find the Audio control interface.
+ //
+ ui32Temp = AudioControlGet(psConfigDesc);
+
+ if(ui32Temp == INVALID_INTERFACE)
+ {
+ return(0);
+ }
+
+ //
+ // Save the control interface index and increment the number
+ // of interfaces that have been found.
+ //
+ g_sAudioDevice.ui8IControl = (uint8_t)ui32Temp;
+
+ //
+ // If the call back exists, call it with an Open event.
+ //
+ if(g_sAudioDevice.pfnCallback != 0)
+ {
+ g_sAudioDevice.pfnCallback(&g_sAudioDevice,
+ USBH_AUDIO_EVENT_OPEN, 0, 0);
+ }
+
+ //
+ // If a feature unit was found, save the ID
+ //
+ if(g_sAudioDevice.psFeatureUnit != 0)
+ {
+ g_sAudioDevice.ui8VolumeID = g_sAudioDevice.psFeatureUnit->bUnitID;
+ }
+
+ //
+ // Allocate the USB Pipe for this Isochronous IN end point.
+ //
+ g_sAudioDevice.ui32IsochInPipe =
+ USBHCDPipeAllocSize(0, USBHCD_PIPE_ISOC_IN_DMA,
+ g_sAudioDevice.psDevice, 256, PipeCallbackIN);
+ g_sAudioDevice.ui16PipeSizeIn = 256;
+
+ //
+ // Allocate the USB Pipe for this Isochronous OUT end point.
+ //
+ g_sAudioDevice.ui32IsochOutPipe =
+ USBHCDPipeAllocSize(0, USBHCD_PIPE_ISOC_OUT_DMA,
+ g_sAudioDevice.psDevice, 256, PipeCallbackOUT);
+ g_sAudioDevice.ui16PipeSizeOut = 256;
+
+ //
+ // Clear the flags.
+ //
+ g_sAudioDevice.ui32Flags = 0;
+
+ //
+ // Return the only instance of this device.
+ //
+ return(&g_sAudioDevice);
+}
+
+//*****************************************************************************
+//
+// This function is used to release an instance of the USB host audio driver.
+//
+// \param pvAudioDevice is an instance pointer that needs to be released.
+//
+// This function frees up any resources in use by the USB host audio
+// driver instance that is passed in. The \e pvAudioDevice pointer should be a
+// valid value that was returned from a call to USBHostAudioOpen().
+//
+// \return None.
+//
+//*****************************************************************************
+static void
+USBAudioClose(void *pvAudioDevice)
+{
+ tUSBHostAudioInstance *psAudioDevice;
+
+ psAudioDevice = (tUSBHostAudioInstance *)pvAudioDevice;
+
+ //
+ // Do nothing if there is not a driver open.
+ //
+ if(psAudioDevice->psDevice == 0)
+ {
+ return;
+ }
+
+ //
+ // Reset the device pointer.
+ //
+ psAudioDevice->psDevice = 0;
+
+ //
+ // Free the Isochronous IN pipe.
+ //
+ if(psAudioDevice->ui32IsochInPipe != 0)
+ {
+ USBHCDPipeFree(psAudioDevice->ui32IsochInPipe);
+ }
+
+ //
+ // Free the Isochronous OUT pipe.
+ //
+ if(psAudioDevice->ui32IsochOutPipe != 0)
+ {
+ USBHCDPipeFree(psAudioDevice->ui32IsochOutPipe);
+ }
+
+ //
+ // If the call back exists then call it.
+ //
+ if(psAudioDevice->pfnCallback != 0)
+ {
+ psAudioDevice->pfnCallback(psAudioDevice, USBH_AUDIO_EVENT_CLOSE, 0,
+ 0);
+ }
+}
+
+//*****************************************************************************
+//
+//! This function should be called before any devices are present to enable
+//! the host audio class driver.
+//!
+//! \param ui32Index is the audio device to open (currently only 0 is
+//! supported).
+//! \param pfnCallback is the driver call back for host audio events.
+//!
+//! This function is called to open an instance of a host audio device and
+//! should provide a valid callback function for host audio events in the
+//! \e pfnCallback parameter. This function must be called before the USB
+//! host code can successfully enumerate an audio device.
+//!
+//! \return This function returns the driver instance to use for the other
+//! host audio functions. If there is no instance available at the time of
+//! this call, this function returns zero.
+//
+//*****************************************************************************
+tUSBHostAudioInstance *
+USBHostAudioOpen(uint32_t ui32Index, tUSBHostAudioCallback pfnCallback)
+{
+ //
+ // Only one audio device is supported at this time and on one instance
+ // is supported so if there is already a call back then fail.
+ //
+ if((ui32Index != 0) || (g_sAudioDevice.pfnCallback))
+ {
+ return(0);
+ }
+
+ //
+ // Save the call back.
+ //
+ g_sAudioDevice.pfnCallback = pfnCallback;
+
+ //
+ // Return the requested device instance.
+ //
+ return(&g_sAudioDevice);
+}
+
+//*****************************************************************************
+//
+//! This function should be called to release an audio device instance.
+//!
+//! \param psAudioInstance is the device instance that is to be released.
+//!
+//! This function is called when a host audio device needs to be released.
+//! This could be in preparation for shutdown or a switch to USB device mode,
+//! for example. Following this call, the audio device is available and can
+//! be opened again using a call to USBHostAudioOpen(). After calling this
+//! function, the host audio driver will no longer provide any callbacks or
+//! accept calls to other audio driver APIs.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+USBHostAudioClose(tUSBHostAudioInstance *psAudioInstance)
+{
+ //
+ // Close the audio device.
+ //
+ USBAudioClose(psAudioInstance);
+
+ //
+ // Clear the call back indicating that the device is now closed.
+ //
+ psAudioInstance->pfnCallback = 0;
+}
+
+//*****************************************************************************
+//
+// This function is used to request settings from a given audio interface.
+//
+// \param psAudioDevice is the audio device instance to access.
+// \param ui32Interface is the interface to access.
+// \param ui32Channel is the channel number to access.
+// \param ui32Request is the audio device request.
+//
+// This function is used to get volume control parameters from a given
+// interface and on a given channel. The \e ui32Interface is the interface to
+// make the request specified by \e ui32Channel and \e ui32Request. The
+// \e ui32Request parameter must be one of the USB_AC_GET_* values.
+//
+// \return This function returns the requested value.
+//
+//*****************************************************************************
+static uint32_t
+VolumeSettingGet(tUSBHostAudioInstance *psAudioDevice, uint32_t ui32Interface,
+ uint32_t ui32Channel, uint32_t ui32Request)
+{
+ uint32_t ui32Value;
+ tUSBRequest sSetupPacket;
+
+ ui32Value = 0;
+
+ //
+ // This is a Class specific Interface IN request.
+ //
+ sSetupPacket.bmRequestType = USB_RTYPE_DIR_IN | USB_RTYPE_CLASS |
+ USB_RTYPE_INTERFACE;
+
+ //
+ // Request a Device Descriptor.
+ //
+ sSetupPacket.bRequest = (ui32Request & 0xff);
+
+ //
+ // Request for a string descriptor.
+ //
+ sSetupPacket.wValue = VOLUME_CONTROL | (ui32Channel & 0xff);
+
+ //
+ // Set the language ID.
+ //
+ sSetupPacket.wIndex = (psAudioDevice->ui8VolumeID << 8) |
+ (ui32Interface & 0xff);
+
+ //
+ // Only request the space available.
+ //
+ sSetupPacket.wLength = 2;
+
+ //
+ // Put the setup packet in the buffer.
+ //
+ USBHCDControlTransfer(0, &sSetupPacket, psAudioDevice->psDevice,
+ (uint8_t *)&ui32Value, 4,
+ psAudioDevice->psDevice->sDeviceDescriptor.bMaxPacketSize0);
+
+ return(ui32Value);
+}
+
+//*****************************************************************************
+//
+//! This function is used to get the current volume setting for a given
+//! audio device.
+//!
+//! \param psAudioInstance is an instance of the USB audio device.
+//! \param ui32Interface is the interface number to use to query the current
+//! volume setting.
+//! \param ui32Channel is the 0 based channel number to query.
+//!
+//! The function is used to retrieve the current volume setting for an audio
+//! device on the channel specified by \e ui32Channel. The \e ui32Interface is
+//! ignored for now and should be set to 0 to access the default audio control
+//! interface. The \e ui32Channel value starts with 0 which is the master
+//! audio volume control interface. The remaining \e ui32Channel values
+//! provide access to various other audio channels, with 1 and 2 being left and
+//! right audio channels.
+//!
+//! \note On devices that do not support volume control interfaces, this
+//! call returns 0, indicating a 0db setting.
+//!
+//! \return Returns the current volume setting for the requested interface.
+//
+//*****************************************************************************
+uint32_t
+USBHostAudioVolumeGet(tUSBHostAudioInstance *psAudioInstance,
+ uint32_t ui32Interface, uint32_t ui32Channel)
+{
+ return(VolumeSettingGet(psAudioInstance, ui32Interface, ui32Channel,
+ USB_AC_GET_CUR));
+}
+
+//*****************************************************************************
+//
+//! This function is used to get the maximum volume setting for a given
+//! audio device.
+//!
+//! \param psAudioInstance is an instance of the USB audio device.
+//! \param ui32Interface is the interface number to use to query the maximum
+//! volume control value.
+//! \param ui32Channel is the 0 based channel number to query.
+//!
+//! The function is used to retrieve the maximum volume setting for an audio
+//! device on the channel specified by \e ui32Channel. The \e ui32Interface is
+//! ignored for now and should be set to 0 to access the default audio control
+//! interface. The \e ui32Channel value starts with 0 which is the master
+//! audio volume control interface. The remaining \e ui32Channel values
+//! provide access to various other audio channels, with 1 and 2 being left and
+//! right audio channels.
+//!
+//! \note On devices that do not support volume control interfaces, this
+//! call returns 0, indicating a 0db setting.
+//!
+//! \return Returns the maximum volume setting for the requested interface.
+//
+//*****************************************************************************
+uint32_t
+USBHostAudioVolumeMaxGet(tUSBHostAudioInstance *psAudioInstance,
+ uint32_t ui32Interface, uint32_t ui32Channel)
+{
+ return(VolumeSettingGet(psAudioInstance, ui32Interface, ui32Channel,
+ USB_AC_GET_MAX));
+}
+
+//*****************************************************************************
+//
+//! This function is used to get the minimum volume setting for a given
+//! audio device.
+//!
+//! \param psAudioInstance is an instance of the USB audio device.
+//! \param ui32Interface is the interface number to use to query the minimum
+//! volume control value.
+//! \param ui32Channel is the 0 based channel number to query.
+//!
+//! The function is used to retrieve the minimum volume setting for an audio
+//! device on the channel specified by \e ui32Channel. The \e ui32Interface is
+//! ignored for now and should be set to 0 to access the default audio control
+//! interface. The \e ui32Channel value starts with 0 which is the master
+//! audio volume control interface. The remaining \e ui32Channel values
+//! provide access to various other audio channels, with 1 and 2 being left and
+//! right audio channels.
+//!
+//! \note On devices that do not support volume control interfaces, this
+//! call returns 0, indicating a 0db setting.
+//!
+//! \return Returns the minimum volume setting for the requested interface.
+//
+//*****************************************************************************
+uint32_t
+USBHostAudioVolumeMinGet(tUSBHostAudioInstance *psAudioInstance,
+ uint32_t ui32Interface, uint32_t ui32Channel)
+{
+ return(VolumeSettingGet(psAudioInstance, ui32Interface, ui32Channel,
+ USB_AC_GET_MIN));
+}
+
+//*****************************************************************************
+//
+//! This function is used to get the volume control resolution for a given
+//! audio device.
+//!
+//! \param psAudioInstance is an instance of the USB audio device.
+//! \param ui32Interface is the interface number to use to query the resolution
+//! for the volume control.
+//! \param ui32Channel is the 0 based channel number to query.
+//!
+//! The function is used to retrieve the volume control resolution for an audio
+//! device on the channel specified by \e ui32Channel. The \e ui32Interface is
+//! ignored for now and should be set to 0 to access the default audio control
+//! interface. The \e ui32Channel value starts with 0 which is the master
+//! audio volume control interface. The remaining \e ui32Channel values
+//! provide access to various other audio channels, with 1 and 2 being left and
+//! right audio channels.
+//!
+//! \note On devices that do not support volume control interfaces, this
+//! call returns 0, indicating a 0db setting.
+//!
+//! \return Returns the volume control resolution for the requested interface.
+//
+//*****************************************************************************
+uint32_t
+USBHostAudioVolumeResGet(tUSBHostAudioInstance *psAudioInstance,
+ uint32_t ui32Interface, uint32_t ui32Channel)
+{
+ return(VolumeSettingGet(psAudioInstance, ui32Interface, ui32Channel,
+ USB_AC_GET_RES));
+}
+
+//*****************************************************************************
+//
+//! This function is used to set the current volume setting for a given
+//! audio device.
+//!
+//! \param psAudioInstance is an instance of the USB audio device.
+//! \param ui32Interface is the interface number to use to set the current
+//! volume setting.
+//! \param ui32Channel is the 0 based channel number to query.
+//! \param ui32Value is the value to write to the USB audio device.
+//!
+//! The function is used to set the current volume setting for an audio
+//! device on the channel specified by \e ui32Channel. The \e ui32Interface is
+//! ignored for now and should be set to 0 to access the default audio control
+//! interface. The \e ui32Channel value starts with 0 which is the master
+//! audio volume control interface. The remaining \e ui32Channel values
+//! provide access to various other audio channels, with 1 and 2 being left and
+//! right audio channels.
+//!
+//! \note On devices that do not support volume control interfaces, this
+//! call returns 0, indicating a 0db setting.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+USBHostAudioVolumeSet(tUSBHostAudioInstance *psAudioInstance,
+ uint32_t ui32Interface, uint32_t ui32Channel,
+ uint32_t ui32Value)
+{
+ tUSBRequest sSetupPacket;
+
+ //
+ // This is a Class specific Interface OUT request.
+ //
+ sSetupPacket.bmRequestType = USB_RTYPE_DIR_OUT | USB_RTYPE_CLASS |
+ USB_RTYPE_INTERFACE;
+
+ //
+ // Request is to set the current value.
+ //
+ sSetupPacket.bRequest = USB_AC_SET_CUR;
+
+ //
+ // Request the volume control.
+ //
+ sSetupPacket.wValue = VOLUME_CONTROL | (ui32Channel & 0xff);
+
+ //
+ // Set Volume control ID and interface to 0.
+ //
+ sSetupPacket.wIndex = psAudioInstance->ui8VolumeID << 8;
+
+ //
+ // Only request the space available.
+ //
+ sSetupPacket.wLength = 2;
+
+ //
+ // Put the setup packet in the buffer.
+ //
+ USBHCDControlTransfer(0, &sSetupPacket, psAudioInstance->psDevice,
+ (uint8_t *)&ui32Value, 2,
+ psAudioInstance->psDevice->sDeviceDescriptor.bMaxPacketSize0);
+}
+
+//*****************************************************************************
+//
+//! This function is called to determine if an audio format is supported by the
+//! connected USB Audio device.
+//!
+//! \param psAudioInstance is the device instance for this call.
+//! \param ui32SampleRate is the sample rate of the audio stream.
+//! \param ui32Bits is the number of bits per sample in the audio stream.
+//! \param ui32Channels is the number of channels in the audio stream.
+//! \param ui32Flags is a set of flags to determine what type of interface to
+//! retrieve.
+//!
+//! This function is called when an application needs to determine which audio
+//! formats are supported by a USB audio device that has been connected. The
+//! \e psAudioInstance value that is used with this call is the value that was
+//! returned from the USBHostAudioOpen() function. This call checks the
+//! USB audio device to determine if it can support the values provided in the
+//! \e ui32SampleRate, \e ui32Bits, and \e ui32Channels values. The
+//! \e ui32Flags currently only supports either the \b USBH_AUDIO_FORMAT_IN or
+//! \b USBH_AUDIO_FORMAT_OUT values that indicates if a request is for an
+//! audio input and an audio output. If the format is supported this
+//! function returns zero, and this function returns a non-zero value if the
+//! format is not supported. This function does not set the current output or
+//! input format.
+//!
+//! \return A value of zero indicates the supplied format is supported and
+//! a non-zero value indicates that the format is not supported.
+//
+//*****************************************************************************
+uint32_t
+USBHostAudioFormatGet(tUSBHostAudioInstance *psAudioInstance,
+ uint32_t ui32SampleRate, uint32_t ui32Bits,
+ uint32_t ui32Channels, uint32_t ui32Flags)
+{
+ //
+ // Look for the requested format.
+ //
+ if(AudioGetInterface(psAudioInstance, USB_ADF_PCM, ui32SampleRate,
+ ui32Bits >> 3, ui32Channels, ui32Flags) !=
+ INVALID_INTERFACE)
+ {
+ return(0);
+ }
+ return(1);
+}
+
+//*****************************************************************************
+//
+//! This function is called to set the current sample rate on an audio
+//! interface.
+//!
+//! \param psAudioInstance specifies the device instance for this call.
+//! \param ui32SampleRate is the sample rate in Hz.
+//! \param ui32Bits is the number of bits per sample.
+//! \param ui32Channels is then number of audio channels.
+//! \param ui32Flags is a set of flags that determine the access type.
+//!
+//! This function is called when to set the current audio output or input
+//! format for a USB audio device. The \e psAudioInstance value that is used
+//! with this call is the value that was returned from the USBHostAudioOpen()
+//! function. The application can use this call to insure that the audio
+//! format is supported and set the format at the same time. If the
+//! application is just checking for supported rates, then it should call the
+//! USBHostAudioFormatGet().
+//!
+//! \note This function must be called before attempting to send or receive
+//! audio with the USBHostAudioPlay() or USBHostAudioRecord() functions.
+//!
+//! \return A non-zero value indicates the supplied format is not supported and
+//! a zero value indicates that the format was supported and has been
+//! configured.
+//
+//*****************************************************************************
+uint32_t
+USBHostAudioFormatSet(tUSBHostAudioInstance *psAudioInstance,
+ uint32_t ui32SampleRate, uint32_t ui32Bits,
+ uint32_t ui32Channels, uint32_t ui32Flags)
+{
+ uint32_t ui32Interface;
+
+ //
+ // Look for the requested format.
+ //
+ ui32Interface = AudioGetInterface(psAudioInstance, USB_ADF_PCM,
+ ui32SampleRate, ui32Bits >> 3,
+ ui32Channels, ui32Flags);
+
+ if(ui32Interface == INVALID_INTERFACE)
+ {
+ return(1);
+ }
+
+ //
+ // Determine if this is an input or output request.
+ //
+ if(ui32Flags & USBH_AUDIO_FORMAT_IN)
+ {
+ //
+ // Get the active interface number and alternate setting for this
+ // format.
+ //
+ psAudioInstance->ui8InInterface =
+ (uint8_t)(ui32Interface & INTERFACE_NUM_M);
+ psAudioInstance->ui8InAltSetting =
+ (uint8_t)((ui32Interface & INTERFACE_ALTSETTING_M) >>
+ INTERFACE_ALTSETTING_S);
+ }
+ else
+ {
+ //
+ // Get the active interface number and alternate setting for this
+ // format.
+ //
+ psAudioInstance->ui8OutInterface =
+ (uint8_t)(ui32Interface & INTERFACE_NUM_M);
+ psAudioInstance->ui8OutAltSetting =
+ (uint8_t)((ui32Interface & INTERFACE_ALTSETTING_M) >>
+ INTERFACE_ALTSETTING_S);
+ }
+ return(0);
+}
+
+//*****************************************************************************
+//
+//! This function is called to send an audio buffer to the USB audio device.
+//!
+//! \param psAudioInstance specifies the device instance for this call.
+//! \param pvBuffer is the audio buffer to send.
+//! \param ui32Size is the size of the buffer in bytes.
+//! \param pfnCallback is a pointer to a callback function that is called
+//! when the buffer can be used again.
+//!
+//! This function is called when an application needs to schedule a new buffer
+//! for output to the USB audio device. Since this call schedules the transfer
+//! and returns immediately, the application should provide a \e pfnCallback
+//! function to be notified when the buffer can be used again by the
+//! application. The \e pfnCallback function provided is called with the
+//! \e pvBuffer parameter set to the \e pvBuffer provided by this call, the
+//! \e ui32Param can be ignored and the \e ui32Event parameter is
+//! \b USB_EVENT_TX_COMPLETE.
+//!
+//! \return This function returns the number of bytes that were scheduled
+//! to be sent. If this function returns zero then there was no USB audio
+//! device present or the request could not be satisfied at this time.
+//
+//*****************************************************************************
+int32_t
+USBHostAudioPlay(tUSBHostAudioInstance *psAudioInstance, void *pvBuffer,
+ uint32_t ui32Size, tUSBHostAudioCallback pfnCallback)
+{
+ uint32_t ui32Bytes;
+
+ //
+ // Make sure that there is a device present.
+ //
+ if(psAudioInstance->psDevice == 0)
+ {
+ return(0);
+ }
+
+ //
+ // If the audio output interface is not active then select the current
+ // active audio interface.
+ //
+ if(HWREGBITW(&psAudioInstance->ui32Flags, AUDIO_FLAG_OUT_ACTIVE) == 0)
+ {
+ //
+ // Indicate the active audio interface has been selected.
+ //
+ HWREGBITW(&psAudioInstance->ui32Flags, AUDIO_FLAG_OUT_ACTIVE) = 1;
+
+ //
+ // Configure the USB audio device to use the selected audio interface.
+ //
+ USBHCDSetInterface(0, (uint32_t)psAudioInstance->psDevice,
+ psAudioInstance->ui8OutInterface,
+ psAudioInstance->ui8OutAltSetting);
+ }
+
+ //
+ // Save the callback function and the buffer pointer.
+ //
+ psAudioInstance->pfnOutCallback = pfnCallback;
+ psAudioInstance->pvOutBuffer = (void *)pvBuffer;
+
+ //
+ // Schedule the data to be written out to the FIFO.
+ //
+ ui32Bytes = USBHCDPipeSchedule(psAudioInstance->ui32IsochOutPipe, pvBuffer,
+ ui32Size);
+
+ //
+ // Return the number of bytes scheduled to be sent.
+ //
+ return(ui32Bytes);
+}
+
+//*****************************************************************************
+//
+//! This function is called to provide an audio buffer to the USB audio device
+//! for audio input.
+//!
+//! \param psAudioInstance specifies the device instance for this call.
+//! \param pvBuffer is the audio buffer to send.
+//! \param ui32Size is the size of the buffer in bytes.
+//! \param pfnCallback is a pointer to a callback function that is called
+//! when the buffer has been filled.
+//!
+//! This function is called when an application needs to schedule a new buffer
+//! for input from the USB audio device. Since this call schedules the
+//! transfer and returns immediately, the application should provide a
+//! \e pfnCallback function to be notified when the buffer has been filled with
+//! audio data. When the \e pfnCallback function is called, the \e pvBuffer
+//! parameter is set to \e pvBuffer provided in this call, the \e ui32Param is
+//! the number of valid bytes in the pvBuffer and the \e ui32Event is set to
+//! \b USB_EVENT_RX_AVAILABLE.
+//!
+//! \return This function returns the number of bytes that were scheduled
+//! to be sent. If this function returns zero then there was no USB audio
+//! device present or the device does not support audio input.
+//
+//*****************************************************************************
+int32_t
+USBHostAudioRecord(tUSBHostAudioInstance *psAudioInstance, void *pvBuffer,
+ uint32_t ui32Size, tUSBHostAudioCallback pfnCallback)
+{
+ uint32_t ui32Bytes;
+
+ //
+ // Make sure that there is a device present.
+ //
+ if(psAudioInstance->psDevice == 0)
+ {
+ return(0);
+ }
+
+ //
+ // If the audio input interface is not active then select the current
+ // active audio interface.
+ //
+ if(HWREGBITW(&psAudioInstance->ui32Flags, AUDIO_FLAG_IN_ACTIVE) == 0)
+ {
+ //
+ // Indicate the active audio interface has been selected.
+ //
+ HWREGBITW(&psAudioInstance->ui32Flags, AUDIO_FLAG_IN_ACTIVE) = 1;
+
+ //
+ // Configure the USB audio device to use the selected audio interface.
+ //
+ USBHCDSetInterface(0, (uint32_t)psAudioInstance->psDevice,
+ psAudioInstance->ui8InInterface,
+ psAudioInstance->ui8InAltSetting);
+ }
+
+ //
+ // Save the callback function and the buffer pointer.
+ //
+ psAudioInstance->pfnInCallback = pfnCallback;
+ psAudioInstance->pvInBuffer = (void *)pvBuffer;
+
+ //
+ // Schedule the data to be read from the FIFO.
+ //
+ ui32Bytes = USBHCDPipeSchedule(psAudioInstance->ui32IsochInPipe, pvBuffer,
+ ui32Size);
+
+ //
+ // Return the number of bytes scheduled to be sent.
+ //
+ return(ui32Bytes);
+}
+
+//*****************************************************************************
+//
+//! This function forwards an LPM request for a device to enter L1 sleep state.
+//!
+//! \param psAudioInstance is the audio device instance that was returned
+//! from the call to USBHostAudioOpen().
+//!
+//! This function forwards a request from an application to the audio device
+//! class to request that a device enter the LPM L1 sleep state. The
+//! caller must check the return value to see if the request can be
+//! attempted at this time. If another LPM transaction is busy on this or
+//! another device, then this function returns \b USBHCD_LPM_PENDING. If
+//! the LPM request was scheduled to be sent the function returns
+//! \b USBHCD_LPM_AVAIL. The caller should check the USBHCDLPMStatus()
+//! function to determine if the request completed successfully or if there
+//! was an error.
+//!
+//! \return This function returns the following values:
+//! - \b USBHCD_LPM_AVAIL - The transition to L1 state is scheduled to be sent.
+//! - \b USBHCD_LPM_PENDING - There is already an LPM request pending.
+//
+//*****************************************************************************
+uint32_t
+USBHostAudioLPMSleep(tUSBHostAudioInstance *psAudioInstance)
+{
+ //
+ // Call the host controller function to send the sleep command.
+ //
+ return(USBHCDLPMSleep(psAudioInstance->psDevice));
+}
+
+//*****************************************************************************
+//
+//! This function returns the current status of an LPM request.
+//!
+//! \param psAudioInstance is the audio device instance that was returned
+//! from the call to USBHostAudioOpen().
+//!
+//! This function returns the current status of LPM requests for a given
+//! device. This is called to determine if a previous request completed
+//! successfully or if there was an error.
+//!
+//! \return This function returns the following values:
+//! - \b USBHCD_LPM_AVAIL - There are no pending LPM requests on this specific
+//! device or the last request completed successfully.
+//! - \b USBHCD_LPM_ERROR - The last LPM request for this device did not
+//! complete successfully.
+//! - \b USBHCD_LPM_PENDING - The last LPM request has not completed.
+//
+//*****************************************************************************
+uint32_t
+USBHostAudioLPMStatus(tUSBHostAudioInstance *psAudioInstance)
+{
+ //
+ // Call the host controller function to get the current LPM status.
+ //
+ return(USBHCDLPMStatus(psAudioInstance->psDevice));
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
+