⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audioclass.c

📁 基于ADSP-BF535 USB驱动应用程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/*----------------------------------------------------------------------------------
*
* COPYRIGHT (c) 2001 by Singing Electrons, Inc. All rights reserved.
*
* Module Name			: C:\se\adi\hidclass\Source\HidClass.c
*
* Description			: The HID Class implementation - contains routines that implment the HID Class device
*
*
* Revision History	: At bottom of the file.
*
*---------------------------------------------------------------------------------*/

/** include files **/
#include <sys/exception.h>
#include <sys/excause.h>
//#include <def21535.h>
#include <defBF535.h>
#include "dtype.h"
#include "usb.h"
#include "usbdriver.h"
#include "audioclass.h"
#include "ac97.h"
#include "dprintf.h"

/** local definitions **/
#define PROVIDE_FEEDBACK 1


/* default settings */
#define CONTROL_PIPE_MAX_TRANSFER_LENGTH 32

#define INTERFACE_FOR_AUDIOCONTROL 0
#define ALTSETTING_FOR_AUDIOCONTROL 0

#define INTERFACE_FOR_AUDIOSTREAMING 1
#define ALTSETTING_FOR_AUDIOSTREAMING_IDLE 0
#define ALTSETTING_FOR_AUDIOSTREAMING_48K 1


#define PLAYBACK_EP 0x01
#define PLAYBACK_FEEDBACK_EP 0x82

#define TERMID_USBOUT 0x01
#define UNITID_OUTVOLUME 0x02
#define TERMID_LINEOUT 0x03

#define PLAYBACK_DELAY 3 //milliseconds

//ToDo: These need to be changed based on the codec used
#define OUTVOLUME_MIN 0xa180 //-94.5dB
#define OUTVOLUME_MAX 0x0000 //0 dB
#define OUTVOLUME_RES 0x0180 //1.5 dB


#define NUM_CHANNELS 2
#define CHANNELCONFIG 0x0003 //left and right
#define SAMPLINGRATE 48000

//To create a 24bit audio device change
//the following two values to 24, and also
//change the code that takes data from the buffer 
#define BIT_DEPTH 16
#define CONTAINER_SIZE 16

#if PROVIDE_FEEDBACK
#define FEEDBACK_RANGE 1000 //samples per second
#else
#define FEEDBACK_RANGE 0 //samples per second
#endif

#define MAX_PACKET_SIZE (((SAMPLINGRATE + FEEDBACK_RANGE)  * NUM_CHANNELS * (CONTAINER_SIZE / 8)) / 1000)
#define FEEDBACK_PACKET_SIZE 3

//#define NUM_PACKETS_TO_BUFFER 7
//#define MAX_DATA_BUFFER_SIZE (MAX_PACKET_SIZE * NUM_PACKETS_TO_BUFFER)

//0000110000.0000000000  = 48.0 (48 + 0/1024) (bcd 10.10 format)
//000011000000000000000000  = 48.0 (48 + 0/1024) = 0c0000
#define FEEDBACK_FREQUENCY_NORMAL 0x0c0000

//0000110000.1000000000 = 48.5 (48 + 512/1024)
//000011000010000000000000  = 48.5 (48 + 512/1024) = 0c2000
//#define FEEDBACK_FREQUENCY_PLEASE_HURRY 0x0c2000
#define FEEDBACK_FREQUENCY_PLEASE_HURRY 0x0c4000 //49K


//0000101111.1000000000  = 47.5 (47 + 512/1024)
//000010111110000000000000  = 47.5 (47 + 512/1024) = 0be000
//#define FEEDBACK_FREQUENCY_PLEASE_SLOWDOWN 0x0be000
#define FEEDBACK_FREQUENCY_PLEASE_SLOWDOWN 0x0bc000 //47K


#include "descriptors.h"



/** external functions **/

/** external data **/

/** internal functions **/

/** public data **/
bool gIsPlaybackActive;


/** private data **/
static PSUSPENDPROC gpOnSuspend;
static PRESUMEPROC gpOnResume;
static PRESETPROC gpOnReset;

static UCHAR gOutMute;
static USHORT gOutLeftVol;
static USHORT gOutRightVol;

static UINT gFeedbackData;
static USHORT gEnablePlaybackCountdown;
static UINT gRegChangesRequested, gRegChangesImplemented;

static UINT gTimeoutCount;

//static UINT gDataBufferHead;
//static UINT gDataBufferTail;
//static UCHAR gDataBuffer[MAX_DATA_BUFFER_SIZE];

static UINT gDebugNumTransfers;
static UINT gDebugTotalTransferLength;

/** public functions **/

/** private functions **/
bool AudioGetRequest (UCHAR bRequest, UCHAR wIndexHi, USHORT wValue, USHORT wLength, PUINT pNumBytesToTransfer, UCHAR *buffer);
bool AudioSetRequest (UCHAR bRequest, UCHAR wIndexHi, USHORT wValue, USHORT wLength, UCHAR *buffer);

/** callback functions **/
static bool OnSetupRequest (UCHAR endpointNumber, PUSB_SETUP_DATA pSetupData, void *buffer, 
	PUINT pNumBytesToTransfer);
static bool OnGetDeviceDescriptor (void *buffer, PUINT pNumBytesToTransfer);
static bool OnGetConfigDescriptor (void *buffer, PUINT pNumBytesToTransfer);
static bool OnGetStringDescriptor (UCHAR stringIndex, USHORT langID, void *buffer, PUINT pNumBytesToTransfer);
static void OnInTransferComplete (UCHAR endpointNumber);
static bool OnOutTransferComplete (UCHAR endpointNumber, void *buffer, UINT numBytesReceived, bool wasPCAsserted);
static void OnNAKSent (UCHAR endpointNumber);
static bool OnConfigRequest (UCHAR newConfiguration, UCHAR newInterface, UCHAR newAltSetting);
static void OnSuspend (void);
static void OnResume (void);
static void OnReset (void);
static void OnSOF (void);




/*------------------------------------------------------------
*	HIDCLASS_Init
*
*	Parameters:  
*
*	Globals Used:
*		gpOnResume, gpOnReset, gUseINEP, gpTheReportDescriptor, gTheReportDescriptorSize
*		gTheDeviceDescriptor, gTheConfigDescriptor
*
*	Description:
*		This is the main initialization routine. The client provides the vendor id, device id,
*		revision, and a bunch of pointers to routines to be calleld under various conditions.
*
*	Returns:
*		true on success, false on failure.
*
*------------------------------------------------------------*/
bool AUDIOCLASS_Init (uint16 vid, uint16 pid, uint16 rel, PSUSPENDPROC pOnSuspendProc, 
	PRESUMEPROC pOnResumeProc, PRESETPROC pOnResetProc)
	{
		if (!AC97_Init())
			return false;
			
		//Initialize the state variables
		gOutMute = 0;
		gOutLeftVol = OUTVOLUME_MAX;
		gOutRightVol = OUTVOLUME_MAX;
		gIsPlaybackActive = false;
		gEnablePlaybackCountdown = 0;
		//gDataBufferHead = gDataBufferTail = 0;
		//memset (&gDataBuffer, 0, sizeof (gDataBuffer));

		gDebugNumTransfers = 0;
		gDebugTotalTransferLength = 0;

		gFeedbackData = FEEDBACK_FREQUENCY_NORMAL;

		//Save the callback addresses
		gpOnSuspend = pOnSuspendProc;
		gpOnResume = pOnResumeProc;
		gpOnReset = pOnResetProc;

		gRegChangesRequested = gRegChangesImplemented = 0;


		//Update the VID and PID
		memcpy (&gTheDeviceDescriptor[OFFSET_VENDOR_ID], &vid, sizeof (uint16));
		memcpy (&gTheDeviceDescriptor[OFFSET_PRODUCT_ID], &pid, sizeof (uint16));
		memcpy (&gTheDeviceDescriptor[OFFSET_RELEASE], &rel, sizeof (uint16));


		//Things to do before setting up endpoints
		if (!USBDriver_PreInit ())
			return false;

		USBDriver_SetupEndpoint (EP1, ALTSETTING_FOR_AUDIOSTREAMING_IDLE, 
			INTERFACE_FOR_AUDIOSTREAMING, EP_CONFIG1, EP_OUT,
			EP_ISO, 0);

		USBDriver_SetupEndpoint (EP1, ALTSETTING_FOR_AUDIOSTREAMING_48K, 
			INTERFACE_FOR_AUDIOSTREAMING, EP_CONFIG1, EP_OUT,
			EP_ISO, MAX_PACKET_SIZE);

#if PROVIDE_FEEDBACK		
		USBDriver_SetupEndpoint (EP2, ALTSETTING_FOR_AUDIOSTREAMING_48K, 
			INTERFACE_FOR_AUDIOSTREAMING, EP_CONFIG1, EP_IN,
			EP_ISO, FEEDBACK_PACKET_SIZE);
#endif //PROVIDE_FEEDBACK		

		return USBDriver_CompleteInit (OnSetupRequest, OnGetDeviceDescriptor, 
			OnGetConfigDescriptor, OnGetStringDescriptor, 
			OnInTransferComplete, OnOutTransferComplete, OnNAKSent, 
			OnSuspend, OnResume, OnReset, OnConfigRequest, OnSOF, CONTROL_PIPE_MAX_TRANSFER_LENGTH);

	}



/*------------------------------------------------------------
*	AUDIOCLASS_DoForegroundTasks
*
*	Parameters:  None
*
*	Globals Used:
*		gRegChangesImplemented, gRegChangesRequested
*
*	Description:
*		This routine essentially does the time consuming task
*		of talking to the AC97 codec when requested for volume
*		and mute controls. This way the ISR does not have to
*		waste a lot of time.
*
*	Returns:
*		Nothing
*
*------------------------------------------------------------*/
void AUDIOCLASS_DoForegroundTasks (void)
	{
		if (gRegChangesRequested != gRegChangesImplemented)
			{
				AC97_SetVolumeAndMute (gOutLeftVol, gOutRightVol, gOutMute);
				gRegChangesImplemented++;
			}
	}



/*------------------------------------------------------------
*	OnSetupRequest
*
*	Parameters:  
*		endpointNumber - the endpoint on which this request was received
*		pSetupData - points to a structure cantaining the SETUP DATA(0)
*		buffer - points to a buffer where the setup data is available, or should be placed.
*		pNumBytesToTransfer - points to a location where the number of bytes
*			to be sent back should be stored.
*	Globals Used:
*		None
*
*	Description:
*		This routine is called by the USB driver to handle a special setup request, 
*		that is not a GET DEVICE, GET CONFIG, or GET STRING descriptor
*		
*		Based on the request type, this routine reads/writes to the buffer
*		provided.
*
*	Returns:
*		true to succeed the request, false to stall the request
*
*------------------------------------------------------------*/
bool OnSetupRequest (UCHAR endpointNumber, PUSB_SETUP_DATA pSetupData, void *buffer, 
	PUINT pNumBytesToTransfer)
	{
		bool retVal = false; //stall
		bool validRequest = false;

		//Need to handle the requests used to change the various controls
		if (endpointNumber == EP0)
			{
				if ((USB_CONTROL_REQUEST_GET_TYPE (pSetupData->bmRequestType) == USB_CONTROL_REQUEST_TYPE_CLASS) &&
					(USB_CONTROL_REQUEST_GET_RECIPIENT (pSetupData->bmRequestType) == USB_CONTROL_REQUEST_TYPE_INTERFACE) &&
					(LOBYTE (pSetupData->wIndex) == INTERFACE_FOR_AUDIOCONTROL))
					{
						validRequest = true;
						if (USB_CONTROL_REQUEST_GET_DIRECTION(pSetupData->bmRequestType) == USB_CONTROL_REQUEST_TYPE_OUT)
							retVal = AudioSetRequest (pSetupData->bRequest, HIBYTE(pSetupData->wIndex), pSetupData->wValue, pSetupData->wLength, buffer);
						else
							retVal = AudioGetRequest (pSetupData->bRequest, HIBYTE(pSetupData->wIndex), pSetupData->wValue, pSetupData->wLength, pNumBytesToTransfer, buffer);
					}
			}

		
		if (!validRequest)
			{
				Dprintf1 ("Unknown setup request: %02x", pSetupData->bmRequestType);
				Dprintf3 ("Dir = %02x, Type = %02x, Rec = %02x", USB_CONTROL_REQUEST_GET_DIRECTION (pSetupData->bmRequestType),
					USB_CONTROL_REQUEST_GET_TYPE (pSetupData->bmRequestType),
					USB_CONTROL_REQUEST_GET_RECIPIENT (pSetupData->bmRequestType));
				Dprintf1 ("bRequest = %02x", pSetupData->bRequest);
			}
			

		return (retVal);
	}


/*------------------------------------------------------------
*	AudioGetRequest
*
*	Parameters:  
*		bRequest - the request.
*		wIndexHi - the high byte of wIndex
*		wValue - as it comes in the setup packet
*		wLength - as it comes in the setup packet.
*		pNumBytesToTransfer - pointer to a location which receives the number of bytes to be transferred.
*		buffer - pointer to a buffer where the result data is to be stored.
*
*	Globals Used:
*		gOutMute, gOutLeftVol, gOutRightVol
*
*	Description:
*		This handles the Audio Class Get Requests
*
*	Returns:
*		true on success, false on failure (to stall the EP).
*
*------------------------------------------------------------*/
bool AudioGetRequest (UCHAR bRequest, UCHAR wIndexHi, USHORT wValue, USHORT wLength, PUINT pNumBytesToTransfer, UCHAR *buffer)
	{
		bool retVal = false;

		switch (bRequest)
			{
				case GET_CUR:
					switch (wIndexHi)
						{
							case UNITID_OUTVOLUME:
								switch (HIBYTE(wValue))
									{
										case USB_AUDIO_CONTROL_SELECTOR_MUTE_CONTROL:
											if (LOBYTE(wValue) == 0)
												{
													buffer[0] = gOutMute;
													*pNumBytesToTransfer = sizeof (UCHAR);
													retVal = true;
												}
											break;
										case USB_AUDIO_CONTROL_SELECTOR_VOLUME_CONTROL:
											switch (LOBYTE(wValue))
												{
													case 0:
														buffer[0] = LOBYTE ((gOutLeftVol + gOutRightVol) >> 1);
														buffer[1] = HIBYTE ((gOutLeftVol + gOutRightVol) >> 1);
														*pNumBytesToTransfer = sizeof (USHORT);
														retVal = true;
														break;
													case 1:
														buffer[0] = LOBYTE (gOutLeftVol);
														buffer[1] = HIBYTE (gOutLeftVol);
														*pNumBytesToTransfer = sizeof (USHORT);
														retVal = true;
														break;
													case 2:
														buffer[0] = LOBYTE (gOutRightVol);
														buffer[1] = HIBYTE (gOutRightVol);
														*pNumBytesToTransfer = sizeof (USHORT);
														retVal = true;
														break;
													case 0xff:
														buffer[0] = LOBYTE ((gOutLeftVol + gOutRightVol) >> 1);
														buffer[1] = HIBYTE ((gOutLeftVol + gOutRightVol) >> 1);
														buffer[2] = LOBYTE (gOutLeftVol);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -