This module provides a USB Peripheral Audio Device Class Driver (PAUD). It implements the USB PAUD Interface.
The r_usb_paud module combines with the r_usb_basic module to provide a USB Peripheral Audio Device Class (PAUD) driver.
This driver notifies the application when receiving the following class requests:
For details about each device class, please refer to Audio Class specification.
#define A10_FU_ID_0 (5)
#define A10_FU_ID_1 (8)
#define A10_EP_ADDR_OUT (0x02)
#define A10_EP_ADDR_IN (0x81)
#define A10_MUTE_0 (0)
#define A10_MUTE_1 (0x10)
#define A10_VOL_0 (0)
#define A10_VOL_MIN_0 (0)
#define A10_VOL_MAX_0 (0x80)
#define A10_VOL_RES_0 (0x40)
#define A10_VOL_1 (0)
#define A10_VOL_MIN_1 (0)
#define A10_VOL_MAX_1 (0xF0)
#define A10_VOL_RES_1 (0x80)
#define ISO_OUT_IF_NO (0x0001)
#define ISO_IN_IF_NO (0x0002)
#define ISO_IF_ALT_1 (0x0001)
#define ISO_IF_ALT_0 (0x0000)
#define ISO_OUT_MAX_PACKET_SIZE (192)
#define ISO_IN_MAX_PACKET_SIZE (200)
#define APP_BUFFER_SIZE (1024 * 200)
#define BMREQUESTTYPEDIR (0x0080U)
#define VALUE_FF00H (0xFF00)
void usb_paud_example(void);
#if (BSP_CFG_RTOS == 2)
void usb_apl_callback(usb_event_info_t * p_event_info, usb_hdl_t handler,
usb_onoff_t state);
#endif
static uint8_t g_paud10_snd_buf[APP_BUFFER_SIZE] = {0};
static uint8_t g_paud10_rcv_buf[ISO_OUT_MAX_PACKET_SIZE] = {0};
static uint32_t g_rcv_index = 0;
static uint32_t g_snd_index = 0;
static volatile bool g_err_flag = false;
static bool b_usb_connected = false;
static void process_usb_audio_class_request(void);
static void process_usb_audio_class_request_out(void);
static void process_usb_audio_class_request_in(void);
static void reset_apl_buffer_info(void);
static void handle_error(
fsp_err_t err,
char * err_str);
#if (BSP_CFG_RTOS == 2)
static volatile usb_event_info_t * p_usb_event = NULL;
#else
static usb_event_info_t event_info = {0};
static volatile usb_event_info_t * p_usb_event = &event_info;
#endif
#if (BSP_CFG_RTOS == 2)
extern QueueHandle_t g_queue;
#endif
void usb_paud_example (void)
{
#if (BSP_CFG_RTOS == 2)
BaseType_t err_queue = pdFALSE;
#endif
g_audio_control[0].
fu_id = A10_FU_ID_0;
g_audio_control[0].
mute = A10_MUTE_0;
g_audio_control[0].
volume = A10_VOL_0;
g_audio_control[0].ep_addr = A10_EP_ADDR_OUT;
g_audio_control[1].
fu_id = A10_FU_ID_1;
g_audio_control[1].
mute = A10_MUTE_1;
g_audio_control[1].
volume = A10_VOL_1;
g_audio_control[1].ep_addr = A10_EP_ADDR_IN;
g_audio_control_group.
p_controls = &g_audio_control[0];
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
while (true)
{
if (true == g_err_flag)
{
handle_error(
FSP_ERR_ABORTED,
"\r\nError in sending usb event through queue\r\n");
}
#if (BSP_CFG_RTOS == 2)
err_queue = xQueueReceive(g_queue, &p_usb_event, (portMAX_DELAY));
if (pdTRUE != err_queue)
{
handle_error(
FSP_ERR_ABORTED,
"\r\nError in receiving event through queue\r\n");
}
#else
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
#endif
err = process_usb_events();
handle_error(err, "\r\nprocess_usb_events failed.\r\n");
}
}
{
switch (p_usb_event->event)
{
{
b_usb_connected = true;
break;
}
{
if ((FSP_SUCCESS == p_usb_event->status) || (FSP_ERR_USB_SIZE_SHORT == p_usb_event->status))
{
if ((g_rcv_index + p_usb_event->data_size) < APP_BUFFER_SIZE)
{
memcpy(&g_paud10_snd_buf[g_rcv_index], g_paud10_rcv_buf, p_usb_event->data_size);
}
g_rcv_index += p_usb_event->data_size;
if ((g_rcv_index + ISO_OUT_MAX_PACKET_SIZE) < APP_BUFFER_SIZE)
{
if (b_usb_connected)
{
}
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
}
}
break;
}
{
if (FSP_SUCCESS == p_usb_event->status)
{
g_snd_index += ISO_IN_MAX_PACKET_SIZE;
if (g_snd_index >= APP_BUFFER_SIZE)
{
g_snd_index = 0;
}
else
{
if (b_usb_connected)
{
&g_paud10_snd_buf[g_snd_index],
ISO_IN_MAX_PACKET_SIZE,
}
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
}
}
break;
}
{
process_usb_audio_class_request();
break;
}
{
{
{
if (ISO_OUT_IF_NO == p_usb_event->setup.request_index)
{
if (ISO_IF_ALT_1 == p_usb_event->setup.request_value)
{
if (b_usb_connected)
{
g_paud10_rcv_buf,
ISO_OUT_MAX_PACKET_SIZE,
}
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
}
if (ISO_IF_ALT_0 == p_usb_event->setup.request_value)
{
}
}
if (ISO_IN_IF_NO == p_usb_event->setup.request_index)
{
if (ISO_IF_ALT_1 == p_usb_event->setup.request_value)
{
if (b_usb_connected)
{
g_paud10_snd_buf,
ISO_IN_MAX_PACKET_SIZE,
}
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
}
if (ISO_IF_ALT_0 == p_usb_event->setup.request_value)
{
}
}
}
}
break;
}
{
b_usb_connected = false;
reset_apl_buffer_info();
break;
}
{
b_usb_connected = true;
break;
}
default:
{
break;
}
}
return err;
}
static void process_usb_audio_class_request (void)
{
if (
USB_HOST_TO_DEV == (BMREQUESTTYPEDIR & p_usb_event->setup.request_type))
{
process_usb_audio_class_request_out();
}
{
process_usb_audio_class_request_in();
}
else
{
}
}
static void process_usb_audio_class_request_out (void)
{
uint32_t i;
uint32_t unit_id;
{
{
{
if (A10_EP_ADDR_OUT == p_usb_event->setup.request_index)
{
p_usb_event->setup.request_length);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
}
else if (A10_EP_ADDR_IN == p_usb_event->setup.request_index)
{
p_usb_event->setup.request_length);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
}
else
{
}
}
else
{
}
}
else
{
}
}
{
unit_id = (uint32_t) (p_usb_event->setup.request_index & VALUE_FF00H);
unit_id = unit_id >> 8;
for (i = 0; i < g_audio_control_group.
controls_nb; i++)
{
{
{
p_usb_event->setup.request_length);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
break;
}
{
p_usb_event->setup.request_length);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
break;
}
}
}
}
else
{
}
}
static void process_usb_audio_class_request_in (void)
{
uint32_t i;
uint32_t unit_id;
uint32_t size;
{
{
{
if (A10_EP_ADDR_OUT == p_usb_event->setup.request_index)
{
p_usb_event->setup.request_length);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
}
else if (A10_EP_ADDR_IN == p_usb_event->setup.request_index)
{
p_usb_event->setup.request_length);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
}
else
{
}
}
else
{
}
}
else
{
}
}
{
unit_id = (uint32_t) (p_usb_event->setup.request_index & VALUE_FF00H);
unit_id = unit_id >> 8;
for (i = 0; i < g_audio_control_group.
controls_nb; i++)
{
{
{
if (p_usb_event->setup.request_length <
mute))
{
size = p_usb_event->setup.request_length;
}
else
{
size =
mute);
}
size);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
break;
}
{
if (p_usb_event->setup.request_length <
volume))
{
size = p_usb_event->setup.request_length;
}
else
{
size =
volume);
}
size);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
break;
}
}
}
}
{
unit_id = (uint32_t) (p_usb_event->setup.request_index & VALUE_FF00H);
unit_id = unit_id >> 8;
for (i = 0; i < g_audio_control_group.
controls_nb; i++)
{
{
{
if (p_usb_event->setup.request_length <
volume_min))
{
size = p_usb_event->setup.request_length;
}
else
{
size =
volume_min);
}
size);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
break;
}
}
}
}
{
unit_id = (uint32_t) (p_usb_event->setup.request_index & VALUE_FF00H);
unit_id = unit_id >> 8;
for (i = 0; i < g_audio_control_group.
controls_nb; i++)
{
{
{
if (p_usb_event->setup.request_length <
volume_max))
{
size = p_usb_event->setup.request_length;
}
else
{
size =
volume_max);
}
size);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
break;
}
}
}
}
{
unit_id = (uint32_t) (p_usb_event->setup.request_index & VALUE_FF00H);
unit_id = unit_id >> 8;
for (i = 0; i < g_audio_control_group.
controls_nb; i++)
{
{
{
if (p_usb_event->setup.request_length <
volume_res))
{
size = p_usb_event->setup.request_length;
}
else
{
size =
volume_res);
}
size);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
break;
}
}
}
}
else
{
}
}
static void reset_apl_buffer_info (void)
{
memset(g_paud10_snd_buf, 0, sizeof(g_paud10_snd_buf));
g_rcv_index = 0;
g_snd_index = 0;
}
#if (BSP_CFG_RTOS == 2)
void usb_apl_callback (usb_event_info_t * p_event_info, usb_hdl_t handler,
usb_onoff_t state)
{
if (pdTRUE != (xQueueSend(g_queue, (const void *) &p_event_info, (TickType_t) (RESET_VALUE))))
{
g_err_flag = true;
}
}
#endif
static void handle_error (
fsp_err_t err,
char * err_str)
{
if (FSP_SUCCESS != err)
{
{
APP_ERR_TRAP
}
APP_ERR_TRAP
}
}
#define USB_PAUD_CLOCK_SOURCE_UNIT (0x1000U)
#define A20_CS_ID (0x10)
#define A20_SAMPLING_FREQUENCY (48000)
#define A20_FU_ID_0 (5)
#define A20_FU_ID_1 (8)
#define A20_MUTE (0)
#define A20_VOL_MIN_0 (0)
#define A20_VOL_MAX_0 (100)
#define A20_SET_VOL_0 (50)
#define A20_VOL_MIN_1 (0)
#define A20_VOL_MAX_1 (200)
#define A20_SET_VOL_1 (100)
#define ISO_OUT_IF_NO (0x0001)
#define ISO_IN_IF_NO (0x0002)
#define ISO_IF_ALT_1 (0x0001)
#define ISO_IF_ALT_0 (0x0000)
#define ISO_OUT_MAX_PACKET_SIZE (192)
#define ISO_IN_MAX_PACKET_SIZE (200)
#define APP_BUFFER_SIZE (1024 * 200)
#define RANGE_DATA_TOP2BYTES (0x0001)
#define BMREQUESTTYPEDIR (0x0080U)
#define VAULE_FFH (0xFF)
#define VALUE_FF00H (0xFF00)
void usb_paud_example(void);
#if (BSP_CFG_RTOS == 2)
void usb_apl_callback(usb_event_info_t * p_event_info, usb_hdl_t handler,
usb_onoff_t state);
#endif
static uint8_t g_paud20_snd_buf[APP_BUFFER_SIZE] = {0};
static uint8_t g_paud20_rcv_buf[ISO_OUT_MAX_PACKET_SIZE] = {0};
static uint32_t g_rcv_index = 0;
static uint32_t g_snd_index = 0;
static volatile bool g_err_flag = false;
static bool b_usb_connected = false;
static void process_usb_audio_class_request(void);
static void reset_apl_buffer_info(void);
static void handle_error(
fsp_err_t err,
char * err_str);
#if (BSP_CFG_RTOS == 2)
static volatile usb_event_info_t * p_usb_event = NULL;
#else
static usb_event_info_t event_info = {0};
static volatile usb_event_info_t * p_usb_event = &event_info;
#endif
#if (BSP_CFG_RTOS == 2)
extern QueueHandle_t g_queue;
#endif
void usb_paud_example (void)
{
#if (BSP_CFG_RTOS == 2)
BaseType_t err_queue = pdFALSE;
#endif
g_audio20_control[0].cs_id = A20_CS_ID;
g_audio20_control[0].
sam_freq = A20_SAMPLING_FREQUENCY;
g_audio20_control[0].
fu_id = A20_FU_ID_0;
g_audio20_control[0].
mute = A20_MUTE;
g_audio20_control[0].
volume = A20_SET_VOL_0;
g_audio20_control[1].cs_id = A20_CS_ID;
g_audio20_control[1].
sam_freq = A20_SAMPLING_FREQUENCY;
g_audio20_control[1].
fu_id = A20_FU_ID_1;
g_audio20_control[1].
mute = A20_MUTE;
g_audio20_control[1].
volume = A20_SET_VOL_1;
g_audio20_control_group.
p_controls = &g_audio20_control[0];
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
while (true)
{
if (true == g_err_flag)
{
handle_error(
FSP_ERR_ABORTED,
"\r\nError in sending usb event through queue\r\n");
}
#if (BSP_CFG_RTOS == 2)
err_queue = xQueueReceive(g_queue, &p_usb_event, (portMAX_DELAY));
if (pdTRUE != err_queue)
{
handle_error(
FSP_ERR_ABORTED,
"\r\nError in receiving event through queue\r\n");
}
#else
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
#endif
err = process_usb_events();
handle_error(err, "\r\nprocess_usb_events failed.\r\n");
}
}
{
switch (p_usb_event->event)
{
{
b_usb_connected = true;
break;
}
{
if ((FSP_SUCCESS == p_usb_event->status) || (FSP_ERR_USB_SIZE_SHORT == p_usb_event->status))
{
if ((g_rcv_index + p_usb_event->data_size) < APP_BUFFER_SIZE)
{
memcpy(&g_paud20_snd_buf[g_rcv_index], g_paud20_rcv_buf, p_usb_event->data_size);
}
g_rcv_index += p_usb_event->data_size;
if ((g_rcv_index + ISO_OUT_MAX_PACKET_SIZE) < APP_BUFFER_SIZE)
{
if (b_usb_connected)
{
}
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
}
}
break;
}
{
if (FSP_SUCCESS == p_usb_event->status)
{
g_snd_index += ISO_IN_MAX_PACKET_SIZE;
if (g_snd_index >= APP_BUFFER_SIZE)
{
g_snd_index = 0;
}
else
{
if (b_usb_connected)
{
&g_paud20_snd_buf[g_snd_index],
ISO_IN_MAX_PACKET_SIZE,
}
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
}
}
break;
}
{
process_usb_audio_class_request();
break;
}
{
{
{
if (ISO_OUT_IF_NO == p_usb_event->setup.request_index)
{
if (ISO_IF_ALT_1 == p_usb_event->setup.request_value)
{
if (b_usb_connected)
{
g_paud20_rcv_buf,
ISO_OUT_MAX_PACKET_SIZE,
}
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
}
if (ISO_IF_ALT_0 == p_usb_event->setup.request_value)
{
}
}
if (ISO_IN_IF_NO == p_usb_event->setup.request_index)
{
if (ISO_IF_ALT_1 == p_usb_event->setup.request_value)
{
if (b_usb_connected)
{
g_paud20_snd_buf,
ISO_IN_MAX_PACKET_SIZE,
}
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
}
if (ISO_IF_ALT_0 == p_usb_event->setup.request_value)
{
}
}
}
}
break;
}
{
b_usb_connected = false;
reset_apl_buffer_info();
break;
}
{
b_usb_connected = true;
break;
}
default:
{
break;
}
}
return err;
}
static void process_usb_audio_class_request (void)
{
uint32_t i;
uint32_t unit_id;
uint32_t freq;
uint8_t * p_range;
uint8_t volume_range[8];
uint8_t smpl_freq_range[14];
if (
USB_HOST_TO_DEV == (BMREQUESTTYPEDIR & p_usb_event->setup.request_type))
{
{
(USB_PAUD_CLOCK_SOURCE_UNIT == p_usb_event->setup.request_index))
{
unit_id = (uint32_t) (p_usb_event->setup.request_index & VALUE_FF00H);
unit_id = unit_id >> 8;
if (FSP_SUCCESS == err)
{
for (i = 0; i < g_audio20_control_group.
controls_nb; i++)
{
if (unit_id ==
{
if (0 ==
sam_freq)
{
sam_freq = freq;
}
}
}
}
else
{
APP_ERR_TRAP
}
}
{
unit_id = (uint32_t) (p_usb_event->setup.request_index & VALUE_FF00H);
unit_id = unit_id >> 8;
for (i = 0; i < g_audio20_control_group.
controls_nb; i++)
{
if (unit_id ==
{
p_usb_event->setup.request_length);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
break;
}
}
}
else
{
}
}
else
{
}
}
{
{
(USB_PAUD_CLOCK_SOURCE_UNIT == p_usb_event->setup.request_index))
{
unit_id = (uint32_t) (p_usb_event->setup.request_index & VALUE_FF00H);
unit_id = unit_id >> 8;
for (i = 0; i < g_audio20_control_group.
controls_nb; i++)
{
if (unit_id ==
{
p_usb_event->setup.request_length);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
break;
}
}
}
{
unit_id = (uint32_t) (p_usb_event->setup.request_index & VALUE_FF00H);
unit_id = unit_id >> 8;
for (i = 0; i < g_audio20_control_group.
controls_nb; i++)
{
if (unit_id ==
{
p_usb_event->setup.request_length);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
break;
}
}
}
{
unit_id = (uint32_t) (p_usb_event->setup.request_index & VALUE_FF00H);
unit_id = unit_id >> 8;
for (i = 0; i < g_audio20_control_group.
controls_nb; i++)
{
if (unit_id ==
{
p_usb_event->setup.request_length);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
break;
}
}
}
else
{
}
}
{
(USB_PAUD_CLOCK_SOURCE_UNIT == p_usb_event->setup.request_index))
{
unit_id = (uint32_t) (p_usb_event->setup.request_index & VALUE_FF00H);
unit_id = unit_id >> 8;
for (i = 0; i < g_audio20_control_group.
controls_nb; i++)
{
if (unit_id ==
{
p_range = smpl_freq_range;
*p_range++ = (uint8_t) (RANGE_DATA_TOP2BYTES & VAULE_FFH);
*p_range++ = (uint8_t) ((RANGE_DATA_TOP2BYTES >> 8) & VAULE_FFH);
*p_range++ =
(uint8_t) ((g_audio20_control_group.
p_controls[i].
sam_freq) & VAULE_FFH);
*p_range++ =
(uint8_t) ((g_audio20_control_group.
p_controls[i].
sam_freq >> 8) & VAULE_FFH);
*p_range++ =
(uint8_t) ((g_audio20_control_group.
p_controls[i].
sam_freq >> 16) & VAULE_FFH);
*p_range++ =
(uint8_t) ((g_audio20_control_group.
p_controls[i].
sam_freq >> 24) & VAULE_FFH);
*p_range++ =
sam_freq & VAULE_FFH);
*p_range++ =
(uint8_t) ((g_audio20_control_group.
p_controls[i].
sam_freq >>
8) & VAULE_FFH);
*p_range++ =
(uint8_t) ((g_audio20_control_group.
p_controls[i].
sam_freq >> 16) & VAULE_FFH);
*p_range++ =
(uint8_t) ((g_audio20_control_group.
p_controls[i].
sam_freq >> 24) & VAULE_FFH);
*p_range++ = (uint8_t) 0x00;
*p_range++ = (uint8_t) 0x00;
*p_range++ = (uint8_t) 0x00;
*p_range++ = (uint8_t) 0x00;
if (sizeof(smpl_freq_range) < p_usb_event->setup.request_length)
{
err =
}
else
{
smpl_freq_range,
p_usb_event->setup.request_length);
}
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
break;
}
}
}
{
unit_id = (uint32_t) (p_usb_event->setup.request_index & VALUE_FF00H);
unit_id = unit_id >> 8;
for (i = 0; i < g_audio20_control_group.
controls_nb; i++)
{
if (unit_id ==
{
p_range = volume_range;
*p_range++ = (uint8_t) (RANGE_DATA_TOP2BYTES & VAULE_FFH);
*p_range++ = (uint8_t) ((RANGE_DATA_TOP2BYTES >> 8) & VAULE_FFH);
*p_range++ =
volume_min &
VAULE_FFH);
*p_range++ =
(uint8_t) ((g_audio20_control_group.
p_controls[i].
volume_min >>
8) & VAULE_FFH);
*p_range++ =
volume_max &
VAULE_FFH);
*p_range++ =
(uint8_t) ((g_audio20_control_group.
p_controls[i].
volume_max >>
8) & VAULE_FFH);
if (1 <
volume_res)
{
*p_range++ =
volume_res &
VAULE_FFH);
*p_range =
(uint8_t) ((g_audio20_control_group.
p_controls[i].
volume_res >> 8) & VAULE_FFH);
}
else
{
*p_range++ = (uint8_t) (RANGE_DATA_TOP2BYTES & VAULE_FFH);
*p_range = (uint8_t) ((RANGE_DATA_TOP2BYTES >> 8) & VAULE_FFH);
}
err =
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
break;
}
}
}
else
{
}
}
else
{
}
}
else
{
}
}
static void reset_apl_buffer_info (void)
{
memset(g_paud20_snd_buf, 0, sizeof(g_paud20_snd_buf));
g_rcv_index = 0;
g_snd_index = 0;
}
#if (BSP_CFG_RTOS == 2)
void usb_apl_callback (usb_event_info_t * p_event_info, usb_hdl_t handler,
usb_onoff_t state)
{
if (pdTRUE != (xQueueSend(g_queue, (const void *) &p_event_info, (TickType_t) (RESET_VALUE))))
{
g_err_flag = true;
}
}
#endif
static void handle_error (
fsp_err_t err,
char * err_str)
{
if (FSP_SUCCESS != err)
{
{
APP_ERR_TRAP
}
APP_ERR_TRAP
}
}
A template for PAUD descriptors can be found in ra/fsp/src/r_usb_paud/r_usb_paud_descriptor.c.template. Also, please be sure to use your vendor ID.