SAMV71 Xplained Ultra Software Package 1.5

AUDDSpeakerPhoneDriver.c

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