simtrace2/sam3s_example/atmel_softpack_libraries/usb/device/audio-speaker/AUDDSpeakerDriver.c

235 lines
8.1 KiB
C

/* ----------------------------------------------------------------------------
* 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_speaker
*@{
*/
/*------------------------------------------------------------------------------
* Headers
*------------------------------------------------------------------------------*/
#include <AUDDSpeakerDriver.h>
#include <AUDDSpeakerPhone.h>
#include <USBLib_Trace.h>
#include <AUDRequests.h>
#include <USBD.h>
#include <USBD_HAL.h>
#include <USBDDriver.h>
/*----------------------------------------------------------------------------
* Internal types
*----------------------------------------------------------------------------*/
/**
* \brief Audio speaker driver struct.
*/
typedef struct _AUDDSpeakerDriver {
/** Speaker & Phone function */
AUDDSpeakerPhone fun;
/** Stream instance for speaker */
AUDDStream speaker;
/** Array for storing the current setting of each interface */
uint8_t bAltInterfaces[AUDDSpeakerDriver_NUMINTERFACES];
} AUDDSpeakerDriver;
/*----------------------------------------------------------------------------
* Internal variables
*----------------------------------------------------------------------------*/
/** Global USB audio speaker driver instance. */
static AUDDSpeakerDriver auddSpeakerDriver;
/*----------------------------------------------------------------------------
* Dummy callbacks
*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
* Internal functions
*----------------------------------------------------------------------------*/
/**
* Callback triggerred after the mute or volume status of the channel has been
* changed.
* \param ec Event code.
* \param channel Channel number.
* \param pArg Pointer to AUDDStream instance.
*/
static void AUDDSpeaker_EventCallback(uint32_t ec,
uint8_t channel,
AUDDStream *pArg)
{
if (ec == AUDD_EC_MuteChanged) {
if (AUDDSpeakerDriver_MuteChanged)
AUDDSpeakerDriver_MuteChanged(channel, pArg->bmMute);
}
else if (ec == AUDD_EC_VolumeChanged) {
/* Not supported now */
}
}
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* Initializes an USB audio speaker device driver, as well as the underlying
* USB controller.
*/
void AUDDSpeakerDriver_Initialize(const USBDDriverDescriptors *pDescriptors)
{
AUDDSpeakerDriver *pAudd = &auddSpeakerDriver;
AUDDSpeakerPhone *pAudf = &pAudd->fun;
AUDDStream *pAuds = &pAudd->speaker;
USBDDriver *pUsbd = USBD_GetDriver();
AUDDSpeakerPhone_InitializeStream(
pAuds, AUDDSpeakerDriver_NUMCHANNELS, 0,
(AUDDStreamEventCallback)AUDDSpeaker_EventCallback, pAuds);
AUDDSpeakerPhone_Initialize(
pAudf, pUsbd, pAuds, 0);
/* Initialize the USB driver */
USBDDriver_Initialize(pUsbd,
pDescriptors,
pAudd->bAltInterfaces);
USBD_Init();
}
/**
* Invoked whenever the active configuration of device is changed by the
* host.
* \param cfgnum Configuration number.
*/
void AUDDSpeakerDriver_ConfigurationChangeHandler(uint8_t cfgnum)
{
AUDDSpeakerDriver *pAudd = &auddSpeakerDriver;
AUDDSpeakerPhone *pAudf = &pAudd->fun;
const USBDDriverDescriptors *pDescriptors = pAudf->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];
AUDDSpeakerPhone_ParseInterfaces(pAudf,
(USBGenericDescriptor*)pDesc,
pDesc->wTotalLength);
}
}
/**
* 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 AUDDSpeakerDriver_InterfaceSettingChangedHandler(uint8_t interface,
uint8_t setting)
{
AUDDSpeakerDriver *pSpeakerd = &auddSpeakerDriver;
AUDDSpeakerPhone *pAudf = &pSpeakerd->fun;
if (setting == 0) {
AUDDSpeakerPhone_CloseStream(pAudf, interface);
}
if (AUDDSpeakerDriver_StreamSettingChanged)
AUDDSpeakerDriver_StreamSettingChanged(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 AUDDSpeakerDriver_RequestHandler(const USBGenericRequest *request)
{
AUDDSpeakerDriver *pAudd = &auddSpeakerDriver;
AUDDSpeakerPhone *pAudf = &pAudd->fun;
USBDDriver *pUsbd = pAudf->pUsbd;
TRACE_INFO_WP("NewReq ");
/* Handle Audio Class requests */
if (AUDDSpeakerPhone_RequestHandler(pAudf, request) == USBRC_SUCCESS) {
return;
}
/* Handle STD requests */
if (USBGenericRequest_GetType(request) == USBGenericRequest_STANDARD) {
USBDDriver_RequestHandler(pUsbd, request);
}
/* Unsupported request */
else {
TRACE_WARNING(
"AUDDSpeakerDriver_RequestHandler: Unsupported request (%d,%x)\n\r",
USBGenericRequest_GetType(request),
USBGenericRequest_GetRequest(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 AUDDSpeakerDriver_Read(void *buffer,
uint32_t length,
TransferCallback callback,
void *argument)
{
AUDDSpeakerDriver *pAudd = &auddSpeakerDriver;
AUDDSpeakerPhone *pAudf = &pAudd->fun;
return USBD_Read(pAudf->pSpeaker->bEndpointOut,
buffer, length,
callback, argument);
}
/**@}*/