mirror of
https://gitea.osmocom.org/sim-card/simtrace2.git
synced 2026-03-20 07:18:33 +03:00
Renamed main folder to firmware
This commit is contained in:
@@ -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