SAMV71 Xplained Ultra Software Package 1.4

AUDDSpeakerPhoneDriver.c

Go to the documentation of this file.
00001 /* ----------------------------------------------------------------------------
00002  *         ATMEL Microcontroller Software Support
00003  * ----------------------------------------------------------------------------
00004  * Copyright (c) 2008, Atmel Corporation
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *
00011  * - Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the disclaimer below.
00013  *
00014  * Atmel's name may not be used to endorse or promote products derived from
00015  * this software without specific prior written permission.
00016  *
00017  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
00020  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00022  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00023  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00024  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00025  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00026  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  * ----------------------------------------------------------------------------
00028  */
00029 
00030 /** \file
00031  * \addtogroup usbd_audio_speakerphone
00032  *@{
00033  */
00034 
00035 /*------------------------------------------------------------------------------
00036  *         Headers
00037  *------------------------------------------------------------------------------*/
00038 
00039 #include <AUDDSpeakerPhoneDriver.h>
00040 
00041 #include <AUDRequests.h>
00042 
00043 #include <USBLib_Trace.h>
00044 
00045 /*------------------------------------------------------------------------------
00046  *         Internal types
00047  *------------------------------------------------------------------------------*/
00048 
00049 /**
00050  * Structs of USB Audio Stream Function Interface.
00051  */
00052 typedef struct _AUDDStream {
00053 
00054     /* -- USB Interface settings -- */
00055     /** Audio Control Interface Number */
00056     uint8_t  bAcInterface;
00057     /** Audio Streaming Interface Number */
00058     uint8_t  bAsInterface;
00059     /** Audio Streaming endpoint address */
00060     uint8_t  bEpNum;
00061     /** Audio Control Unit ID */
00062     uint8_t  bUnitID;
00063 
00064     /* -- Channel settings -- */
00065     /** Number of channels (including master 0, max 32) */
00066     uint16_t  bNumChannels;
00067     /** Mute Controls bitmap */
00068     uint16_t  bmMuteControls;
00069     /** Volume Controls (Master,L,R..) array */
00070     uint16_t *pVolumes;
00071 } AUDDStream;
00072 
00073 /**
00074  * \brief Audio SpeakerPhone driver internal state.
00075  */
00076 typedef struct _AUDDSpeakerPhoneDriver {
00077 
00078     /** Pointer to USBDDriver instance */
00079     USBDDriver * pUsbd;
00080     /** Intermediate storage variable for the mute status of a stream */
00081     uint8_t    muted;
00082     /** Array for storing the current setting of each interface. */
00083     uint8_t    interfaces[3];
00084     /** Audio Speaker interface */
00085     AUDDStream speaker;
00086     /** Audio Microphone interface */
00087     AUDDStream mic;
00088 } AUDDSpeakerPhoneDriver;
00089 
00090 /*------------------------------------------------------------------------------
00091  *         Internal variables
00092  *------------------------------------------------------------------------------*/
00093 
00094 /** Global USB audio SpeakerPhone driver instance. */
00095 static AUDDSpeakerPhoneDriver auddSpeakerPhoneDriver;
00096 
00097 /*------------------------------------------------------------------------------
00098  *         Internal functions
00099  *------------------------------------------------------------------------------*/
00100 
00101 /**
00102  * Parse descriptors: Interrupt IN, Bulk EP IN/OUT.
00103  * \param desc Pointer to descriptor.
00104  * \param arg  Argument, pointer to AUDDSpeakerPhoneDriver instance.
00105  */
00106 static uint32_t AUDDSpeakerPhone_Parse(USBGenericDescriptor* desc,
00107                                        AUDDSpeakerPhoneDriver* arg)
00108 {
00109     /* Not a valid descriptor */
00110     if (desc->bLength == 0) {
00111         return USBD_STATUS_INVALID_PARAMETER;
00112     }
00113     /* Parse endpoint descriptor */
00114     if (desc->bDescriptorType == USBGenericDescriptor_ENDPOINT) {
00115         USBEndpointDescriptor *pEP = (USBEndpointDescriptor*)desc;
00116         if (pEP->bmAttributes == USBEndpointDescriptor_ISOCHRONOUS) {
00117             if (pEP->bEndpointAddress & 0x80)
00118                 arg->mic.bEpNum = pEP->bEndpointAddress & 0x7F;
00119             else
00120                 arg->speaker.bEpNum = pEP->bEndpointAddress;
00121         }
00122     }
00123     return 0;
00124 }
00125 
00126 /**
00127  * Callback triggered after the new mute status of a channel has been read
00128  * by AUDDSpeakerPhoneDriver_SetFeatureCurrentValue. Changes the mute status
00129  * of the given channel accordingly.
00130  * \param channel Number of the channel whose mute status has changed.
00131  */
00132 static void AUDDSpeakerPhone_MuteReceived(uint32_t channel)
00133 {
00134     AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver;
00135     AUDDStream *pAuds;
00136 
00137     if ((uint8_t)(channel >> 8) ==
00138         AUDDSpeakerPhoneDriverDescriptors_OUTPUTTERMINAL_REC) {
00139         pAuds = &pAudd->mic;
00140     }
00141     else {
00142         pAuds = &pAudd->speaker;
00143     }
00144 
00145     if (pAudd->muted != pAuds->bmMuteControls) {
00146         pAuds->bmMuteControls = pAudd->muted;
00147         AUDDSpeakerPhoneDriver_MuteChanged(0, channel, pAudd->muted);
00148     }
00149     USBD_Write(0, 0, 0, 0, 0);
00150 }
00151 
00152 /**
00153  * Handle the SET_CUR request.
00154  * \param pReq Pointer to USBGenericRequest instance.
00155  */
00156 static void AUDDSpeakerPhone_SetCUR(const USBGenericRequest* pReq)
00157 {
00158     AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver;
00159     uint8_t bIf     = AUDGenericRequest_GetInterface(pReq);
00160     uint8_t bEntity = AUDGenericRequest_GetEntity(pReq);
00161     uint8_t bLength = USBGenericRequest_GetLength(pReq);
00162     uint8_t bCh     = AUDFeatureUnitRequest_GetChannel(pReq);
00163     uint8_t bCtrl   = AUDFeatureUnitRequest_GetControl(pReq);
00164     uint8_t bSet = 0;
00165     AUDDStream *pAuds = 0;
00166 
00167     TRACE_INFO_WP("sCUR ");
00168     TRACE_DEBUG("\b(E%d, CtlS%d, Ch%d, L%d) ", bEntity, bCtrl, bCh, bLength);
00169     /* Only AC.FeatureUnit accepted */
00170     if (bCtrl == AUDFeatureUnitRequest_MUTE
00171         && bLength == 1) {
00172 
00173         if (bEntity == pAudd->speaker.bUnitID)
00174             pAuds = &pAudd->speaker;
00175         else if (bEntity == pAudd->mic.bUnitID)
00176             pAuds = &pAudd->mic;
00177 
00178         if (pAuds != 0
00179             && bIf == pAuds->bAcInterface
00180             && bCh <= pAuds->bNumChannels) {
00181             bSet = 1;
00182         }
00183     }
00184 
00185     if (bSet) {
00186 
00187         uint32_t argument = bCh | (bEntity << 8);
00188         USBD_Read(0, /* Endpoint #0 */
00189                   &pAudd->muted,
00190                   sizeof(uint8_t),
00191                   (TransferCallback) AUDDSpeakerPhone_MuteReceived,
00192                   (void *) argument);
00193     }
00194     else {
00195 
00196         USBD_Stall(0);
00197     }
00198 
00199 }
00200 
00201 /**
00202  * Handle the GET_CUR request.
00203  * \param pReq Pointer to USBGenericRequest instance.
00204  */
00205 static void AUDDSpeakerPhone_GetCUR(const USBGenericRequest *pReq)
00206 {
00207     AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver;
00208     uint8_t bIf     = AUDGenericRequest_GetInterface(pReq);
00209     uint8_t bEntity = AUDGenericRequest_GetEntity(pReq);
00210     uint8_t bLength = USBGenericRequest_GetLength(pReq);
00211     uint8_t bCh     = AUDFeatureUnitRequest_GetChannel(pReq);
00212     uint8_t bCtrl   = AUDFeatureUnitRequest_GetControl(pReq);
00213     uint8_t bGet = 0;
00214     AUDDStream *pAuds = 0;
00215 
00216     TRACE_INFO_WP("gCUR ");
00217     TRACE_DEBUG("\b(E%d, CtlS%d, Ch%d, L%d) ", bEntity, bCtrl, bCh, bLength);
00218     /* Only AC.FeatureUnit accepted */
00219     if (bCtrl == AUDFeatureUnitRequest_MUTE
00220         && bLength == 1) {
00221 
00222         if (bEntity == pAudd->speaker.bUnitID)
00223             pAuds = &pAudd->speaker;
00224         else if (bEntity == pAudd->mic.bUnitID)
00225             pAuds = &pAudd->mic;
00226 
00227         if (pAuds != 0
00228             && bIf == pAuds->bAcInterface
00229             && bCh <= pAuds->bNumChannels) {
00230             bGet = 1;
00231         }
00232     }
00233 
00234     if (bGet) {
00235 
00236         pAudd->muted = pAuds->bmMuteControls;
00237         USBD_Write(0, &pAudd->muted, sizeof(uint8_t), 0, 0);
00238     }
00239     else {
00240 
00241         USBD_Stall(0);
00242     }
00243 }
00244 
00245 /*------------------------------------------------------------------------------
00246  *         Exported functions
00247  *------------------------------------------------------------------------------*/
00248 
00249 /**
00250  * Initializes an USB audio SpeakerPhone device driver, as well as the underlying
00251  * USB controller.
00252  */
00253 void AUDDSpeakerPhoneDriver_Initialize(const USBDDriverDescriptors *pDescriptors)
00254 {
00255     AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver;
00256     USBDDriver *pUsbd = USBD_GetDriver();
00257 
00258     pAudd->pUsbd = pUsbd;
00259 
00260     /* Initialize SpeakerPhone channels */
00261     pAudd->speaker.bNumChannels = 3;
00262     pAudd->speaker.bmMuteControls = 0;
00263     pAudd->speaker.pVolumes = 0;
00264 
00265     pAudd->mic.bNumChannels = 1;
00266     pAudd->mic.bmMuteControls = 0;
00267     pAudd->mic.pVolumes = 0;
00268 
00269     pAudd->mic.bAcInterface = AUDDSpeakerPhoneDriverDescriptors_CONTROL;
00270     pAudd->mic.bAsInterface = AUDDSpeakerPhoneDriverDescriptors_STREAMINGIN;
00271     pAudd->mic.bEpNum = 5;//AUDDSpeakerPhoneDriverDescriptors_DATAIN;
00272     pAudd->mic.bUnitID = AUDDSpeakerPhoneDriverDescriptors_FEATUREUNIT_REC;
00273 
00274     pAudd->speaker.bAcInterface = AUDDSpeakerPhoneDriverDescriptors_CONTROL;
00275     pAudd->speaker.bAsInterface = AUDDSpeakerPhoneDriverDescriptors_STREAMING;
00276     pAudd->speaker.bEpNum = 4;//AUDDSpeakerPhoneDriverDescriptors_DATAOUT;
00277     pAudd->speaker.bUnitID = AUDDSpeakerPhoneDriverDescriptors_FEATUREUNIT;
00278 
00279     /* Initialize the USB driver */
00280     USBDDriver_Initialize(pUsbd,
00281                           pDescriptors,
00282                           pAudd->interfaces);
00283     USBD_Init();
00284 
00285 }
00286 
00287 /**
00288  * Invoked whenever the active configuration of device is changed by the
00289  * host.
00290  * \param cfgnum Configuration number.
00291  */
00292 void AUDDSpeakerPhoneDriver_ConfigurationChangeHandler(uint8_t cfgnum)
00293 {
00294     AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver;
00295     const USBDDriverDescriptors *pDescriptors = pAudd->pUsbd->pDescriptors;
00296     USBConfigurationDescriptor *pDesc;
00297 
00298     if (cfgnum > 0) {
00299 
00300         /* Parse endpoints for data & notification */
00301         if (USBD_HAL_IsHighSpeed() && pDescriptors->pHsConfiguration)
00302             pDesc = (USBConfigurationDescriptor*)pDescriptors->pHsConfiguration;
00303         else
00304             pDesc = (USBConfigurationDescriptor*)pDescriptors->pFsConfiguration;
00305 
00306         USBGenericDescriptor_Parse((USBGenericDescriptor*)pDesc, pDesc->wTotalLength,
00307                     (USBDescriptorParseFunction)AUDDSpeakerPhone_Parse, pAudd);
00308     }
00309 }
00310 
00311 /**
00312  * Invoked whenever the active setting of an interface is changed by the
00313  * host. Changes the status of the third LED accordingly.
00314  * \param interface Interface number.
00315  * \param setting Newly active setting.
00316  */
00317 void AUDDSpeakerPhoneDriver_InterfaceSettingChangedHandler(uint8_t interface,
00318                                                            uint8_t setting)
00319 {
00320     AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver;
00321 
00322     if (interface == pAudd->speaker.bAsInterface) {
00323         /* reset ISO OUT ep */
00324         if (setting == 0 && pAudd->speaker.bEpNum) {
00325             USBD_HAL_ResetEPs(1 << pAudd->speaker.bEpNum,
00326                               USBD_STATUS_CANCELED, 1);
00327         }
00328         AUDDSpeakerPhoneDriver_StreamSettingChanged(0, setting);
00329     }
00330     if (interface == pAudd->mic.bAsInterface) {
00331         /* reset ISO IN ep */
00332         if (setting == 0 && pAudd->mic.bEpNum) {
00333             USBD_HAL_ResetEPs(1 << pAudd->mic.bEpNum,
00334                               USBD_STATUS_CANCELED, 1);
00335         }
00336         AUDDSpeakerPhoneDriver_StreamSettingChanged(1, setting);
00337     }
00338 }
00339 
00340 
00341 /**
00342  *  Handles audio-specific USB requests sent by the host, and forwards
00343  *  standard ones to the USB device driver.
00344  *  \param request Pointer to a USBGenericRequest instance.
00345  */
00346 void AUDDSpeakerPhoneDriver_RequestHandler(const USBGenericRequest *request)
00347 {
00348     AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver;
00349     USBDDriver *pUsbd = pAudd->pUsbd;
00350 
00351     TRACE_INFO_WP("NewReq ");
00352 
00353     /* Check if this is a class request */
00354     if (USBGenericRequest_GetType(request) == USBGenericRequest_CLASS) {
00355 
00356         /* Check if the request is supported */
00357         switch (USBGenericRequest_GetRequest(request)) {
00358 
00359             case AUDGenericRequest_SETCUR:
00360 
00361                 AUDDSpeakerPhone_SetCUR(request);
00362                 break;
00363 
00364             case AUDGenericRequest_GETCUR:
00365 
00366                 AUDDSpeakerPhone_GetCUR(request);
00367                 break;
00368 
00369             default:
00370 
00371                 TRACE_WARNING(
00372                           "AUDDSpeakerPhoneDriver_RequestHandler: Unsupported request (%d)\n\r",
00373                           USBGenericRequest_GetRequest(request));
00374                 USBD_Stall(0);
00375         }
00376     }
00377     /* Check if this is a standard request */
00378     else if (USBGenericRequest_GetType(request) == USBGenericRequest_STANDARD) {
00379 
00380         /* Forward request to the standard handler */
00381         USBDDriver_RequestHandler(pUsbd, request);
00382     }
00383     /* Unsupported request type */
00384     else {
00385 
00386         TRACE_WARNING(
00387                   "AUDDSpeakerPhoneDriver_RequestHandler: Unsupported request type (%d)\n\r",
00388                   USBGenericRequest_GetType(request));
00389         USBD_Stall(0);
00390     }
00391 }
00392 
00393 /**
00394  * Reads incoming audio data sent by the USB host into the provided
00395  * buffer. When the transfer is complete, an optional callback function is
00396  * invoked.
00397  * \param buffer Pointer to the data storage buffer.
00398  * \param length Size of the buffer in bytes.
00399  * \param callback Optional callback function.
00400  * \param argument Optional argument to the callback function.
00401  * \return USBD_STATUS_SUCCESS if the transfer is started successfully;
00402  *         otherwise an error code.
00403  */
00404 uint8_t AUDDSpeakerPhoneDriver_Read(void *buffer,
00405                                     uint32_t length,
00406                                     TransferCallback callback,
00407                                     void *argument)
00408 {
00409     AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver;
00410     return USBD_Read(pAudd->speaker.bEpNum,
00411                      buffer,
00412                      length,
00413                      callback,
00414                      argument);
00415 }
00416 
00417 /**
00418  * Initialize Frame List for sending audio data.
00419  *
00420  * \param pListInit Pointer to the allocated list for audio write.
00421  * \param pDmaInit  Pointer to the allocated DMA descriptors for autio write
00422  *                  (if DMA supported).
00423  * \param listSize  Circular list size.
00424  * \param delaySize Start transfer after delaySize frames filled in.
00425  * \param callback  Optional callback function for transfer.
00426  * \param argument  Optional callback argument.
00427  * \return USBD_STATUS_SUCCESS if setup successfully; otherwise an error code.
00428  */
00429 uint8_t AUDDSpeakerPhoneDriver_SetupWrite(void * pListInit,
00430                                           void * pDmaInit,
00431                                           uint16_t listSize,
00432                                           uint16_t delaySize,
00433                                           TransferCallback callback,
00434                                           void * argument)
00435 {
00436     AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver;
00437     uint8_t error;
00438     pDmaInit = pDmaInit;
00439 
00440     if (pAudd->mic.bEpNum == 0)
00441         return USBRC_STATE_ERR;
00442 
00443     error = USBD_HAL_SetupMblTransfer(pAudd->mic.bEpNum,
00444                                       pListInit,
00445                                       listSize,
00446                                       delaySize);
00447     if (error)  return error;
00448     error = USBD_HAL_SetTransferCallback(
00449                                     pAudd->mic.bEpNum,
00450                                     callback, argument);
00451     return error;
00452 }
00453 
00454 /**
00455  *  Add frame buffer to audio sending list.
00456  *  \buffer Pointer to data frame to send.
00457  *  \length Frame size in bytes.
00458  *  \return USBD_STATUS_SUCCESS if the transfer is started successfully;
00459  *          otherwise an error code.
00460  */
00461 uint8_t AUDDSpeakerPhoneDriver_Write(void* buffer, uint16_t length)
00462 {
00463     AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver;
00464 
00465     return USBD_HAL_Write(pAudd->mic.bEpNum,
00466                           buffer, length);
00467 }
00468 
00469 /**@}*/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines