MCUXpresso_MIMXRT1052xxxxB/boards/evkbimxrt1050/usb_examples/usb_host_audio_recorder/freertos/audio_recorder.c
Yilin Sun 6baf4427ce
Updated to v2.15.000
Signed-off-by: Yilin Sun <imi415@imi.moe>
2024-03-18 23:15:10 +08:00

1344 lines
59 KiB
C

/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016, 2018-2020 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "usb_host_config.h"
#include "usb_host.h"
#include "audio_recorder.h"
#include "usb_host_audio.h"
#include "fsl_debug_console.h"
#include "fsl_sd.h"
#include "ff.h"
#include "diskio.h"
#include "fsl_sd_disk.h"
#include "app.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
static uint32_t USB_HostAudioRecorderBufferSpaceUsed(void);
static void USB_HostAudioRecorderWriteSdcard();
static void USB_HostAudioRecorderWaitCommand();
/*******************************************************************************
* Variables
******************************************************************************/
/* should set it as 1024U, set as 256U for saving memory */
#define MAX_ISO_PACKET_SIZE (256U)
#define USB_AUDIO_RECORDER_STREAM_PRIME_COUNT (5U)
#ifndef USB_AUDIO_RECORDER_SDCARD_BUFFER_LENGTH
#define USB_AUDIO_RECORDER_SDCARD_BUFFER_LENGTH (1024U * 3U)
#endif
#ifndef USB_AUDIO_RECORDER_SDCARD_WRITE_LENGTH
#define USB_AUDIO_RECORDER_SDCARD_WRITE_LENGTH (1024U)
#endif
#define NUMBER_OF_COMMAND_RETRY 0x3U
/* USB audio transfer Types string*/
static char *strTransferType[4] = {"Control", "Isochronous", "Bulk", "Interrupt"};
/* USB audio Sync Types string*/
static char *strSyncType[4] = {"No synchronization", "Asynchronous", "Adaptive", "Synchronous"};
/* USB audio Data Types string*/
static char *strDataType[4] = {"Data endpoint", "Feedback endpoint", "Implicit feedback", "Reserved"};
usb_device_handle g_audioRecorderDeviceHandle;
usb_host_interface_handle g_audioRecorderOutControlifHandle;
usb_host_interface_handle g_audioRecorderOutStreamifHandle;
audio_recorder_instance_t g_audioRecorder;
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)
static uint8_t s_audioRecordStreamBuffer[USB_AUDIO_RECORDER_STREAM_PRIME_COUNT][MAX_ISO_PACKET_SIZE];
uint8_t g_audioDataSdcardBuffer[USB_AUDIO_RECORDER_SDCARD_BUFFER_LENGTH];
extern const unsigned char wav_data[];
extern const uint32_t wav_size;
uint8_t g_hostCurVolume = 4U;
uint16_t g_deviceVolumeStep;
usb_audio_stream_format_type_desc_t *g_pFormatTypeDesc = NULL;
usb_audio_2_0_stream_format_type_desc_t *g_pFormatTypeDesc_20 = NULL;
usb_audio_2_0_stream_spepific_as_intf_desc_t *g_generalDesc_20 = NULL;
usb_audio_stream_spepific_as_intf_desc_t *g_pAsItfDesc = NULL;
usb_descriptor_endpoint_t *g_pIsoEndpDesc = NULL;
static uint16_t g_curVolume;
static uint16_t g_minVolume;
static uint16_t g_maxVolume;
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) usb_audio_2_0_control_range_layout2_struct_t g_volumeRang;
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) usb_audio_2_0_control_range_layout3_struct_t g_frequencyRang;
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) uint8_t g_curVol[2];
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) uint8_t g_curMute[2];
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) static uint16_t minVol[2];
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) static uint16_t maxVol[2];
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) static uint16_t resVol[2];
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) uint32_t freq;
uint8_t *g_frequencyAllRang;
/* File system object */
static FATFS g_fileSystem;
const TCHAR g_DriverNumberBuffer[] = {SDDISK + '0', ':', '/', '\0'};
/*******************************************************************************
* Code
******************************************************************************/
/*!
* @brief usb host audio control transfer callback.
*
* This function is used as callback function for control transfer .
*
* @param param the host audio instance pointer.
* @param data data buffer pointer.
* @param dataLen data length.
* @param status transfer result status.
*/
void Audio_ControlCallback(void *param, uint8_t *data, uint32_t dataLen, usb_status_t status)
{
audio_recorder_instance_t *audio_ptr = (audio_recorder_instance_t *)param;
static uint32_t retryCount = 0;
if (status != kStatus_USB_Success)
{
retryCount++;
if (kUSB_HostAudioRunWaitAudioSetCurSamplingFreq == audio_ptr->runWaitState)
{
usb_echo("audio recorder doest not support SamplingFreq request!\r\n");
/* set idle, don't do retry */
audio_ptr->runState = kUSB_HostAudioRunIdle;
}
else if (audio_ptr->runWaitState == kUSB_HostAudioRunWaitSetStreamInterface)
{
audio_ptr->runState = kUSB_HostAudioRunSetControlInterfaceDone;
}
else if (audio_ptr->runWaitState == kUSB_HostAudioRunWaitAudioGetMinVolume)
{
if (kStatus_USB_TransferStall == status)
{
usb_echo("audio recorder doest not support GetMinVolume request!\r\n");
}
audio_ptr->runState = kUSB_HostAudioRunSetInterfaceDone;
}
else if (audio_ptr->runWaitState == kUSB_HostAudioRunWaitAudioGetMaxVolume)
{
if (kStatus_USB_TransferStall == status)
{
usb_echo("audio recorder doest not support GetMaxVolume request!\r\n");
}
audio_ptr->runState = kUSB_HostAudioRunAudioGetMaxVolume;
}
else if (audio_ptr->runWaitState == kUSB_HostAudioRunWaitAudioGetResVolume)
{
if (kStatus_USB_TransferStall == status)
{
usb_echo("audio recorder doest not support GetResVolume request!\r\n");
}
audio_ptr->runState = kUSB_HostAudioRunAudioGetResVolume;
}
else if (audio_ptr->runWaitState == kUSB_HostAudioRunWaitAudioGetVolumeRang)
{
if (kStatus_USB_TransferStall == status)
{
usb_echo("audio recorder doest not support GetVolumeRang request!\r\n");
}
audio_ptr->runState = kUSB_HostAudioRunSetInterfaceDone;
}
else if (audio_ptr->runWaitState == kUSB_HostAudioRunWaitAudioGetCurrentVolumeDone)
{
if (kStatus_USB_TransferStall == status)
{
usb_echo("audio recorder doest not support GetCurrentVolume request!\r\n");
}
audio_ptr->runState = kUSB_HostAudioRunAudioGetCurrentVolume;
}
else if (audio_ptr->runWaitState == kUSB_HostAudioRunWaitAudioGetSampleFrequencyRange)
{
if (kStatus_USB_TransferStall == status)
{
usb_echo("audio recorder doest not support GetSampleFrequencyRange request!\r\n");
}
audio_ptr->runState = kUSB_HostAudioRunAudioGetSampleFrequencyRange;
}
else /* other states, don't do retry */
{
audio_ptr->runState = kUSB_HostAudioRunIdle;
}
if (kUSB_HostAudioRunIdle != audio_ptr->runState)
{
if (retryCount < NUMBER_OF_COMMAND_RETRY)
{
return;
}
else
{
audio_ptr->runState = kUSB_HostAudioRunIdle;
}
}
}
if (audio_ptr->runState == kUSB_HostAudioRunIdle)
{
retryCount = 0;
if (audio_ptr->runWaitState == kUSB_HostAudioRunSetControlInterface)
{
audio_ptr->runState = kUSB_HostAudioRunSetControlInterfaceDone;
}
else if (audio_ptr->runWaitState == kUSB_HostAudioRunWaitSetStreamInterface)
{
audio_ptr->runState = kUSB_HostAudioRunSetInterfaceDone;
}
else if (audio_ptr->runWaitState == kUSB_HostAudioRunWaitAudioGetVolumeRang)
{
audio_ptr->runState = kUSB_HostAudioRunAudioGetCurrentVolume;
}
else if (audio_ptr->runWaitState == kUSB_HostAudioRunWaitAudioGetCurrentVolumeDone)
{
audio_ptr->runState = kUSB_HostAudioRunAudioGetSampleFrequencyRange;
}
else if (audio_ptr->runWaitState == kUSB_HostAudioRunWaitAudioGetSampleFrequencyRange)
{
/*device support discrete frequency list, will get all the frequency */
if (USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS((&g_frequencyRang.wNumSubRanges[0])) > 1U)
{
audio_ptr->runState = kUSB_HostAudioRunAudioGetAllSampleFrequencyRange;
}
else
{
audio_ptr->runState = kUSB_HostAudioRunAudioConfigChannel;
}
}
else if (audio_ptr->runWaitState == kUSB_HostAudioRunWaitAudioGetAllSampleFrequencyRange)
{
audio_ptr->runState = kUSB_HostAudioRunAudioConfigChannel;
}
else if (audio_ptr->runWaitState == kUSB_HostAudioRunWaitAudioGetMinVolume)
{
audio_ptr->runState = kUSB_HostAudioRunAudioGetMaxVolume;
}
else if (audio_ptr->runWaitState == kUSB_HostAudioRunWaitAudioGetMaxVolume)
{
audio_ptr->runState = kUSB_HostAudioRunAudioGetResVolume;
}
else if (audio_ptr->runWaitState == kUSB_HostAudioRunWaitAudioGetResVolume)
{
audio_ptr->runState = kUSB_HostAudioRunAudioConfigChannel;
}
else if (audio_ptr->runWaitState == kUSB_HostAudioRunWaitAudioConfigChannel)
{
audio_ptr->runState = kUSB_HostAudioRunAudioConfigChannel1Vol;
}
else if (audio_ptr->runWaitState == kUSB_HostAudioRunWaitAudioConfigChannel1Vol)
{
audio_ptr->runState = kUSB_HostAudioRunAudioConfigChannel2Vol;
}
else if (audio_ptr->runWaitState == kUSB_HostAudioRunWaitAudioSetCurSamplingFreq)
{
audio_ptr->runState = kUSB_HostAudioRunAudioDone;
}
else if (audio_ptr->runWaitState == kUSB_HostAudioRunWaitAudioConfigChannel2Vol)
{
if (g_audioRecorder.deviceIsUsed == 0)
{
audio_ptr->runState = kUSB_HostAudioRunAudioSetCurSamplingFreq;
}
else if (g_audioRecorder.deviceIsUsed == 1)
{
audio_ptr->runState = kUSB_HostAudioRunIdle;
}
else
{
}
}
else if (audio_ptr->runWaitState == kUSB_HostAudioRunWaitAudioConfigMute)
{
audio_ptr->runState = kUSB_HostAudioRunIdle;
}
else
{
}
}
}
/*!
* @brief host audio iso out transfer callback.
*
* This function is used as callback function when call usb_host_audio_send .
*
* @param param the host audio instance pointer.
* @param data data buffer pointer.
* @param dataLen data length.
* @param status transfer result status.
*/
void Audio_RecorderInCallback(void *param, uint8_t *data, uint32_t dataLen, usb_status_t transfer_status)
{
usb_status_t status = kStatus_USB_Error;
uint32_t buffer_length = 0U;
uint32_t partLength = 0U;
if (transfer_status == kStatus_USB_TransferCancel)
{
return;
}
if (0U != dataLen)
{
buffer_length = g_audioRecorder.audioRecorderStreamPutBufferIndex + dataLen;
if (buffer_length < USB_AUDIO_RECORDER_SDCARD_BUFFER_LENGTH)
{
memcpy(
(void *)((uint8_t *)&g_audioDataSdcardBuffer[g_audioRecorder.audioRecorderStreamPutBufferIndex]),
(void *)((uint8_t *)&s_audioRecordStreamBuffer[g_audioRecorder.audioRecorderStreamUsbBufferIndex][0]),
dataLen);
g_audioRecorder.audioRecorderStreamPutBufferIndex += dataLen;
}
else
{
partLength = USB_AUDIO_RECORDER_SDCARD_BUFFER_LENGTH - g_audioRecorder.audioRecorderStreamPutBufferIndex;
memcpy(
(void *)((uint8_t *)&g_audioDataSdcardBuffer[g_audioRecorder.audioRecorderStreamPutBufferIndex]),
(void *)((uint8_t *)&s_audioRecordStreamBuffer[g_audioRecorder.audioRecorderStreamUsbBufferIndex][0]),
partLength);
buffer_length = dataLen - partLength; /* the remain data length */
if (buffer_length > 0U)
{
memcpy((void *)((uint8_t *)&g_audioDataSdcardBuffer[0]),
(void *)(uint8_t *)&s_audioRecordStreamBuffer[g_audioRecorder.audioRecorderStreamUsbBufferIndex]
[partLength],
buffer_length);
}
g_audioRecorder.audioRecorderStreamPutBufferIndex = buffer_length;
}
}
if (1U == g_audioRecorder.audioRecorderRunFlag)
{
/* prime the next usb stream transfer */
status = USB_HostAudioStreamRecv(
g_audioRecorder.classHandle,
(unsigned char *)&s_audioRecordStreamBuffer[g_audioRecorder.audioRecorderStreamUsbBufferIndex][0],
g_audioRecorder.audioRecorderIsoMaxPacketSize, Audio_RecorderInCallback, &g_audioRecorder);
if (status != kStatus_USB_Success)
{
usb_echo("usb transfer error");
}
}
g_audioRecorder.audioRecorderStreamUsbBufferIndex++;
if (g_audioRecorder.audioRecorderStreamUsbBufferIndex == USB_AUDIO_RECORDER_STREAM_PRIME_COUNT)
{
g_audioRecorder.audioRecorderStreamUsbBufferIndex = 0;
}
}
/* The USB_AudioRecorderBufferSpaceUsed() function gets the used recorder ringbuffer used size */
static uint32_t USB_HostAudioRecorderBufferSpaceUsed(void)
{
if (g_audioRecorder.audioRecorderStreamPutBufferIndex >= g_audioRecorder.audioRecorderStreamGetBufferIndex)
{
g_audioRecorder.recorderUsedSpace =
g_audioRecorder.audioRecorderStreamPutBufferIndex - g_audioRecorder.audioRecorderStreamGetBufferIndex;
}
else
{
g_audioRecorder.recorderUsedSpace = g_audioRecorder.audioRecorderStreamPutBufferIndex +
USB_AUDIO_RECORDER_SDCARD_BUFFER_LENGTH -
g_audioRecorder.audioRecorderStreamGetBufferIndex;
}
return g_audioRecorder.recorderUsedSpace;
}
/*!
* @brief write picture into sd card.
*/
static void USB_HostAudioRecorderWriteSdcard()
{
static uint8_t s_FileOpened = 0;
static FIL fileObj;
char fileName[32];
FRESULT fileStatus;
uint32_t writeSize = 0U;
uint32_t used_size = 0U;
uint32_t actual_size = 0U;
uint32_t part_length = 0U;
if (g_audioRecorder.audioRecorderWriteSdcardFlag)
{
if (!s_FileOpened)
{
sprintf(fileName, "%saudio%d.pcm", &g_DriverNumberBuffer[0], g_audioRecorder.audioFileIndex);
fileStatus = f_open(&fileObj, _T(fileName), FA_WRITE | FA_CREATE_ALWAYS);
if (FR_OK != fileStatus)
{
usb_echo("sdcard operate fail\r\n");
return;
}
s_FileOpened = 1;
}
used_size = USB_HostAudioRecorderBufferSpaceUsed();
if (used_size < USB_AUDIO_RECORDER_SDCARD_WRITE_LENGTH)
{
if (1U == g_audioRecorder.audioRecorderRunFlag)
{
return;
}
else
{
actual_size = used_size;
}
}
else
{
actual_size = USB_AUDIO_RECORDER_SDCARD_WRITE_LENGTH;
}
if (0U != actual_size)
{
part_length = g_audioRecorder.audioRecorderStreamGetBufferIndex + actual_size;
fileStatus = FR_INVALID_PARAMETER;
if (part_length <= USB_AUDIO_RECORDER_SDCARD_BUFFER_LENGTH)
{
fileStatus = f_write(
&fileObj, (uint8_t *)&g_audioDataSdcardBuffer[g_audioRecorder.audioRecorderStreamGetBufferIndex],
actual_size, (UINT *)&writeSize);
}
if ((fileStatus != FR_OK) || (actual_size != writeSize))
{
usb_echo("sdcard operate fail\r\n");
g_audioRecorder.runState = kUSB_HostAudioRunAudioWaitCommand;
g_audioRecorder.audioRecorderWriteSdcardFlag = 0U;
return;
}
}
g_audioRecorder.audioRecorderStreamGetBufferIndex += actual_size;
if (g_audioRecorder.audioRecorderStreamGetBufferIndex >= USB_AUDIO_RECORDER_SDCARD_BUFFER_LENGTH)
{
g_audioRecorder.audioRecorderStreamGetBufferIndex =
g_audioRecorder.audioRecorderStreamGetBufferIndex - USB_AUDIO_RECORDER_SDCARD_BUFFER_LENGTH;
}
/* Stop recording and the buffer data has been saved in sdcard */
if ((actual_size < USB_AUDIO_RECORDER_SDCARD_WRITE_LENGTH) && (0U == g_audioRecorder.audioRecorderRunFlag))
{
s_FileOpened = 0;
fileStatus = f_sync(&fileObj);
f_close(&fileObj);
if (FR_OK != fileStatus)
{
usb_echo("file sync fail\r\n");
return;
}
usb_echo("Recording stops, AUDIO%d.PCM is saved\r\n", g_audioRecorder.audioFileIndex);
if (kStatus_DEV_Detached == g_audioRecorder.devState)
{
g_audioRecorder.devState = kStatus_DEV_Idle;
g_audioRecorder.runState = kUSB_HostAudioRunIdle;
g_audioRecorder.runWaitState = kUSB_HostAudioRunIdle;
USB_HostAudioDeinit(g_audioRecorder.deviceHandle, g_audioRecorder.classHandle);
g_audioRecorder.classHandle = NULL;
}
g_audioRecorder.audioFileIndex++;
g_audioRecorder.runState = kUSB_HostAudioRunAudioWaitCommand;
g_audioRecorder.audioRecorderWriteSdcardFlag = 0U;
}
}
}
/*!
* @brief check user command to start record.
*/
static void USB_HostAudioRecorderWaitCommand()
{
uint8_t command;
if (kStatus_USB_Success != DbgConsole_TryGetchar((char *)&command))
{
command = 0;
}
if ('r' == command)
{
g_audioRecorder.audioRecorderRunFlag = 1U;
}
else if ('s' == command)
{
g_audioRecorder.audioRecorderRunFlag = 0U;
}
else
{
/* TO DO */
}
}
/*!
* @brief host usb audio task function.
*
* This function implements the host audio action, it is used to create task.
*
* @param param the host audio instance pointer.
*/
void USB_AudioTask(void *arg)
{
uint32_t bsamfreqtype_g_index;
uint8_t pcm_format = 0U;
uint8_t *frequencyArray;
uint8_t *frequencyArrayStart;
/* device state changes */
if (g_audioRecorder.devState != g_audioRecorder.prevState)
{
g_audioRecorder.prevState = g_audioRecorder.devState;
switch (g_audioRecorder.devState)
{
case kStatus_DEV_Idle:
break;
case kStatus_DEV_Attached:
g_audioRecorder.runState = kUSB_HostAudioRunSetControlInterface;
g_audioRecorder.deviceIsUsed = 0;
g_hostCurVolume = 4;
USB_HostAudioInit(g_audioRecorder.deviceHandle, &g_audioRecorder.classHandle);
usb_echo("USB audio attached\r\n");
break;
case kStatus_DEV_Detached:
/* when recording, stop recording and de-initialize host when finishing writing sdcard */
if (1U == g_audioRecorder.audioRecorderRunFlag)
{
g_audioRecorder.audioRecorderRunFlag = 0U;
}
else
{
g_audioRecorder.devState = kStatus_DEV_Idle;
g_audioRecorder.runState = kUSB_HostAudioRunIdle;
USB_HostAudioDeinit(g_audioRecorder.deviceHandle, g_audioRecorder.classHandle);
g_audioRecorder.classHandle = NULL;
}
if (NULL != g_frequencyAllRang)
{
free(g_frequencyAllRang);
g_frequencyAllRang = NULL;
}
usb_echo("audio recorder detached\r\n");
break;
default:
break;
}
}
/* run state */
switch (g_audioRecorder.runState)
{
case kUSB_HostAudioRunIdle:
break;
case kUSB_HostAudioRunSetControlInterface:
g_audioRecorder.runWaitState = kUSB_HostAudioRunSetControlInterface;
g_audioRecorder.runState = kUSB_HostAudioRunIdle;
if (USB_HostAudioControlSetInterface(g_audioRecorder.classHandle, g_audioRecorder.controlIntfHandle, 0,
Audio_ControlCallback, &g_audioRecorder) != kStatus_USB_Success)
{
usb_echo("set interface error\r\n");
}
break;
case kUSB_HostAudioRunSetControlInterfaceDone:
g_audioRecorder.runWaitState = kUSB_HostAudioRunWaitSetStreamInterface;
g_audioRecorder.runState = kUSB_HostAudioRunIdle;
if (USB_HostAudioStreamSetInterface(g_audioRecorder.classHandle, g_audioRecorder.streamIntfHandle, 1,
Audio_ControlCallback, &g_audioRecorder) != kStatus_USB_Success)
{
usb_echo("set interface error\r\n");
}
break;
case kUSB_HostAudioRunSetInterfaceDone:
g_audioRecorder.runState = kUSB_HostAudioRunIdle;
{
usb_audio_ctrl_common_header_desc_t *commonHeader;
if (USB_HostAudioControlGetCurrentAltsettingSpecificDescriptors(
g_audioRecorder.classHandle, USB_AUDIO_DESCRIPTOR_TYPE_CS_INTERFACE,
USB_DESC_SUBTYPE_AUDIO_CS_HEADER, (void *)&commonHeader) != kStatus_USB_Success)
{
usb_echo("Get header descriptor error\r\n");
g_audioRecorder.runState = kUSB_HostAudioRunIdle;
}
else
{
g_audioRecorder.deviceAudioVersion =
USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(((uint8_t *)commonHeader->bcdcdc));
if (AUDIO_DEVICE_VERSION_01 == g_audioRecorder.deviceAudioVersion)
{
usb_echo("AUDIO 1.0 device\r\n");
if (USB_HostAudioStreamGetCurrentAltsettingSpecificDescriptors(
g_audioRecorder.classHandle, USB_DESCRIPTOR_TYPE_ENDPOINT, USB_AUDIO_EP_TYPE_DATA,
(void *)&g_pIsoEndpDesc) != kStatus_USB_Success)
{
usb_echo("Get data endpoint descriptor error\r\n");
}
if (USB_HostAudioStreamGetCurrentAltsettingSpecificDescriptors(
g_audioRecorder.classHandle, USB_AUDIO_DESCRIPTOR_TYPE_CS_INTERFACE,
USB_AUDIO_DESC_SUBTYPE_AS_FORMAT_TYPE,
(void *)&g_pFormatTypeDesc) != kStatus_USB_Success)
{
usb_echo("Get format descriptor error\r\n");
}
if (USB_HostAudioStreamGetCurrentAltsettingSpecificDescriptors(
g_audioRecorder.classHandle, USB_AUDIO_DESCRIPTOR_TYPE_CS_INTERFACE,
USB_AUDIO_DESC_SUBTYPE_AS_GENERAL, (void *)&g_pAsItfDesc) != kStatus_USB_Success)
{
usb_echo("Get audio general descriptor error\r\n");
}
g_audioRecorder.runWaitState = kUSB_HostAudioRunWaitAudioGetMinVolume;
g_audioRecorder.runState = kUSB_HostAudioRunIdle;
if (kStatus_USB_Success !=
USB_HostAudioGetSetFeatureUnitRequest(
g_audioRecorder.classHandle, (uint32_t)((AUDIO_FU_VOLUME << 8U) | 0U),
(uint32_t)((1U << 8) | USB_AUDIO_CS_REQUEST_CODE_GET_MIN), &minVol, sizeof(minVol),
Audio_ControlCallback, &g_audioRecorder))
{
g_audioRecorder.runState = kUSB_HostAudioRunAudioDone;
}
usb_echo("AUDIO_GET_MIN_VOLUME\r\n");
}
else if (AUDIO_DEVICE_VERSION_02 == g_audioRecorder.deviceAudioVersion)
{
usb_echo("AUDIO 2.0 device\r\n");
if (USB_HostAudioStreamGetCurrentAltsettingSpecificDescriptors(
g_audioRecorder.classHandle, USB_DESCRIPTOR_TYPE_ENDPOINT, USB_AUDIO_EP_TYPE_DATA,
(void *)&g_pIsoEndpDesc) != kStatus_USB_Success)
{
usb_echo("Get data endpoint descriptor error\r\n");
}
if (USB_HostAudioStreamGetCurrentAltsettingSpecificDescriptors(
g_audioRecorder.classHandle, USB_AUDIO_DESCRIPTOR_TYPE_CS_INTERFACE,
USB_AUDIO_DESC_SUBTYPE_AS_FORMAT_TYPE_20,
(void *)&g_pFormatTypeDesc_20) != kStatus_USB_Success)
{
usb_echo("Get format descriptor error\r\n");
}
if (USB_HostAudioStreamGetCurrentAltsettingSpecificDescriptors(
g_audioRecorder.classHandle, USB_AUDIO_DESCRIPTOR_TYPE_CS_INTERFACE,
USB_AUDIO_DESC_SUBTYPE_AS_GENERAL_20, (void *)&g_generalDesc_20) != kStatus_USB_Success)
{
usb_echo("Get audio general descriptor error\r\n");
}
g_audioRecorder.runWaitState = kUSB_HostAudioRunWaitAudioGetVolumeRang;
g_audioRecorder.runState = kUSB_HostAudioRunIdle;
if (kStatus_USB_Success !=
USB_HostAudioGetSetFeatureUnitRequest(
g_audioRecorder.classHandle, (uint32_t)((AUDIO_FU_VOLUME << 8U) | 0U),
(uint32_t)((1U << 8) | USB_AUDIO_CS_REQUEST_CODE_RANGE_20), &g_volumeRang,
sizeof(g_volumeRang), Audio_ControlCallback, &g_audioRecorder))
{
g_audioRecorder.runState = kUSB_HostAudioRunAudioDone;
}
usb_echo("AUDIO_GET_VOLUME_RANG\r\n");
}
else
{
usb_echo("unsupported audio device, current host only support audio1.0 and audio2.0\r\n");
}
}
}
break;
case kUSB_HostAudioRunAudioGetMaxVolume:
if (AUDIO_DEVICE_VERSION_01 == g_audioRecorder.deviceAudioVersion)
{
g_audioRecorder.runWaitState = kUSB_HostAudioRunWaitAudioGetMaxVolume;
g_audioRecorder.runState = kUSB_HostAudioRunIdle;
if (kStatus_USB_Success != USB_HostAudioGetSetFeatureUnitRequest(
g_audioRecorder.classHandle, (uint32_t)((AUDIO_FU_VOLUME << 8U) | 0U),
(uint32_t)((1U << 8U) | USB_AUDIO_CS_REQUEST_CODE_GET_MAX), &maxVol,
sizeof(maxVol), Audio_ControlCallback, &g_audioRecorder))
{
g_audioRecorder.runState = kUSB_HostAudioRunAudioDone;
}
}
break;
case kUSB_HostAudioRunAudioGetResVolume:
if (AUDIO_DEVICE_VERSION_01 == g_audioRecorder.deviceAudioVersion)
{
g_audioRecorder.runState = kUSB_HostAudioRunIdle;
g_audioRecorder.runWaitState = kUSB_HostAudioRunWaitAudioGetResVolume;
if (kStatus_USB_Success != USB_HostAudioGetSetFeatureUnitRequest(
g_audioRecorder.classHandle, (uint32_t)((AUDIO_FU_VOLUME << 8U) | 0U),
(uint32_t)((1U << 8U) | USB_AUDIO_CS_REQUEST_CODE_GET_RES), &resVol,
sizeof(resVol), Audio_ControlCallback, &g_audioRecorder))
{
g_audioRecorder.runState = kUSB_HostAudioRunAudioDone;
}
}
break;
case kUSB_HostAudioRunAudioGetCurrentVolume:
if (AUDIO_DEVICE_VERSION_02 == g_audioRecorder.deviceAudioVersion)
{
g_audioRecorder.runState = kUSB_HostAudioRunIdle;
g_audioRecorder.runWaitState = kUSB_HostAudioRunWaitAudioGetCurrentVolumeDone;
if (kStatus_USB_Success != USB_HostAudioGetSetFeatureUnitRequest(
g_audioRecorder.classHandle, (uint32_t)((AUDIO_FU_VOLUME << 8U) | 0U),
((1U << 8U) | USB_AUDIO_CS_REQUEST_CODE_CUR_20), &g_curVolume,
sizeof(g_curVolume), Audio_ControlCallback, &g_audioRecorder))
{
g_audioRecorder.runState = kUSB_HostAudioRunAudioDone;
}
}
break;
case kUSB_HostAudioRunAudioGetSampleFrequencyRange:
if (AUDIO_DEVICE_VERSION_02 == g_audioRecorder.deviceAudioVersion)
{
g_audioRecorder.runState = kUSB_HostAudioRunIdle;
g_audioRecorder.runWaitState = kUSB_HostAudioRunWaitAudioGetSampleFrequencyRange;
if (kStatus_USB_Success != USB_HostAudioGetSetClockSourceRequest(
g_audioRecorder.classHandle,
(uint32_t)((USB_AUDIO_CS_SAM_FREQ_CONTROL_20 << 8U) | 0U),
((1U << 8U) | USB_AUDIO_CS_REQUEST_CODE_RANGE_20), &g_frequencyRang,
sizeof(g_frequencyRang), Audio_ControlCallback, &g_audioRecorder))
{
g_audioRecorder.runState = kUSB_HostAudioRunAudioDone;
}
}
break;
case kUSB_HostAudioRunAudioGetAllSampleFrequencyRange:
if (AUDIO_DEVICE_VERSION_02 == g_audioRecorder.deviceAudioVersion)
{
/*fresurency use layout 3 Parameter Block, so the lenght is 2+12*n*/
g_frequencyAllRang =
malloc(2U + 12U * (USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS((&g_frequencyRang.wNumSubRanges[0]))));
g_audioRecorder.runState = kUSB_HostAudioRunIdle;
g_audioRecorder.runWaitState = kUSB_HostAudioRunWaitAudioGetAllSampleFrequencyRange;
if (kStatus_USB_Success !=
USB_HostAudioGetSetClockSourceRequest(
g_audioRecorder.classHandle, (uint32_t)((USB_AUDIO_CS_SAM_FREQ_CONTROL_20 << 8U) | 0U),
((1U << 8U) | USB_AUDIO_CS_REQUEST_CODE_RANGE_20), g_frequencyAllRang,
(2U + 12U * (USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS((&g_frequencyRang.wNumSubRanges[0])))),
Audio_ControlCallback, &g_audioRecorder))
{
g_audioRecorder.runState = kUSB_HostAudioRunAudioDone;
}
}
break;
case kUSB_HostAudioRunAudioConfigChannel:
g_audioRecorder.runState = kUSB_HostAudioRunIdle;
if (AUDIO_DEVICE_VERSION_01 == g_audioRecorder.deviceAudioVersion)
{
g_minVolume = (uint16_t)(minVol[1] << 8U) | (minVol[0]);
g_maxVolume = (uint16_t)(maxVol[1] << 8U) | (maxVol[0]);
g_deviceVolumeStep =
(int16_t)(((int16_t)(g_maxVolume) - (int16_t)(g_minVolume)) / (HOST_MAX_VOLUME - HOST_MIN_VOLUME));
g_curVolume = (int16_t)(g_minVolume + g_deviceVolumeStep * g_hostCurVolume);
g_curVol[0] = (uint8_t)((uint16_t)g_curVolume & 0x00FF);
g_curVol[1] = (uint8_t)((uint16_t)g_curVolume >> 8U);
g_curMute[0] = 0U;
g_audioRecorder.runWaitState = kUSB_HostAudioRunWaitAudioConfigChannel;
if (kStatus_USB_Success != USB_HostAudioGetSetFeatureUnitRequest(
g_audioRecorder.classHandle, (uint32_t)((AUDIO_FU_MUTE << 8U) | 0U),
(uint32_t)((0U << 8U) | USB_AUDIO_CS_REQUEST_CODE_SET_CUR), &g_curMute,
sizeof(g_curMute), Audio_ControlCallback, &g_audioRecorder))
{
g_audioRecorder.runState = kUSB_HostAudioRunAudioConfigChannel1Vol;
}
}
else if (AUDIO_DEVICE_VERSION_02 == g_audioRecorder.deviceAudioVersion)
{
g_minVolume = USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS((&g_volumeRang.wMIN[0]));
g_maxVolume = USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS((&g_volumeRang.wMAX[0]));
g_deviceVolumeStep = USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS((&g_volumeRang.wRES[0]));
g_curVol[0] = (uint8_t)((uint16_t)g_curVolume & 0x00FF);
g_curVol[1] = (uint8_t)((uint16_t)g_curVolume >> 8U);
g_curMute[0] = 0U;
g_audioRecorder.runWaitState = kUSB_HostAudioRunWaitAudioConfigChannel;
if (kStatus_USB_Success != USB_HostAudioGetSetFeatureUnitRequest(
g_audioRecorder.classHandle, (uint32_t)((AUDIO_FU_MUTE << 8U) | 0U),
((0U << 8U) | USB_AUDIO_CS_REQUEST_CODE_CUR_20), (void *)g_curMute,
sizeof(g_curMute[0]), Audio_ControlCallback, &g_audioRecorder))
{
g_audioRecorder.runState = kUSB_HostAudioRunAudioConfigChannel1Vol;
}
}
else
{
/*TO DO*/
}
break;
case kUSB_HostAudioRunAudioConfigMute:
if (AUDIO_DEVICE_VERSION_01 == g_audioRecorder.deviceAudioVersion)
{
g_audioRecorder.runState = kUSB_HostAudioRunIdle;
g_curMute[0] = !g_curMute[0];
g_audioRecorder.runWaitState = kUSB_HostAudioRunWaitAudioConfigMute;
if (kStatus_USB_Success != USB_HostAudioGetSetFeatureUnitRequest(
g_audioRecorder.classHandle, (uint32_t)((AUDIO_FU_MUTE << 8U) | 0U),
((0U << 8U) | USB_AUDIO_CS_REQUEST_CODE_SET_CUR), (void *)g_curMute,
sizeof(g_curMute[0]), Audio_ControlCallback, &g_audioRecorder))
{
usb_echo("config mute failed\n\r");
}
}
else if ((AUDIO_DEVICE_VERSION_02 == g_audioRecorder.deviceAudioVersion))
{
g_audioRecorder.runState = kUSB_HostAudioRunIdle;
g_curMute[0] = !g_curMute[0];
g_audioRecorder.runWaitState = kUSB_HostAudioRunWaitAudioConfigMute;
if (kStatus_USB_Success != USB_HostAudioGetSetFeatureUnitRequest(
g_audioRecorder.classHandle, (uint32_t)((AUDIO_FU_MUTE << 8U) | 0U),
((0U << 8U) | USB_AUDIO_CS_REQUEST_CODE_CUR_20), (void *)g_curMute,
sizeof(g_curMute[0]), Audio_ControlCallback, &g_audioRecorder))
{
usb_echo("config mute failed\n\r");
}
}
else
{
/*TO DO*/
}
break;
case kUSB_HostAudioRunAudioConfigChannel1Vol:
g_audioRecorder.runState = kUSB_HostAudioRunIdle;
g_audioRecorder.runWaitState = kUSB_HostAudioRunWaitAudioConfigChannel1Vol;
if (AUDIO_DEVICE_VERSION_01 == g_audioRecorder.deviceAudioVersion)
{
if (kStatus_USB_Success != USB_HostAudioGetSetFeatureUnitRequest(
g_audioRecorder.classHandle, (uint32_t)((AUDIO_FU_VOLUME << 8U) | 0U),
((0U << 8U) | USB_AUDIO_CS_REQUEST_CODE_SET_CUR), (void *)g_curVol,
sizeof(g_curVol), Audio_ControlCallback, &g_audioRecorder))
{
g_audioRecorder.runState = kUSB_HostAudioRunAudioSetCurSamplingFreq;
usb_echo("config volume failed\n\r");
}
}
else if ((AUDIO_DEVICE_VERSION_02 == g_audioRecorder.deviceAudioVersion))
{
if (kStatus_USB_Success != USB_HostAudioGetSetFeatureUnitRequest(
g_audioRecorder.classHandle, (uint32_t)((AUDIO_FU_VOLUME << 8U) | 0U),
((0U << 8U) | USB_AUDIO_CS_REQUEST_CODE_CUR_20), (void *)g_curVol,
sizeof(g_curVol), Audio_ControlCallback, &g_audioRecorder))
{
g_audioRecorder.runState = kUSB_HostAudioRunAudioSetCurSamplingFreq;
usb_echo("config volume failed\n\r");
}
}
else
{
/*TO DO*/
}
break;
case kUSB_HostAudioRunAudioConfigChannel2Vol:
if (AUDIO_DEVICE_VERSION_01 == g_audioRecorder.deviceAudioVersion)
{
g_audioRecorder.runState = kUSB_HostAudioRunIdle;
g_audioRecorder.runWaitState = kUSB_HostAudioRunWaitAudioConfigChannel2Vol;
if (kStatus_USB_Success != USB_HostAudioGetSetFeatureUnitRequest(
g_audioRecorder.classHandle,
(uint32_t)((AUDIO_FU_VOLUME << 8U) | g_pFormatTypeDesc->bnrchannels),
((0U << 8U) | USB_AUDIO_CS_REQUEST_CODE_SET_CUR), (void *)g_curVol,
sizeof(g_curVol), Audio_ControlCallback, &g_audioRecorder))
{
g_audioRecorder.runState = kUSB_HostAudioRunAudioSetCurSamplingFreq;
usb_echo("config channel 2 volume failed\n\r");
}
}
else if ((AUDIO_DEVICE_VERSION_02 == g_audioRecorder.deviceAudioVersion))
{
g_audioRecorder.runState = kUSB_HostAudioRunIdle;
g_audioRecorder.runWaitState = kUSB_HostAudioRunWaitAudioConfigChannel2Vol;
if (kStatus_USB_Success != USB_HostAudioGetSetFeatureUnitRequest(
g_audioRecorder.classHandle,
(uint32_t)((AUDIO_FU_VOLUME << 8U) | g_generalDesc_20->bNrChannels),
((0U << 8U) | USB_AUDIO_CS_REQUEST_CODE_CUR_20), (void *)g_curVol,
sizeof(g_curVol), Audio_ControlCallback, &g_audioRecorder))
{
g_audioRecorder.runState = kUSB_HostAudioRunAudioSetCurSamplingFreq;
usb_echo("config channel 2 volume failed\n\r");
}
}
else
{
/*TO DO*/
}
break;
case kUSB_HostAudioRunAudioSetCurSamplingFreq:
usb_echo("Audio Recorder device information:\r\n");
if (AUDIO_DEVICE_VERSION_01 == g_audioRecorder.deviceAudioVersion)
{
for (bsamfreqtype_g_index = 0U; bsamfreqtype_g_index < g_pFormatTypeDesc->bsamfreqtype;
bsamfreqtype_g_index++)
{
usb_echo(" - Frequency device support : %d Hz\n\r",
(((uint32_t)g_pFormatTypeDesc->tsamfreq[bsamfreqtype_g_index][2]) << 16U) |
(((uint32_t)g_pFormatTypeDesc->tsamfreq[bsamfreqtype_g_index][1]) << 8U) |
(((uint32_t)g_pFormatTypeDesc->tsamfreq[bsamfreqtype_g_index][0]) << 0U));
}
usb_echo(" - Bit resolution : %d bits\n\r", g_pFormatTypeDesc->bbitresolution);
usb_echo(" - Number of channels : %d channels\n\r", g_pFormatTypeDesc->bnrchannels);
usb_echo(" - Transfer type : %s\n\r", strTransferType[(g_pIsoEndpDesc->bmAttributes) & EP_TYPE_MASK]);
usb_echo(" - Sync type : %s\n\r",
strSyncType[(uint8_t)(g_pIsoEndpDesc->bmAttributes >> 2) & EP_TYPE_MASK]);
usb_echo(" - Usage type : %s \n\r",
strDataType[(uint8_t)(g_pIsoEndpDesc->bmAttributes >> 4) & EP_TYPE_MASK]);
usb_echo("This audio device supports play audio files with these properties:\r\n");
usb_echo(" - Sample rate :\r\n");
for (bsamfreqtype_g_index = 0U; bsamfreqtype_g_index < g_pFormatTypeDesc->bsamfreqtype;
bsamfreqtype_g_index++)
{
usb_echo(" : %d Hz\n\r",
(((uint32_t)g_pFormatTypeDesc->tsamfreq[bsamfreqtype_g_index][2]) << 16U) |
(((uint32_t)g_pFormatTypeDesc->tsamfreq[bsamfreqtype_g_index][1]) << 8U) |
(((uint32_t)g_pFormatTypeDesc->tsamfreq[bsamfreqtype_g_index][0]) << 0U));
}
usb_echo(" - Sample size : %d bits\n\r", g_pFormatTypeDesc->bbitresolution);
usb_echo(" - Number of channels : %d channels\n\r", g_pFormatTypeDesc->bnrchannels);
usb_echo("USB Recorder example try to record %dk_%dbit_%dch audio using PCM format.\r\n",
((((uint32_t)g_pFormatTypeDesc->tsamfreq[0][2]) << 16U) |
(((uint32_t)g_pFormatTypeDesc->tsamfreq[0][1]) << 8U) |
(((uint32_t)g_pFormatTypeDesc->tsamfreq[0][0]) << 0U)) /
1000U,
g_pFormatTypeDesc->bbitresolution, g_pFormatTypeDesc->bnrchannels);
}
else if ((AUDIO_DEVICE_VERSION_02 == g_audioRecorder.deviceAudioVersion))
{
if (1U < USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS((&g_frequencyRang.wNumSubRanges[0])))
{
/*frequency array location in layout 3, offset 2 is the start address of frequency array*/
frequencyArray = (uint8_t *)(g_frequencyAllRang + 2U);
usb_echo("more than one frequenuy is support by device\r\n");
}
else
{
frequencyArray = (uint8_t *)&g_frequencyRang.wMIN[0];
}
frequencyArrayStart = frequencyArray;
for (bsamfreqtype_g_index = 0U;
bsamfreqtype_g_index < USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS((&g_frequencyRang.wNumSubRanges[0]));
bsamfreqtype_g_index++)
{
/*frequency array location in layout 3*/
usb_echo(
" - Frequency device support frequency rang is :MIN %d Hz, MAX %d Hz, RES attributes %dHz, "
"\n\r",
USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS((frequencyArrayStart)),
USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS((frequencyArrayStart + 4U)),
USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS((frequencyArrayStart + 8U)));
frequencyArrayStart += sizeof(usb_audio_2_0_layout3_struct_t);
}
usb_echo(" - Bit resolution : %d bits\n\r", g_pFormatTypeDesc_20->bBitResolution);
usb_echo(" - Number of channels : %d channels\n\r", g_generalDesc_20->bNrChannels);
usb_echo(" - Transfer type : %s\n\r", strTransferType[(g_pIsoEndpDesc->bmAttributes) & EP_TYPE_MASK]);
usb_echo(" - Sync type : %s\n\r",
strSyncType[(uint8_t)(g_pIsoEndpDesc->bmAttributes >> 2U) & EP_TYPE_MASK]);
usb_echo(" - Usage type : %s \n\r",
strDataType[(uint8_t)(g_pIsoEndpDesc->bmAttributes >> 4U) & EP_TYPE_MASK]);
usb_echo("USB Host Recorder example try to record %dk_%dbit_%d ch audio using PCM format.\r\n",
USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS((frequencyArray)) / 1000U,
g_pFormatTypeDesc_20->bBitResolution, g_generalDesc_20->bNrChannels);
}
else
{
/*TO DO*/
}
g_audioRecorder.audioRecorderIsoMaxPacketSize =
(uint16_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(g_pIsoEndpDesc->wMaxPacketSize) &
USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK));
g_audioRecorder.runState = kUSB_HostAudioRunIdle;
g_audioRecorder.runWaitState = kUSB_HostAudioRunWaitAudioSetCurSamplingFreq;
if ((AUDIO_DEVICE_VERSION_02 == g_audioRecorder.deviceAudioVersion))
{
}
if (AUDIO_DEVICE_VERSION_01 == g_audioRecorder.deviceAudioVersion)
{
USB_HostAudioGetSetEndpointRequest(g_audioRecorder.classHandle,
(uint32_t)((USB_AUDIO_EP_CS_SAMPING_FREQ_CONTROL << 8U)),
((0U << 8U) | USB_AUDIO_CS_REQUEST_CODE_SET_CUR), &freq,
sizeof(freq), Audio_ControlCallback, &g_audioRecorder);
}
else if ((AUDIO_DEVICE_VERSION_02 == g_audioRecorder.deviceAudioVersion))
{
USB_HostAudioGetSetClockSourceRequest(g_audioRecorder.classHandle,
(uint32_t)((USB_AUDIO_CS_SAM_FREQ_CONTROL_20 << 8U) | 0U),
((0U << 8U) | USB_AUDIO_CS_REQUEST_CODE_CUR_20), &freq,
sizeof(freq), Audio_ControlCallback, &g_audioRecorder);
}
else
{
/*TO DO*/
}
break;
case kUSB_HostAudioRunAudioDone:
if ((AUDIO_DEVICE_VERSION_01 == g_audioRecorder.deviceAudioVersion))
{
/* only Audio Data Format Type I support PCM format */
if (USB_AUDIO_FORMAT_TYPE_I == g_pFormatTypeDesc->bformattype)
{
if ((0x0001U == USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(g_pAsItfDesc->wformattag)) ||
(0x0002U == USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(g_pAsItfDesc->wformattag)))
{
pcm_format = 1U;
}
}
}
else if ((AUDIO_DEVICE_VERSION_02 == g_audioRecorder.deviceAudioVersion))
{
/* only Audio Data Format Type I and IV support PCM format */
if ((USB_AUDIO_FORMAT_TYPE_I == g_generalDesc_20->bFormatType) ||
(USB_AUDIO_FORMAT_TYPE_IV == g_generalDesc_20->bFormatType))
{
/* PCM or PCM8 */
if ((g_generalDesc_20->bmFormats[0] & 0x01U) || (g_generalDesc_20->bmFormats[0] & 0x02U))
{
pcm_format = 1U;
}
}
}
else
{
/*TO DO*/
}
if (0U == pcm_format)
{
g_audioRecorder.runState = kUSB_HostAudioRunIdle;
g_audioRecorder.runWaitState = kUSB_HostAudioRunIdle;
usb_echo("Do not support this device, USB Host only supports PCM/PCM8 format\r\n");
return;
}
usb_echo("Enter character 'r' to start recording or 's' to stop recording\r\n");
g_audioRecorder.audioFileIndex = 0;
g_audioRecorder.runState = kUSB_HostAudioRunAudioWaitCommand;
case kUSB_HostAudioRunAudioWaitCommand:
g_audioRecorder.audioRecorderRunFlag = 0U;
g_audioRecorder.audioRecorderWriteSdcardFlag = 0U;
g_audioRecorder.audioRecorderStreamUsbBufferIndex = 0U;
g_audioRecorder.audioRecorderStreamPutBufferIndex = 0U;
g_audioRecorder.audioRecorderStreamGetBufferIndex = 0U;
g_audioRecorder.recorderUsedSpace = 0U;
USB_HostAudioRecorderWaitCommand();
if (1U == g_audioRecorder.audioRecorderRunFlag)
{
/* prime total transfers */
for (uint8_t i = 0; i < USB_AUDIO_RECORDER_STREAM_PRIME_COUNT; i++)
{
USB_HostAudioStreamRecv(
g_audioRecorder.classHandle, (unsigned char *)&s_audioRecordStreamBuffer[i][0],
g_audioRecorder.audioRecorderIsoMaxPacketSize, Audio_RecorderInCallback, &g_audioRecorder);
}
g_audioRecorder.runState = kUSB_HostAudioRecorderStartWriteSdcard;
g_audioRecorder.audioRecorderWriteSdcardFlag = 1;
usb_echo("Recording starts...\r\n");
}
break;
case kUSB_HostAudioRecorderStartWriteSdcard:
USB_HostAudioRecorderWaitCommand();
USB_HostAudioRecorderWriteSdcard();
break;
default:
break;
}
}
/*!
* @brief host usb audio mute request.
*
* This function implements the host audio mute request action, it is used to mute or unmute audio device.
*
*/
void Audio_MuteRequest(void)
{
if (g_audioRecorder.devState > kStatus_DEV_Detached)
{
usb_echo(" err: Audio Recorder is not connected\n\r");
return;
}
if (g_audioRecorder.deviceIsUsed == 0)
{
usb_echo(" err: Audio Recorder is not Ready\n\r");
return;
}
g_audioRecorder.runState = kUSB_HostAudioRunAudioConfigMute;
}
/*!
* @brief host usb audio increase volume request.
*
* This function implements the host audio increase volume request action, it is used to increase the volume of audio
* device.
*
* @param channel the audio device channel number.
*/
void Audio_IncreaseVolumeRequest(uint8_t channel)
{
static uint32_t i;
uint8_t max_audio_channel;
max_audio_channel = 2U;
if (channel > max_audio_channel)
{
usb_echo(" err: Channel number larger than max channel\n\r");
return;
}
if (g_audioRecorder.devState > kStatus_DEV_Detached)
{
usb_echo(" err: Audio Recorder is not connected\n\r");
return;
}
if (g_audioRecorder.deviceIsUsed == 0)
{
usb_echo(" err: Audio Recorder is not Ready\n\r");
return;
}
if (channel == 1U)
{
/* Send set mute request */
if ((g_hostCurVolume + HOST_VOLUME_STEP) > HOST_MAX_VOLUME)
{
g_hostCurVolume = HOST_MAX_VOLUME;
i = 0U;
}
else
{
g_hostCurVolume += HOST_VOLUME_STEP;
i = 1U;
}
g_curVolume += (int16_t)(i * HOST_VOLUME_STEP * g_deviceVolumeStep);
g_curVol[0] = (int8_t)((uint16_t)(g_curVolume)&0x00FF);
g_curVol[1] = (int8_t)((uint16_t)(g_curVolume) >> 8U);
}
g_audioRecorder.runState = kUSB_HostAudioRunAudioConfigChannel1Vol;
}
/*!
* @brief host usb audio decrease volume request.
*
* This function implements the host audio decrease volume request action, it is used to decrease the volume of audio
* device.
*
* @param channel the audio device channel number.
*/
void Audio_DecreaseVolumeRequest(uint8_t channel)
{
static uint32_t i;
uint8_t max_audio_channel;
max_audio_channel = g_pFormatTypeDesc->bnrchannels;
if (channel > max_audio_channel)
{
usb_echo(" err: Channel number larger than max channel\n\r");
return;
}
if (g_audioRecorder.devState > kStatus_DEV_Detached)
{
usb_echo(" err: Audio Recorder is not connected\n\r");
return;
}
if (g_audioRecorder.deviceIsUsed == 0U)
{
usb_echo(" err: Audio Recorder is not Ready\n\r");
return;
}
if (channel == 1U)
{
if (g_hostCurVolume < (HOST_VOLUME_STEP + HOST_MIN_VOLUME))
{
g_hostCurVolume = HOST_MIN_VOLUME;
i = 0U;
}
else
{
g_hostCurVolume -= HOST_VOLUME_STEP;
i = 1U;
}
g_curVolume -= (int16_t)(i * HOST_VOLUME_STEP * g_deviceVolumeStep);
g_curVol[0] = (int8_t)((uint16_t)(g_curVolume)&0x00FF);
g_curVol[1] = (int8_t)((uint16_t)(g_curVolume) >> 8U);
}
g_audioRecorder.runState = kUSB_HostAudioRunAudioConfigChannel1Vol;
}
/*!
* @brief host audio callback function.
*
* This function should be called in the host callback function.
*
* @param deviceHandle device handle.
* @param configurationHandle attached device's configuration descriptor information.
* @param eventCode callback event code, please reference to enumeration host_event_t.
*
* @retval kStatus_USB_Success The host is initialized successfully.
* @retval kStatus_USB_NotSupported The configuration don't contain hid mouse interface.
*/
usb_status_t USB_HostAudioEvent(usb_device_handle deviceHandle,
usb_host_configuration_handle configurationHandle,
uint32_t eventCode)
{
uint8_t id;
usb_host_configuration_t *configuration_ptr;
uint8_t interface_g_index;
usb_host_interface_t *interface_ptr;
uint32_t info_value = 0U;
usb_status_t status = kStatus_USB_Success;
switch (eventCode)
{
case kUSB_HostEventAttach:
/* judge whether is configurationHandle supported */
configuration_ptr = (usb_host_configuration_t *)configurationHandle;
g_audioRecorderDeviceHandle = NULL;
g_audioRecorderOutControlifHandle = NULL;
g_audioRecorderOutStreamifHandle = NULL;
for (interface_g_index = 0U; interface_g_index < configuration_ptr->interfaceCount; ++interface_g_index)
{
interface_ptr = &configuration_ptr->interfaceList[interface_g_index];
id = interface_ptr->interfaceDesc->bInterfaceClass;
if (id != USB_AUDIO_CLASS_CODE)
{
continue;
}
id = interface_ptr->interfaceDesc->bInterfaceSubClass;
if (id == USB_AUDIO_SUBCLASS_CODE_CONTROL)
{
g_audioRecorderOutControlifHandle = interface_ptr;
continue;
}
else if (id == USB_AUDIO_SUBCLASS_CODE_AUDIOSTREAMING)
{
usb_host_interface_t alternate1Interface;
if (interface_ptr->alternateSettingNumber > 0U)
{
USB_HostHelperParseAlternateSetting(interface_ptr, 1, &alternate1Interface);
for (info_value = 0U; info_value < alternate1Interface.epCount; ++info_value)
{
if ((alternate1Interface.epList[info_value].epDesc->bEndpointAddress &
USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN)
{
g_audioRecorderDeviceHandle = deviceHandle;
g_audioRecorderOutStreamifHandle = interface_ptr;
break;
}
}
}
if (g_audioRecorderDeviceHandle != NULL)
{
break;
}
}
else
{
continue;
}
}
if (g_audioRecorderDeviceHandle != NULL)
{
return kStatus_USB_Success;
}
status = kStatus_USB_NotSupported;
break;
case kUSB_HostEventNotSupported:
break;
case kUSB_HostEventEnumerationDone:
if (g_audioRecorder.devState == kStatus_DEV_Idle)
{
if ((g_audioRecorderDeviceHandle != NULL) && (g_audioRecorderOutControlifHandle != NULL))
{
g_audioRecorder.devState = kStatus_DEV_Attached;
g_audioRecorder.deviceHandle = g_audioRecorderDeviceHandle;
g_audioRecorder.controlIntfHandle = g_audioRecorderOutControlifHandle;
g_audioRecorder.streamIntfHandle = g_audioRecorderOutStreamifHandle;
USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDevicePID, &info_value);
usb_echo("audio generator attached:pid=0x%x", info_value);
USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceVID, &info_value);
usb_echo("vid=0x%x ", info_value);
USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceAddress, &info_value);
usb_echo("address=%d\r\n", info_value);
}
}
else
{
usb_echo("not idle audio instance\r\n");
}
break;
case kUSB_HostEventDetach:
if (g_audioRecorder.devState != kStatus_DEV_Idle)
{
g_audioRecorder.devState = kStatus_DEV_Detached;
}
break;
default:
break;
}
return status;
}
/*!
* @brief host audio sdcard initialization function.
*
* This function implements the sdcard detect and initialization
*
*/
usb_status_t USB_HostAudioAppSDcardInit(void)
{
FATFS *fs;
FIL fileObj;
uint32_t freeClusterNumber;
uint32_t freeMemorySizeMB;
char fileName[25];
usb_echo("please insert SD card\r\n");
if (f_mount(&g_fileSystem, g_DriverNumberBuffer, 1U))
{
usb_echo("f_mount failed.\r\n");
return kStatus_USB_Error;
}
else
{
usb_echo("sdcard inserted\r\n");
}
if (f_getfree(&g_DriverNumberBuffer[0], (DWORD *)&freeClusterNumber, &fs))
{
usb_echo("f_getfree failed.\r\n");
return kStatus_USB_Error;
}
else
{
freeMemorySizeMB = freeClusterNumber * (fs->csize) / 2048;
usb_echo("sdcard free size: %d MB\r\n", freeMemorySizeMB);
}
/* this operation is to make sure the sdcard and fatfs system is ready fully */
sprintf(fileName, "%saudio.txt", &g_DriverNumberBuffer[0]);
if (f_open(&fileObj, _T(fileName), FA_WRITE | FA_CREATE_ALWAYS) == FR_OK)
{
f_close(&fileObj);
(void)f_unlink(fileName);
}
return kStatus_USB_Success;
}