mirror of
https://gitea.osmocom.org/sim-card/simtrace2.git
synced 2026-03-19 23:08:34 +03:00
Renamed main folder to firmware
This commit is contained in:
@@ -0,0 +1,468 @@
|
||||
/* ----------------------------------------------------------------------------
|
||||
* ATMEL Microcontroller Software Support
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2008, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \addtogroup usbd_audio_speakerphone
|
||||
*@{
|
||||
*/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Headers
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#include <AUDDSpeakerPhoneDriver.h>
|
||||
|
||||
#include <AUDRequests.h>
|
||||
|
||||
#include <USBLib_Trace.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Internal types
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Structs of USB Audio Stream Function Interface.
|
||||
*/
|
||||
typedef struct _AUDDStream {
|
||||
|
||||
/* -- USB Interface settings -- */
|
||||
/** Audio Control Interface Number */
|
||||
uint8_t bAcInterface;
|
||||
/** Audio Streaming Interface Number */
|
||||
uint8_t bAsInterface;
|
||||
/** Audio Streaming endpoint address */
|
||||
uint8_t bEpNum;
|
||||
/** Audio Control Unit ID */
|
||||
uint8_t bUnitID;
|
||||
|
||||
/* -- Channel settings -- */
|
||||
/** Number of channels (including master 0, max 32) */
|
||||
uint16_t bNumChannels;
|
||||
/** Mute Controls bitmap */
|
||||
uint16_t bmMuteControls;
|
||||
/** Volume Controls (Master,L,R..) array */
|
||||
uint16_t *pVolumes;
|
||||
} AUDDStream;
|
||||
|
||||
/**
|
||||
* \brief Audio SpeakerPhone driver internal state.
|
||||
*/
|
||||
typedef struct _AUDDSpeakerPhoneDriver {
|
||||
|
||||
/** Pointer to USBDDriver instance */
|
||||
USBDDriver * pUsbd;
|
||||
/** Intermediate storage variable for the mute status of a stream */
|
||||
uint8_t muted;
|
||||
/** Array for storing the current setting of each interface. */
|
||||
uint8_t interfaces[3];
|
||||
/** Audio Speaker interface */
|
||||
AUDDStream speaker;
|
||||
/** Audio Microphone interface */
|
||||
AUDDStream mic;
|
||||
} AUDDSpeakerPhoneDriver;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Internal variables
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/** Global USB audio SpeakerPhone driver instance. */
|
||||
static AUDDSpeakerPhoneDriver auddSpeakerPhoneDriver;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Internal functions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Parse descriptors: Interrupt IN, Bulk EP IN/OUT.
|
||||
* \param desc Pointer to descriptor.
|
||||
* \param arg Argument, pointer to AUDDSpeakerPhoneDriver instance.
|
||||
*/
|
||||
static uint32_t AUDDSpeakerPhone_Parse(USBGenericDescriptor* desc,
|
||||
AUDDSpeakerPhoneDriver* arg)
|
||||
{
|
||||
/* Not a valid descriptor */
|
||||
if (desc->bLength == 0) {
|
||||
return USBD_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
/* Parse endpoint descriptor */
|
||||
if (desc->bDescriptorType == USBGenericDescriptor_ENDPOINT) {
|
||||
USBEndpointDescriptor *pEP = (USBEndpointDescriptor*)desc;
|
||||
if (pEP->bmAttributes == USBEndpointDescriptor_ISOCHRONOUS) {
|
||||
if (pEP->bEndpointAddress & 0x80)
|
||||
arg->mic.bEpNum = pEP->bEndpointAddress & 0x7F;
|
||||
else
|
||||
arg->speaker.bEpNum = pEP->bEndpointAddress;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback triggered after the new mute status of a channel has been read
|
||||
* by AUDDSpeakerPhoneDriver_SetFeatureCurrentValue. Changes the mute status
|
||||
* of the given channel accordingly.
|
||||
* \param channel Number of the channel whose mute status has changed.
|
||||
*/
|
||||
static void AUDDSpeakerPhone_MuteReceived(uint32_t channel)
|
||||
{
|
||||
AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver;
|
||||
AUDDStream *pAuds;
|
||||
|
||||
if ((uint8_t)(channel >> 8) ==
|
||||
AUDDSpeakerPhoneDriverDescriptors_OUTPUTTERMINAL_REC) {
|
||||
pAuds = &pAudd->mic;
|
||||
}
|
||||
else {
|
||||
pAuds = &pAudd->speaker;
|
||||
}
|
||||
|
||||
if (pAudd->muted != pAuds->bmMuteControls) {
|
||||
pAuds->bmMuteControls = pAudd->muted;
|
||||
AUDDSpeakerPhoneDriver_MuteChanged(0, channel, pAudd->muted);
|
||||
}
|
||||
USBD_Write(0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the SET_CUR request.
|
||||
* \param pReq Pointer to USBGenericRequest instance.
|
||||
*/
|
||||
static void AUDDSpeakerPhone_SetCUR(const USBGenericRequest* pReq)
|
||||
{
|
||||
AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver;
|
||||
uint8_t bIf = AUDGenericRequest_GetInterface(pReq);
|
||||
uint8_t bEntity = AUDGenericRequest_GetEntity(pReq);
|
||||
uint8_t bLength = USBGenericRequest_GetLength(pReq);
|
||||
uint8_t bCh = AUDFeatureUnitRequest_GetChannel(pReq);
|
||||
uint8_t bCtrl = AUDFeatureUnitRequest_GetControl(pReq);
|
||||
uint8_t bSet = 0;
|
||||
AUDDStream *pAuds = 0;
|
||||
|
||||
TRACE_INFO_WP("sCUR ");
|
||||
TRACE_DEBUG("\b(E%d, CtlS%d, Ch%d, L%d) ", bEntity, bCtrl, bCh, bLength);
|
||||
/* Only AC.FeatureUnit accepted */
|
||||
if (bCtrl == AUDFeatureUnitRequest_MUTE
|
||||
&& bLength == 1) {
|
||||
|
||||
if (bEntity == pAudd->speaker.bUnitID)
|
||||
pAuds = &pAudd->speaker;
|
||||
else if (bEntity == pAudd->mic.bUnitID)
|
||||
pAuds = &pAudd->mic;
|
||||
|
||||
if (pAuds != 0
|
||||
&& bIf == pAuds->bAcInterface
|
||||
&& bCh <= pAuds->bNumChannels) {
|
||||
bSet = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (bSet) {
|
||||
|
||||
uint32_t argument = bCh | (bEntity << 8);
|
||||
USBD_Read(0, /* Endpoint #0 */
|
||||
&pAudd->muted,
|
||||
sizeof(uint8_t),
|
||||
(TransferCallback) AUDDSpeakerPhone_MuteReceived,
|
||||
(void *) argument);
|
||||
}
|
||||
else {
|
||||
|
||||
USBD_Stall(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the GET_CUR request.
|
||||
* \param pReq Pointer to USBGenericRequest instance.
|
||||
*/
|
||||
static void AUDDSpeakerPhone_GetCUR(const USBGenericRequest *pReq)
|
||||
{
|
||||
AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver;
|
||||
uint8_t bIf = AUDGenericRequest_GetInterface(pReq);
|
||||
uint8_t bEntity = AUDGenericRequest_GetEntity(pReq);
|
||||
uint8_t bLength = USBGenericRequest_GetLength(pReq);
|
||||
uint8_t bCh = AUDFeatureUnitRequest_GetChannel(pReq);
|
||||
uint8_t bCtrl = AUDFeatureUnitRequest_GetControl(pReq);
|
||||
uint8_t bGet = 0;
|
||||
AUDDStream *pAuds = 0;
|
||||
|
||||
TRACE_INFO_WP("gCUR ");
|
||||
TRACE_DEBUG("\b(E%d, CtlS%d, Ch%d, L%d) ", bEntity, bCtrl, bCh, bLength);
|
||||
/* Only AC.FeatureUnit accepted */
|
||||
if (bCtrl == AUDFeatureUnitRequest_MUTE
|
||||
&& bLength == 1) {
|
||||
|
||||
if (bEntity == pAudd->speaker.bUnitID)
|
||||
pAuds = &pAudd->speaker;
|
||||
else if (bEntity == pAudd->mic.bUnitID)
|
||||
pAuds = &pAudd->mic;
|
||||
|
||||
if (pAuds != 0
|
||||
&& bIf == pAuds->bAcInterface
|
||||
&& bCh <= pAuds->bNumChannels) {
|
||||
bGet = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (bGet) {
|
||||
|
||||
pAudd->muted = pAuds->bmMuteControls;
|
||||
USBD_Write(0, &pAudd->muted, sizeof(uint8_t), 0, 0);
|
||||
}
|
||||
else {
|
||||
|
||||
USBD_Stall(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Initializes an USB audio SpeakerPhone device driver, as well as the underlying
|
||||
* USB controller.
|
||||
*/
|
||||
void AUDDSpeakerPhoneDriver_Initialize(const USBDDriverDescriptors *pDescriptors)
|
||||
{
|
||||
AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver;
|
||||
USBDDriver *pUsbd = USBD_GetDriver();
|
||||
|
||||
pAudd->pUsbd = pUsbd;
|
||||
|
||||
/* Initialize SpeakerPhone channels */
|
||||
pAudd->speaker.bNumChannels = 3;
|
||||
pAudd->speaker.bmMuteControls = 0;
|
||||
pAudd->speaker.pVolumes = 0;
|
||||
|
||||
pAudd->mic.bNumChannels = 1;
|
||||
pAudd->mic.bmMuteControls = 0;
|
||||
pAudd->mic.pVolumes = 0;
|
||||
|
||||
pAudd->mic.bAcInterface = AUDDSpeakerPhoneDriverDescriptors_CONTROL;
|
||||
pAudd->mic.bAsInterface = AUDDSpeakerPhoneDriverDescriptors_STREAMINGIN;
|
||||
pAudd->mic.bEpNum = 5;//AUDDSpeakerPhoneDriverDescriptors_DATAIN;
|
||||
pAudd->mic.bUnitID = AUDDSpeakerPhoneDriverDescriptors_FEATUREUNIT_REC;
|
||||
|
||||
pAudd->speaker.bAcInterface = AUDDSpeakerPhoneDriverDescriptors_CONTROL;
|
||||
pAudd->speaker.bAsInterface = AUDDSpeakerPhoneDriverDescriptors_STREAMING;
|
||||
pAudd->speaker.bEpNum = 4;//AUDDSpeakerPhoneDriverDescriptors_DATAOUT;
|
||||
pAudd->speaker.bUnitID = AUDDSpeakerPhoneDriverDescriptors_FEATUREUNIT;
|
||||
|
||||
/* Initialize the USB driver */
|
||||
USBDDriver_Initialize(pUsbd,
|
||||
pDescriptors,
|
||||
pAudd->interfaces);
|
||||
USBD_Init();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked whenever the active configuration of device is changed by the
|
||||
* host.
|
||||
* \param cfgnum Configuration number.
|
||||
*/
|
||||
void AUDDSpeakerPhoneDriver_ConfigurationChangeHandler(uint8_t cfgnum)
|
||||
{
|
||||
AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver;
|
||||
const USBDDriverDescriptors *pDescriptors = pAudd->pUsbd->pDescriptors;
|
||||
USBConfigurationDescriptor *pDesc;
|
||||
|
||||
if (cfgnum > 0) {
|
||||
|
||||
/* Parse endpoints for data & notification */
|
||||
if (USBD_HAL_IsHighSpeed() && pDescriptors->pHsConfiguration)
|
||||
pDesc = (USBConfigurationDescriptor*)pDescriptors->pHsConfiguration;
|
||||
else
|
||||
pDesc = (USBConfigurationDescriptor*)pDescriptors->pFsConfiguration[0];
|
||||
|
||||
USBGenericDescriptor_Parse((USBGenericDescriptor*)pDesc, pDesc->wTotalLength,
|
||||
(USBDescriptorParseFunction)AUDDSpeakerPhone_Parse, pAudd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked whenever the active setting of an interface is changed by the
|
||||
* host. Changes the status of the third LED accordingly.
|
||||
* \param interface Interface number.
|
||||
* \param setting Newly active setting.
|
||||
*/
|
||||
void AUDDSpeakerPhoneDriver_InterfaceSettingChangedHandler(uint8_t interface,
|
||||
uint8_t setting)
|
||||
{
|
||||
AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver;
|
||||
|
||||
if (interface == pAudd->speaker.bAsInterface) {
|
||||
/* reset ISO OUT ep */
|
||||
if (setting == 0 && pAudd->speaker.bEpNum) {
|
||||
USBD_HAL_ResetEPs(1 << pAudd->speaker.bEpNum,
|
||||
USBD_STATUS_CANCELED, 1);
|
||||
}
|
||||
AUDDSpeakerPhoneDriver_StreamSettingChanged(0, setting);
|
||||
}
|
||||
if (interface == pAudd->mic.bAsInterface) {
|
||||
/* reset ISO IN ep */
|
||||
if (setting == 0 && pAudd->mic.bEpNum) {
|
||||
USBD_HAL_ResetEPs(1 << pAudd->mic.bEpNum,
|
||||
USBD_STATUS_CANCELED, 1);
|
||||
}
|
||||
AUDDSpeakerPhoneDriver_StreamSettingChanged(1, setting);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles audio-specific USB requests sent by the host, and forwards
|
||||
* standard ones to the USB device driver.
|
||||
* \param request Pointer to a USBGenericRequest instance.
|
||||
*/
|
||||
void AUDDSpeakerPhoneDriver_RequestHandler(const USBGenericRequest *request)
|
||||
{
|
||||
AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver;
|
||||
USBDDriver *pUsbd = pAudd->pUsbd;
|
||||
|
||||
TRACE_INFO_WP("NewReq ");
|
||||
|
||||
/* Check if this is a class request */
|
||||
if (USBGenericRequest_GetType(request) == USBGenericRequest_CLASS) {
|
||||
|
||||
/* Check if the request is supported */
|
||||
switch (USBGenericRequest_GetRequest(request)) {
|
||||
|
||||
case AUDGenericRequest_SETCUR:
|
||||
|
||||
AUDDSpeakerPhone_SetCUR(request);
|
||||
break;
|
||||
|
||||
case AUDGenericRequest_GETCUR:
|
||||
|
||||
AUDDSpeakerPhone_GetCUR(request);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
TRACE_WARNING(
|
||||
"AUDDSpeakerPhoneDriver_RequestHandler: Unsupported request (%d)\n\r",
|
||||
USBGenericRequest_GetRequest(request));
|
||||
USBD_Stall(0);
|
||||
}
|
||||
}
|
||||
/* Check if this is a standard request */
|
||||
else if (USBGenericRequest_GetType(request) == USBGenericRequest_STANDARD) {
|
||||
|
||||
/* Forward request to the standard handler */
|
||||
USBDDriver_RequestHandler(pUsbd, request);
|
||||
}
|
||||
/* Unsupported request type */
|
||||
else {
|
||||
|
||||
TRACE_WARNING(
|
||||
"AUDDSpeakerPhoneDriver_RequestHandler: Unsupported request type (%d)\n\r",
|
||||
USBGenericRequest_GetType(request));
|
||||
USBD_Stall(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads incoming audio data sent by the USB host into the provided
|
||||
* buffer. When the transfer is complete, an optional callback function is
|
||||
* invoked.
|
||||
* \param buffer Pointer to the data storage buffer.
|
||||
* \param length Size of the buffer in bytes.
|
||||
* \param callback Optional callback function.
|
||||
* \param argument Optional argument to the callback function.
|
||||
* \return USBD_STATUS_SUCCESS if the transfer is started successfully;
|
||||
* otherwise an error code.
|
||||
*/
|
||||
uint8_t AUDDSpeakerPhoneDriver_Read(void *buffer,
|
||||
uint32_t length,
|
||||
TransferCallback callback,
|
||||
void *argument)
|
||||
{
|
||||
AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver;
|
||||
return USBD_Read(pAudd->speaker.bEpNum,
|
||||
buffer,
|
||||
length,
|
||||
callback,
|
||||
argument);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Frame List for sending audio data.
|
||||
*
|
||||
* \param pListInit Pointer to the allocated list for audio write.
|
||||
* \param pDmaInit Pointer to the allocated DMA descriptors for autio write
|
||||
* (if DMA supported).
|
||||
* \param listSize Circular list size.
|
||||
* \param delaySize Start transfer after delaySize frames filled in.
|
||||
* \param callback Optional callback function for transfer.
|
||||
* \param argument Optional callback argument.
|
||||
* \return USBD_STATUS_SUCCESS if setup successfully; otherwise an error code.
|
||||
*/
|
||||
uint8_t AUDDSpeakerPhoneDriver_SetupWrite(void * pListInit,
|
||||
void * pDmaInit,
|
||||
uint16_t listSize,
|
||||
uint16_t delaySize,
|
||||
TransferCallback callback,
|
||||
void * argument)
|
||||
{
|
||||
AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver;
|
||||
uint8_t error;
|
||||
|
||||
if (pAudd->mic.bEpNum == 0)
|
||||
return USBRC_STATE_ERR;
|
||||
|
||||
error = USBD_HAL_SetupMblTransfer(pAudd->mic.bEpNum,
|
||||
pListInit,
|
||||
listSize,
|
||||
delaySize);
|
||||
if (error) return error;
|
||||
error = USBD_HAL_SetTransferCallback(
|
||||
pAudd->mic.bEpNum,
|
||||
callback, argument);
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add frame buffer to audio sending list.
|
||||
* \buffer Pointer to data frame to send.
|
||||
* \length Frame size in bytes.
|
||||
* \return USBD_STATUS_SUCCESS if the transfer is started successfully;
|
||||
* otherwise an error code.
|
||||
*/
|
||||
uint8_t AUDDSpeakerPhoneDriver_Write(void* buffer, uint16_t length)
|
||||
{
|
||||
AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver;
|
||||
|
||||
return USBD_HAL_Write(pAudd->mic.bEpNum,
|
||||
buffer, length);
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
@@ -0,0 +1,76 @@
|
||||
/* ----------------------------------------------------------------------------
|
||||
* ATMEL Microcontroller Software Support
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2010, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* Default callbacks implement for Audio SpeakerPhone Driver.
|
||||
*/
|
||||
|
||||
/** \addtogroup usbd_audio_speakerphone
|
||||
*@{
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Headers
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/* These headers were introduced in C99
|
||||
by working group ISO/IEC JTC1/SC22/WG14. */
|
||||
#include <stdint.h>
|
||||
|
||||
#include "AUDDSpeakerPhoneDriver.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Default WEAK Callbacks
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Invoked when an audio channel get muted or unmuted. Mutes/unmutes the
|
||||
* channel at the DAC level.
|
||||
* \param mic Microphone/Speaker stream changed.
|
||||
* \param channel Channel number that changed.
|
||||
* \param muted Indicates the new mute status of the channel.
|
||||
*/
|
||||
WEAK void AUDDSpeakerPhoneDriver_MuteChanged(uint8_t mic,uint8_t channel,uint8_t muted)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when an audio streaming interface setting changed. Actually control
|
||||
* streaming rate.
|
||||
* \param mic Microphone/Speaker stream changed.
|
||||
* \param newSetting New stream (interface) setting.
|
||||
*/
|
||||
WEAK void AUDDSpeakerPhoneDriver_StreamSettingChanged(uint8_t mic,uint8_t newSetting)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
@@ -0,0 +1,770 @@
|
||||
/* ----------------------------------------------------------------------------
|
||||
* ATMEL Microcontroller Software Support
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2008, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* USB Audio Device Streaming interface with controls.
|
||||
* (3 channels supported).
|
||||
*/
|
||||
|
||||
/** \addtogroup usbd_audio_speakerphone
|
||||
*@{
|
||||
*/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Headers
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#include <AUDDSpeakerPhone.h>
|
||||
|
||||
#include <USBDescriptors.h>
|
||||
#include <USBRequests.h>
|
||||
#include <AUDDescriptors.h>
|
||||
#include <AUDRequests.h>
|
||||
|
||||
#include <USBD_HAL.h>
|
||||
|
||||
#include <USBLib_Trace.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Types
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/** Parse data extention for descriptor parsing */
|
||||
typedef struct _AUDDParseData {
|
||||
/** Pointer to AUDDSpeakerPhone instance */
|
||||
AUDDSpeakerPhone * pAudf;
|
||||
/** Pointer to found interface descriptor */
|
||||
USBInterfaceDescriptor * pIfDesc;
|
||||
|
||||
} AUDDParseData;
|
||||
|
||||
/** Transfer callback extention */
|
||||
typedef struct _AUDDXfrExt {
|
||||
/** Pointer to AUDDStream instance */
|
||||
AUDDStream *pStream;
|
||||
/** Buffer for USB device to get data from host */
|
||||
uint16_t usbBuffer;
|
||||
/** Additional information: Entity */
|
||||
uint8_t bEntity;
|
||||
/** Additional information: Channel */
|
||||
uint8_t bCh;
|
||||
} AUDDXfrExt;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Internal Variable
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/** Transfer data extension */
|
||||
static AUDDXfrExt auddXfrData;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Internal Functions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Parse descriptors: Interface, ISO IN/OUT, Feature Unit IDs.
|
||||
* \param desc Pointer to descriptor list.
|
||||
* \param arg Argument, pointer to AUDDParseData instance.
|
||||
*/
|
||||
static uint32_t AUDDSpeakerPhone_Parse(USBGenericDescriptor *pDesc,
|
||||
AUDDParseData * pArg)
|
||||
{
|
||||
AUDDStream *pSpeaker = pArg->pAudf->pSpeaker;
|
||||
AUDDStream *pMic = pArg->pAudf->pMicrophone;
|
||||
USBEndpointDescriptor* pEp = (USBEndpointDescriptor*)pDesc;
|
||||
uint8_t bSpeakerDone = 0, bMicDone = 0;
|
||||
|
||||
/* Validate descriptor */
|
||||
if (pDesc->bLength == 0)
|
||||
return USBRC_PARAM_ERR;
|
||||
|
||||
/* Log current interface */
|
||||
if (pDesc->bDescriptorType == USBGenericDescriptor_INTERFACE) {
|
||||
USBInterfaceDescriptor* pIf = (USBInterfaceDescriptor*)pDesc;
|
||||
/* AudioControl interface */
|
||||
if (pIf->bInterfaceClass ==
|
||||
AUDControlInterfaceDescriptor_CLASS
|
||||
&& pIf->bInterfaceSubClass ==
|
||||
AUDControlInterfaceDescriptor_SUBCLASS) {
|
||||
pArg->pIfDesc = pIf;
|
||||
|
||||
if (pSpeaker) pSpeaker->bAcInterface = pIf->bInterfaceNumber;
|
||||
if (pMic) pMic->bAcInterface = pIf->bInterfaceNumber;
|
||||
}
|
||||
/* AudioStreaming interface with endpoint */
|
||||
else if (pIf->bInterfaceClass ==
|
||||
AUDStreamingInterfaceDescriptor_CLASS
|
||||
&& pIf->bInterfaceSubClass ==
|
||||
AUDStreamingInterfaceDescriptor_SUBCLASS) {
|
||||
pArg->pIfDesc = pIf;
|
||||
}
|
||||
/* Not Audio interface, force end */
|
||||
else if (pArg->pIfDesc){
|
||||
return USBRC_PARTIAL_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (pArg->pIfDesc) {
|
||||
/* Find Control Interface */
|
||||
/* Find Entities */
|
||||
/* Find Streaming Interface & Endpoints */
|
||||
if (pDesc->bDescriptorType == USBGenericDescriptor_ENDPOINT
|
||||
&& (pEp->bmAttributes & 0x3) == USBEndpointDescriptor_ISOCHRONOUS) {
|
||||
if (pEp->bEndpointAddress & 0x80
|
||||
&& pMic) {
|
||||
pMic->bEndpointIn = pEp->bEndpointAddress & 0x7F;
|
||||
pMic->bAsInterface = pArg->pIfDesc->bInterfaceNumber;
|
||||
/* Fixed FU */
|
||||
pMic->bFeatureUnitIn = AUDD_ID_MicrophoneFU;
|
||||
}
|
||||
else if (pSpeaker) {
|
||||
pSpeaker->bEndpointOut = pEp->bEndpointAddress;
|
||||
pSpeaker->bAsInterface = pArg->pIfDesc->bInterfaceNumber;
|
||||
/* Fixed FU */
|
||||
pSpeaker->bFeatureUnitOut = AUDD_ID_SpeakerFU;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pSpeaker) {
|
||||
if (pSpeaker->bAcInterface != 0xFF
|
||||
&& pSpeaker->bAsInterface != 0xFF
|
||||
&& pSpeaker->bFeatureUnitOut != 0xFF
|
||||
&& pSpeaker->bEndpointOut != 0) {
|
||||
bSpeakerDone = 1;
|
||||
}
|
||||
}
|
||||
else bSpeakerDone = 1;
|
||||
|
||||
if (pMic) {
|
||||
if (pMic->bAcInterface != 0xFF
|
||||
&& pMic->bAsInterface != 0xFF
|
||||
&& pMic->bFeatureUnitIn != 0xFF
|
||||
&& pMic->bEndpointIn != 0) {
|
||||
bMicDone = 1;
|
||||
}
|
||||
}
|
||||
else bMicDone = 1;
|
||||
|
||||
if (bSpeakerDone && bMicDone)
|
||||
return USBRC_FINISHED;
|
||||
|
||||
return USBRC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback triggered after the new mute status of a channel has been read.
|
||||
* Changes the mute status of the given channel accordingly.
|
||||
* \param pData Pointer to AUDDXfrExt (transfer extension data).
|
||||
*/
|
||||
static void AUDD_MuteReceived(AUDDXfrExt *pData)
|
||||
{
|
||||
AUDDStream_ChangeMute(pData->pStream,
|
||||
pData->bCh,
|
||||
(uint8_t)pData->usbBuffer);
|
||||
USBD_Write(0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback triggered after the new volume status of a channel has been read.
|
||||
* Changes the volume status of the given channel accordingly.
|
||||
* \param pData Pointer to AUDDXfrExt (transfer extension data).
|
||||
*/
|
||||
static void AUDD_VolumeReceived(AUDDXfrExt *pData)
|
||||
{
|
||||
AUDDStream_SetVolume(pData->pStream,
|
||||
pData->bCh,
|
||||
pData->usbBuffer);
|
||||
USBD_Write(0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Target AUDDStream for control
|
||||
* \param pAudf Pointer to AUDDSpeakerPhone instance.
|
||||
* \param bAcInterface Interface number
|
||||
* \param bEntity Entity ID
|
||||
* \param bChannel Channel number
|
||||
* \return Pointer to AUDDStream instance
|
||||
*/
|
||||
static AUDDStream *AUDD_GetCtlStream(
|
||||
AUDDSpeakerPhone *pAudf,
|
||||
uint8_t bAcInterface,
|
||||
uint8_t bEntity,
|
||||
uint8_t bChannel)
|
||||
{
|
||||
AUDDStream *pAuds = 0;
|
||||
|
||||
if (bEntity == pAudf->pSpeaker->bFeatureUnitOut
|
||||
|| bEntity == pAudf->pSpeaker->bFeatureUnitIn)
|
||||
pAuds = pAudf->pSpeaker;
|
||||
else if (bEntity == pAudf->pMicrophone->bFeatureUnitIn
|
||||
|| bEntity == pAudf->pMicrophone->bFeatureUnitOut)
|
||||
pAuds = pAudf->pMicrophone;
|
||||
|
||||
if (pAuds != 0
|
||||
&& bAcInterface == pAuds->bAcInterface
|
||||
&& bChannel <= pAuds->bNumChannels) {
|
||||
return pAuds;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the SET_CUR request.
|
||||
* \param pAudf Pointer to AUDDSpeakerPhone instance.
|
||||
* \param pReq Pointer to USBGenericRequest instance.
|
||||
*/
|
||||
static void AUDD_SetCUR(
|
||||
AUDDSpeakerPhone *pAudf,
|
||||
const USBGenericRequest* pReq)
|
||||
{
|
||||
uint8_t bIf = AUDGenericRequest_GetInterface(pReq);
|
||||
uint8_t bEntity = AUDGenericRequest_GetEntity(pReq);
|
||||
uint8_t bLength = USBGenericRequest_GetLength(pReq);
|
||||
uint8_t bCh = AUDFeatureUnitRequest_GetChannel(pReq);
|
||||
uint8_t bCtrl = AUDFeatureUnitRequest_GetControl(pReq);
|
||||
uint8_t bSet = 1;
|
||||
AUDDStream *pAuds = AUDD_GetCtlStream(pAudf, bIf, bEntity, bCh);
|
||||
TransferCallback fCallback;
|
||||
|
||||
TRACE_INFO_WP("sCUR ");
|
||||
TRACE_DEBUG("\b(E%d, CtlS%d, Ch%d, L%d) ", bEntity, bCtrl, bCh, bLength);
|
||||
|
||||
/* Set Mute to AC, 1 byte */
|
||||
if (bCtrl == AUDFeatureUnitRequest_MUTE
|
||||
&& bLength == 1
|
||||
&& pAuds) {
|
||||
fCallback = (TransferCallback) AUDD_MuteReceived;
|
||||
}
|
||||
else if (bCtrl == AUDFeatureUnitRequest_VOLUME
|
||||
&& bLength == 2
|
||||
&& pAuds && pAuds->pwVolumes) {
|
||||
fCallback = (TransferCallback) AUDD_VolumeReceived;
|
||||
}
|
||||
else
|
||||
bSet = 0;
|
||||
|
||||
if (bSet) {
|
||||
|
||||
auddXfrData.pStream = pAuds;
|
||||
auddXfrData.bEntity = bEntity;
|
||||
auddXfrData.bCh = bCh;
|
||||
USBD_Read(0,
|
||||
&auddXfrData.usbBuffer,
|
||||
bLength,
|
||||
fCallback,
|
||||
(void *) &auddXfrData);
|
||||
}
|
||||
else {
|
||||
|
||||
USBD_Stall(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the GET_CUR request.
|
||||
* \param pAudf Pointer to AUDDSpeakerPhone instance.
|
||||
* \param pReq Pointer to USBGenericRequest instance.
|
||||
*/
|
||||
static void AUDD_GetCUR(
|
||||
AUDDSpeakerPhone *pAudf,
|
||||
const USBGenericRequest *pReq)
|
||||
{
|
||||
uint8_t bIf = AUDGenericRequest_GetInterface(pReq);
|
||||
uint8_t bEntity = AUDGenericRequest_GetEntity(pReq);
|
||||
uint8_t bLength = USBGenericRequest_GetLength(pReq);
|
||||
uint8_t bCh = AUDFeatureUnitRequest_GetChannel(pReq);
|
||||
uint8_t bCtrl = AUDFeatureUnitRequest_GetControl(pReq);
|
||||
uint8_t bGet = 1;
|
||||
AUDDStream *pAuds = AUDD_GetCtlStream(pAudf, bIf, bEntity, bCh);
|
||||
|
||||
TRACE_INFO_WP("gCUR ");
|
||||
TRACE_DEBUG("\b(E%d, CtlS%d, Ch%d, L%d) ", bEntity, bCtrl, bCh, bLength);
|
||||
|
||||
/* Get Mute 1 byte */
|
||||
if (bCtrl == AUDFeatureUnitRequest_MUTE
|
||||
&& bLength == 1
|
||||
&& pAuds) {
|
||||
auddXfrData.usbBuffer = ((pAuds->bmMute & (1<<bCh)) > 0);
|
||||
}
|
||||
else if (bCtrl == AUDFeatureUnitRequest_VOLUME
|
||||
&& bLength == 2
|
||||
&& pAuds && pAuds->pwVolumes) {
|
||||
auddXfrData.usbBuffer = pAuds->pwVolumes[bCh];
|
||||
}
|
||||
else
|
||||
bGet = 0;
|
||||
|
||||
if (bGet) {
|
||||
|
||||
USBD_Write(0, &auddXfrData.usbBuffer, bLength, 0, 0);
|
||||
}
|
||||
else {
|
||||
|
||||
USBD_Stall(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Exported Functions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Initialize AUDDStream instance.
|
||||
* Note the number of channels excludes the master control, so
|
||||
* actual volume array size should be (1 + numChannels).
|
||||
* \param pAuds Pointer to AUDDStream instance.
|
||||
* \param numChannels Number of channels in the stream (<31).
|
||||
* \param wChannelVolumes Data array for channel volume values.
|
||||
* \param fCallback Callback function for stream events.
|
||||
* \param pArg Pointer to event handler arguments.
|
||||
*/
|
||||
void AUDDStream_Initialize(AUDDStream *pAuds,
|
||||
uint8_t numChannels,
|
||||
uint16_t wChannelVolumes[],
|
||||
AUDDStreamEventCallback fCallback,
|
||||
void* pArg)
|
||||
{
|
||||
pAuds->bAcInterface = 0xFF;
|
||||
pAuds->bFeatureUnitOut = 0xFF;
|
||||
pAuds->bFeatureUnitIn = 0xFF;
|
||||
pAuds->bAsInterface = 0xFF;
|
||||
pAuds->bEndpointOut = 0;
|
||||
pAuds->bEndpointIn = 0;
|
||||
|
||||
pAuds->bNumChannels = numChannels;
|
||||
pAuds->bmMute = 0;
|
||||
pAuds->pwVolumes = wChannelVolumes;
|
||||
|
||||
pAuds->fCallback = fCallback;
|
||||
pAuds->pArg = pArg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the request is accepted.
|
||||
* \param pAuds Pointer to AUDDStream instance.
|
||||
* \param pReq Pointer to a USBGenericRequest instance.
|
||||
* \return 1 if accepted.
|
||||
*/
|
||||
uint32_t AUDDStream_IsRequestAccepted(
|
||||
AUDDStream *pAuds,
|
||||
const USBGenericRequest *pReq)
|
||||
{
|
||||
uint8_t bIf = AUDGenericRequest_GetInterface(pReq);
|
||||
uint8_t bEntity = AUDGenericRequest_GetEntity(pReq);
|
||||
uint8_t bCh = AUDFeatureUnitRequest_GetChannel(pReq);
|
||||
/* AudioControl Interface */
|
||||
if (bIf == pAuds->bAcInterface) {
|
||||
if (bCh > pAuds->bNumChannels)
|
||||
return 0;
|
||||
if (bEntity != pAuds->bFeatureUnitIn
|
||||
&& bEntity != pAuds->bFeatureUnitOut)
|
||||
return 0;
|
||||
}
|
||||
/* AudioStream Interface not handled */
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change Stream Mute status.
|
||||
* \param pAuds Pointer to AUDDStream instance.
|
||||
* \param bChannel Channel number.
|
||||
* \param bmMute 1 to mute, 0 to unmute.
|
||||
*/
|
||||
uint32_t AUDDStream_ChangeMute(AUDDStream *pAuds,
|
||||
uint8_t bChannel,
|
||||
uint8_t bMute)
|
||||
{
|
||||
uint8_t bmMute = (bMute << bChannel);
|
||||
|
||||
if (pAuds->bNumChannels < bChannel)
|
||||
return USBRC_PARAM_ERR;
|
||||
|
||||
if (bMute)
|
||||
pAuds->bmMute |= bmMute;
|
||||
else
|
||||
pAuds->bmMute &= ~bmMute;
|
||||
|
||||
if (pAuds->fCallback)
|
||||
pAuds->fCallback(AUDD_EC_MuteChanged,
|
||||
bChannel,
|
||||
pAuds->pArg);
|
||||
|
||||
return USBRC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Stream Volume status.
|
||||
* \param pAuds Pointer to AUDDStream instance.
|
||||
* \param bChannel Channel number.
|
||||
* \param wVolume New volume value.
|
||||
*/
|
||||
uint32_t AUDDStream_SetVolume(AUDDStream *pAuds,
|
||||
uint8_t bChannel,
|
||||
uint16_t wVolume)
|
||||
{
|
||||
if (pAuds->pwVolumes == 0)
|
||||
return USBRC_PARAM_ERR;
|
||||
if (bChannel > pAuds->bNumChannels)
|
||||
return USBRC_PARAM_ERR;
|
||||
|
||||
pAuds->pwVolumes[bChannel] = wVolume;
|
||||
if (pAuds->fCallback) {
|
||||
pAuds->fCallback(AUDD_EC_VolumeChanged,
|
||||
bChannel,
|
||||
pAuds->pArg);
|
||||
}
|
||||
|
||||
return USBRC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives data from the host through the audio function (as speaker).
|
||||
* This function behaves like USBD_Read.
|
||||
* \param pAuds Pointer to AUDDStream instance.
|
||||
* \param pData Pointer to the data buffer to put received data.
|
||||
* \param dwSize Size of the data buffer in bytes.
|
||||
* \param fCallback Optional callback function to invoke when the transfer
|
||||
* finishes.
|
||||
* \param pArg Optional argument to the callback function.
|
||||
* \return USBD_STATUS_SUCCESS if the read operation has been started normally;
|
||||
* otherwise, the corresponding error code.
|
||||
*/
|
||||
uint32_t AUDDStream_Read(
|
||||
AUDDStream *pAuds,
|
||||
void * pData,uint32_t dwSize,
|
||||
TransferCallback fCallback,void * pArg)
|
||||
{
|
||||
if (pAuds->bEndpointOut == 0)
|
||||
return USBRC_PARAM_ERR;
|
||||
return USBD_Read(pAuds->bEndpointOut,
|
||||
pData, dwSize,
|
||||
fCallback, pArg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Frame List for sending audio data.
|
||||
* \param pAuds Pointer to AUDDStream instance.
|
||||
* \param pListInit Pointer to the allocated list for audio write.
|
||||
* \param pDmaInit Pointer to the allocated DMA descriptors for autio write
|
||||
* (if DMA supported).
|
||||
* \param listSize Circular list size.
|
||||
* \param delaySize Start transfer after delaySize frames filled in.
|
||||
* \param callback Optional callback function for transfer.
|
||||
* \param argument Optional callback argument.
|
||||
* \return USBD_STATUS_SUCCESS if setup successfully; otherwise an error code.
|
||||
*/
|
||||
uint32_t AUDDStream_SetupWrite(
|
||||
AUDDStream *pAuds,
|
||||
void * pListInit,
|
||||
void * pDmaInit,
|
||||
uint16_t listSize,
|
||||
uint16_t delaySize,
|
||||
TransferCallback callback,
|
||||
void * argument)
|
||||
{
|
||||
uint32_t error;
|
||||
|
||||
if (pAuds->bEndpointIn == 0)
|
||||
return USBRC_STATE_ERR;
|
||||
|
||||
error = USBD_HAL_SetupMblTransfer(pAuds->bEndpointIn,
|
||||
pListInit,
|
||||
listSize,
|
||||
delaySize);
|
||||
if (error) return error;
|
||||
|
||||
error = USBD_HAL_SetTransferCallback(pAuds->bEndpointIn,
|
||||
callback, argument);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add frame buffer to audio sending list.
|
||||
* \param pAuds Pointer to AUDDStream instance.
|
||||
* \param pBuffer Pointer to data frame to send.
|
||||
* \param wLength Frame size in bytes.
|
||||
* \return USBD_STATUS_SUCCESS if the transfer is started successfully;
|
||||
* otherwise an error code.
|
||||
*/
|
||||
uint32_t AUDDStream_Write(AUDDStream *pAuds, void* pBuffer, uint16_t wLength)
|
||||
{
|
||||
if (pAuds->bEndpointIn == 0)
|
||||
return USBRC_STATE_ERR;
|
||||
|
||||
return USBD_HAL_Write(pAuds->bEndpointIn,
|
||||
pBuffer, wLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the stream. All pending transfers are canceled.
|
||||
* \param pStream Pointer to AUDDStream instance.
|
||||
*/
|
||||
uint32_t AUDDStream_Close(AUDDStream *pStream)
|
||||
{
|
||||
uint32_t bmEPs = 0;
|
||||
|
||||
/* Close output stream */
|
||||
if (pStream->bEndpointIn) {
|
||||
bmEPs |= 1 << pStream->bEndpointIn;
|
||||
}
|
||||
/* Close input stream */
|
||||
if (pStream->bEndpointOut) {
|
||||
bmEPs |= 1 << pStream->bEndpointOut;
|
||||
}
|
||||
USBD_HAL_ResetEPs(bmEPs, USBRC_CANCELED, 1);
|
||||
|
||||
return USBRC_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Audio Speakerphone functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialize AUDDStream instance.
|
||||
* Note the number of channels excludes the master control, so
|
||||
* actual volume array size should be (1 + numChannels).
|
||||
* \param pAuds Pointer to AUDDStream instance.
|
||||
* \param numChannels Number of channels in the stream (excluding master,<31).
|
||||
* \param wChannelVolumes Data array for channel volume values,
|
||||
* must include master (1 + numChannels).
|
||||
* \param fCallback Callback function for stream control events.
|
||||
* \param pArg Pointer to event handler arguments.
|
||||
*/
|
||||
void AUDDSpeakerPhone_InitializeStream(
|
||||
AUDDStream *pAuds,
|
||||
uint8_t numChannels,
|
||||
uint16_t wChannelVolumes[],
|
||||
AUDDStreamEventCallback fCallback,
|
||||
void* pArg)
|
||||
{
|
||||
pAuds->bAcInterface = 0xFF;
|
||||
pAuds->bFeatureUnitOut = 0xFF;
|
||||
pAuds->bFeatureUnitIn = 0xFF;
|
||||
pAuds->bAsInterface = 0xFF;
|
||||
pAuds->bEndpointOut = 0;
|
||||
pAuds->bEndpointIn = 0;
|
||||
|
||||
pAuds->bNumChannels = numChannels;
|
||||
pAuds->bmMute = 0;
|
||||
pAuds->pwVolumes = wChannelVolumes;
|
||||
|
||||
pAuds->fCallback = fCallback;
|
||||
pAuds->pArg = pArg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize AUDDSpeakerPhone instance.
|
||||
* \param pAudf Pointer to AUDDSpeakerPhone instance.
|
||||
* \param pUsbd Pointer to USBDDriver instance.
|
||||
* \param pSpeaker Pointer to speaker streaming interface.
|
||||
* \param pMicrophone Pointer to microphone streaming interface.
|
||||
*/
|
||||
void AUDDSpeakerPhone_Initialize(
|
||||
AUDDSpeakerPhone *pAudf,
|
||||
USBDDriver *pUsbd,
|
||||
AUDDStream *pSpeaker,
|
||||
AUDDStream *pMicrophone)
|
||||
{
|
||||
pAudf->pUsbd = pUsbd;
|
||||
pAudf->pSpeaker = pSpeaker;
|
||||
pAudf->pMicrophone = pMicrophone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse USB Audio streaming information for AUDDStream instance.
|
||||
* \param pAudf Pointer to AUDDSpeakerPhone instance.
|
||||
* \param pDescriptors Pointer to descriptor list.
|
||||
* \param dwLength Descriptor list size in bytes.
|
||||
*/
|
||||
USBGenericDescriptor *AUDDSpeakerPhone_ParseInterfaces(
|
||||
AUDDSpeakerPhone *pAudf,
|
||||
USBGenericDescriptor *pDescriptors,
|
||||
uint32_t dwLength)
|
||||
{
|
||||
AUDDParseData data;
|
||||
|
||||
data.pAudf = pAudf;
|
||||
data.pIfDesc = 0;
|
||||
|
||||
return USBGenericDescriptor_Parse(pDescriptors,
|
||||
dwLength,
|
||||
(USBDescriptorParseFunction)AUDDSpeakerPhone_Parse,
|
||||
(void*)&data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the stream. All pending transfers are canceled.
|
||||
* \param pAudf Pointer to AUDDSpeakerPhone instance.
|
||||
* \param bInterface Stream interface number
|
||||
*/
|
||||
uint32_t AUDDSpeakerPhone_CloseStream(
|
||||
AUDDSpeakerPhone *pAudf,
|
||||
uint32_t bInterface)
|
||||
{
|
||||
if (pAudf->pSpeaker->bAsInterface == bInterface) {
|
||||
USBD_HAL_ResetEPs(1 << pAudf->pSpeaker->bEndpointOut,
|
||||
USBRC_CANCELED,
|
||||
1);
|
||||
}
|
||||
else if (pAudf->pMicrophone->bAsInterface == bInterface) {
|
||||
USBD_HAL_ResetEPs(1 << pAudf->pMicrophone->bEndpointIn,
|
||||
USBRC_CANCELED,
|
||||
1);
|
||||
}
|
||||
|
||||
return USBRC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles audio-specific USB requests sent by the host
|
||||
* \param pAudf Pointer to AUDDSpeakerPhone instance.
|
||||
* \param pRequest Pointer to a USBGenericRequest instance.
|
||||
* \return USBRC_PARAM_ERR if not handled.
|
||||
*/
|
||||
uint32_t AUDDSpeakerPhone_RequestHandler(
|
||||
AUDDSpeakerPhone *pAudf,
|
||||
const USBGenericRequest* pRequest)
|
||||
{
|
||||
//USBDDriver *pUsbd = pAudf->pUsbd;
|
||||
|
||||
if (USBGenericRequest_GetType(pRequest) != USBGenericRequest_CLASS)
|
||||
return USBRC_PARAM_ERR;
|
||||
|
||||
TRACE_INFO_WP("Aud ");
|
||||
switch (USBGenericRequest_GetRequest(pRequest)) {
|
||||
case AUDGenericRequest_SETCUR:
|
||||
AUDD_SetCUR(pAudf, pRequest);
|
||||
break;
|
||||
case AUDGenericRequest_GETCUR:
|
||||
AUDD_GetCUR(pAudf, pRequest);
|
||||
break;
|
||||
|
||||
default:
|
||||
return USBRC_PARAM_ERR;
|
||||
}
|
||||
|
||||
return USBRC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives data from the host through the audio function (as speaker).
|
||||
* This function behaves like USBD_Read.
|
||||
* \param pAudf Pointer to AUDDSpeakerPhone instance.
|
||||
* \param pData Pointer to the data buffer to put received data.
|
||||
* \param dwSize Size of the data buffer in bytes.
|
||||
* \param fCallback Optional callback function to invoke when the transfer
|
||||
* finishes.
|
||||
* \param pArg Optional argument to the callback function.
|
||||
* \return USBD_STATUS_SUCCESS if the read operation has been started normally;
|
||||
* otherwise, the corresponding error code.
|
||||
*/
|
||||
uint32_t AUDDSpeakerPhone_Read(
|
||||
AUDDSpeakerPhone *pAudf,
|
||||
void * pData,uint32_t dwSize,
|
||||
TransferCallback fCallback,void * pArg)
|
||||
{
|
||||
if (pAudf->pSpeaker == 0)
|
||||
return USBRC_PARAM_ERR;
|
||||
if (pAudf->pSpeaker->bEndpointOut == 0)
|
||||
return USBRC_PARAM_ERR;
|
||||
return USBD_Read(pAudf->pSpeaker->bEndpointOut,
|
||||
pData, dwSize,
|
||||
fCallback, pArg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Frame List for sending audio data.
|
||||
* \param pAudf Pointer to AUDDSpeakerPhone instance.
|
||||
* \param pListInit Pointer to the allocated list for audio write.
|
||||
* \param pDmaInit Pointer to the allocated DMA descriptors for autio write
|
||||
* (if DMA supported).
|
||||
* \param listSize Circular list size.
|
||||
* \param delaySize Start transfer after delaySize frames filled in.
|
||||
* \param callback Optional callback function for transfer.
|
||||
* \param argument Optional callback argument.
|
||||
* \return USBD_STATUS_SUCCESS if setup successfully; otherwise an error code.
|
||||
*/
|
||||
uint32_t AUDDSpeakerPhone_SetupWrite(
|
||||
AUDDSpeakerPhone *pAudf,
|
||||
void * pListInit,
|
||||
void * pDmaInit,
|
||||
uint16_t listSize,
|
||||
uint16_t delaySize,
|
||||
TransferCallback callback,
|
||||
void * argument)
|
||||
{
|
||||
uint32_t error;
|
||||
|
||||
if (pAudf->pMicrophone == 0)
|
||||
return USBRC_PARAM_ERR;
|
||||
if (pAudf->pMicrophone->bEndpointIn == 0)
|
||||
return USBRC_STATE_ERR;
|
||||
|
||||
error = USBD_HAL_SetupMblTransfer(pAudf->pMicrophone->bEndpointIn,
|
||||
pListInit,
|
||||
listSize,
|
||||
delaySize);
|
||||
if (error) return error;
|
||||
|
||||
error = USBD_HAL_SetTransferCallback(
|
||||
pAudf->pMicrophone->bEndpointIn,
|
||||
callback, argument);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add frame buffer to audio sending list.
|
||||
* \param pAudf Pointer to AUDDSpeakerPhone instance.
|
||||
* \param pBuffer Pointer to data frame to send.
|
||||
* \param wLength Frame size in bytes.
|
||||
* \return USBD_STATUS_SUCCESS if the transfer is started successfully;
|
||||
* otherwise an error code.
|
||||
*/
|
||||
uint32_t AUDDSpeakerPhone_Write(AUDDSpeakerPhone *pAudf, void* pBuffer, uint16_t wLength)
|
||||
{
|
||||
if (pAudf->pSpeaker == 0)
|
||||
return USBRC_PARAM_ERR;
|
||||
if (pAudf->pSpeaker->bEndpointIn == 0)
|
||||
return USBRC_STATE_ERR;
|
||||
|
||||
return USBD_HAL_Write(pAudf->pSpeaker->bEndpointIn,
|
||||
pBuffer, wLength);
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
Reference in New Issue
Block a user