RA Flexible Software Package Documentation  Release v6.2.0

 
USB HAUD (r_usb_haud)

Functions

fsp_err_t R_USB_HAUD_DeviceInfoGet (usb_ctrl_t *const p_api_ctrl, usb_haud_device_info_t *p_info, uint8_t device_address)
 Check audio version of connected device. More...
 
fsp_err_t R_USB_HAUD_AlternateNumberGet (usb_ctrl_t *const p_api_ctrl, usb_haud_sampling_t *p_info, uint8_t direction, uint8_t device_address)
 Get the alternate number for SET_INTERFACE. (Audio 1.0 support only) More...
 
fsp_err_t R_USB_HAUD_PipeSet (usb_ctrl_t *const p_api_ctrl, uint32_t interface_number, uint32_t alternate_number, uint8_t device_address)
 Find the interface descriptor for streaming data transfer and configure the pipe. More...
 

Detailed Description

This module provides a USB Peripheral Audio Device Class Driver (HAUD). It implements the USB HAUD Interface.

Functions

Refer to USB (r_usb_basic) for the common API (r_usb_basic) to be called from the application.

Detailed Description

Overview

The r_usb_haud module combines with the r_usb_basic module to provide USB Host Audio Device Class (HAUD) driver.

Features

The r_usb_haud module has the following key features:

Clock Configuration

Refer to the USB (r_usb_basic) module.

Pin Configuration

Refer to the USB (r_usb_basic) module.

Usage Notes

Class Requests (Host to Peripheral)

This driver notifies the application when receiving the following class requests:

Request Code Description
SET_CUR 0x01 Current setting attribute
GET_CUR 0x81 Current setting attribute

Note:

For details about each device class, please refer to Audio Class specification.

Limitations

Examples

USB HAUD Example

  1. Example code for Audio 1.0
#define AUDIO_BUFFER_SIZE (3 * 1024) + 1024
#define REQUEST_SIZE (3 * 1024)
#define FIRST_PACKET_TEST_SIZE (200) /* for Test Device (USBX-PAUD Sample Project : EK-RA6M5 Board) */
/* The first 200 bytes of the loopback data are all 0x00. */
#define READ_REQUEST_SIZE (REQUEST_SIZE + FIRST_PACKET_TEST_SIZE)
#define BMREQUESTTYPEDIR (0x0080U)
#define BMREQUESTTYPETYPE (0x0060U)
#define ALT_NUM_0 (0)
#define SAMPLING_FREQUENCY_CHANNNELS (2)
#define SAMPLING_FREQUENCY_FREQUENCY (48000)
#define SAMPLING_FREQUENCY_RESOLUTION (16)
#define SAMPLING_FREQUENCY_DATA_SIZE (3)
/******************************************************************************
* Exported global functions (to be accessed by other files)
******************************************************************************/
void usb_haud_example(void);
#if (BSP_CFG_RTOS == 2)
void usb_apl_callback(usb_event_info_t * p_event_info, usb_hdl_t cur_task, usb_onoff_t usb_state);
#endif
/******************************************************************************
* Private global variables and functions
******************************************************************************/
#if (BSP_CFG_RTOS == 2)
static volatile usb_event_info_t * p_usb_event = NULL;
extern QueueHandle_t g_usb_queue;
#else
static usb_event_info_t event_info = {0};
static volatile usb_event_info_t * p_usb_event = &event_info;
#endif
/* Private variables */
static uint8_t g_buf[8] BSP_ALIGN_VARIABLE(4) = {RESET_VALUE}; // Class request data buffer
static uint8_t g_send_buffer[AUDIO_BUFFER_SIZE] BSP_ALIGN_VARIABLE(4);
static uint8_t g_recv_buffer[AUDIO_BUFFER_SIZE] BSP_ALIGN_VARIABLE(4);
static uint8_t g_usb_dummy = RESET_VALUE; // dummy variable to send
static volatile bool g_err_flag = false; // flag bit
static uint8_t g_device_address = 0;
static uint32_t g_completed_read_transfer_length_total = 0;
static usb_haud_sampling_t g_sampling_tx;
static usb_haud_sampling_t g_sampling_rx;
/* Private functions */
static void haud_app_data_buffer_init(void);
static void haud_app_standard_request_complete(void);
static void haud_app_audio_class_request_complete(void);
static fsp_err_t haud_app_interface_set(uint32_t value, uint32_t index);
static fsp_err_t haud_app_sampling_frequency_set(uint8_t ep_address, uint32_t frequency);
static fsp_err_t haud_app_sampling_frequency_get(uint8_t ep_address);
static void handle_error(fsp_err_t err, char * err_str);
extern const usb_cfg_t g_basic0_cfg;
extern usb_instance_ctrl_t g_basic0_ctrl;
/*******************************************************************************************************************
* Function Name : usb_haud_example
* Description : Host Audio application main process
* Arguments : none
* Return value : none
*******************************************************************************************************************/
void usb_haud_example (void)
{
fsp_err_t err = FSP_SUCCESS;
#if (BSP_CFG_RTOS == 2)
BaseType_t err_queue = USB_FALSE;
#endif
fsp_pack_version_t version = {RESET_VALUE};
/* version get API for FLEX pack information */
R_FSP_VersionGet(&version);
err = R_USB_Open(&g_basic0_ctrl, &g_basic0_cfg);
/* Error Handle */
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
haud_app_data_buffer_init();
while (true)
{
/* Handle error if queue send fails*/
if (true == g_err_flag)
{
handle_error(FSP_ERR_ABORTED, "Error in sending usb event through queue");
}
#if (BSP_CFG_RTOS == 2)
/* Receive message from queue and analyzing the received message*/
err_queue = xQueueReceive(g_usb_queue, &p_usb_event, (portMAX_DELAY));
/* Handle error */
if (USB_TRUE != err_queue)
{
handle_error(FSP_ERR_ABORTED, "Error in receiving USB event message through queue");
}
#else
/* Obtain USB related events */
err = R_USB_EventGet(&event_info, &event_info.event);
/* Handle error */
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
#endif
switch (p_usb_event->event)
{
{
g_device_address = p_usb_event->device_address;
/* Get device information (Audio version) */
err = R_USB_HAUD_DeviceInfoGet(&g_basic0_ctrl, &device_info, g_device_address);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
if (USB_HAUD_PROTOCOL_IP_VERSION_01_00 == device_info.protocol)
{
g_sampling_tx.channels = SAMPLING_FREQUENCY_CHANNNELS;
g_sampling_tx.frequency = SAMPLING_FREQUENCY_FREQUENCY;
g_sampling_tx.resolution = SAMPLING_FREQUENCY_RESOLUTION;
/* Get Alternate number for Isochronous-OUT IF */
err =
R_USB_HAUD_AlternateNumberGet(&g_basic0_ctrl, &g_sampling_tx, USB_EP_DIR_OUT, g_device_address);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
/* SET_INTERFACE (Use the acquired ALT number) */
err = haud_app_interface_set(g_sampling_tx.alternate_number, g_sampling_tx.interface_number);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
}
else
{
/* Do nothing. (Audio 2.0 and later are not supported.) */
}
break;
}
{
if ((FSP_SUCCESS == p_usb_event->status) || (FSP_ERR_USB_SIZE_SHORT == p_usb_event->status))
{
g_completed_read_transfer_length_total += p_usb_event->data_size;
if (READ_REQUEST_SIZE > g_completed_read_transfer_length_total)
{
err = R_USB_Read(&g_basic0_ctrl,
g_recv_buffer + g_completed_read_transfer_length_total,
g_sampling_rx.max_packet_size,
g_device_address);
/* Handle Error */
if (FSP_SUCCESS != err)
{
handle_error(err, "**R_USB_Read API FAILED**");
}
}
else
{
if (0 == memcmp(g_send_buffer, g_recv_buffer + FIRST_PACKET_TEST_SIZE, REQUEST_SIZE))
{
/* SET_INTERFACE (ALT number : 0) */
err = haud_app_interface_set(ALT_NUM_0, g_sampling_rx.interface_number);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
}
else
{
APP_ERR_TRAP
}
}
}
else
{
APP_ERR_TRAP
}
break;
}
{
if (FSP_SUCCESS == p_usb_event->status)
{
/* SET_INTERFACE (ALT number : 0) */
err = haud_app_interface_set(ALT_NUM_0, g_sampling_tx.interface_number);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
}
else
{
APP_ERR_TRAP
}
break;
}
{
switch (BMREQUESTTYPETYPE & p_usb_event->setup.request_type)
{
{
haud_app_standard_request_complete();
break;
}
case USB_CLASS:
{
haud_app_audio_class_request_complete();
break;
}
}
break;
}
{
memset(&g_sampling_tx, 0, sizeof(g_sampling_tx));
memset(&g_sampling_rx, 0, sizeof(g_sampling_rx));
g_device_address = 0;
g_completed_read_transfer_length_total = 0;
break;
}
default:
{
/* No operation to do */
break;
}
}
}
} /* End of function usb_haud_example */
/*******************************************************************************************************************
* Function Name : haud_app_data_buffer_init
* Description : Initializes test write data.
* Arguments : none
* Return value : none
*******************************************************************************************************************/
static void haud_app_data_buffer_init (void)
{
uint32_t i = 0;
uint32_t j = 0;
/* Set data to the send buffer. */
for ( ; i < AUDIO_BUFFER_SIZE; i++)
{
if (i % (VALUE_FFH + 1))
{
(g_send_buffer)[i] = (uint8_t) i;
}
else
{
(g_send_buffer)[i] = (uint8_t) j;
j++;
}
}
} /* End of function haud_app_data_buffer_init */
/*******************************************************************************************************************
* Function Name : haud_app_standard_request_complete
* Description : Standard request (such as SET_INTERFACE) completion event processing.
* Arguments : none
* Return value : none
*******************************************************************************************************************/
static void haud_app_standard_request_complete (void)
{
fsp_err_t err = FSP_SUCCESS;
if (USB_SET_INTERFACE == (p_usb_event->setup.request_type & USB_BREQUEST))
{
if ((g_sampling_tx.interface_number == p_usb_event->setup.request_index) &&
(g_sampling_tx.alternate_number == p_usb_event->setup.request_value))
{
g_sampling_tx.alternate_setting = USB_TRUE;
err = R_USB_HAUD_PipeSet(&g_basic0_ctrl,
g_sampling_tx.interface_number,
g_sampling_tx.alternate_number,
g_device_address);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
g_sampling_tx.frequency_setting = USB_TRUE;
/* Check FormatTypeI::bSamFreqType@7, tSamFreq@8, tSamFreq@11. */
/* If there is only one frequency, no need to set. */
if ((g_sampling_tx.p_sampling_descriptor[7] == 1) ||
((g_sampling_tx.p_sampling_descriptor[7] == 0) &&
(g_sampling_tx.
p_sampling_descriptor[8] == g_sampling_tx.p_sampling_descriptor[11]) &&
(g_sampling_tx.
p_sampling_descriptor[9] == g_sampling_tx.p_sampling_descriptor[12]) &&
(g_sampling_tx.
p_sampling_descriptor[10] == g_sampling_tx.p_sampling_descriptor[13])))
{
g_sampling_tx.frequency_setting = USB_FALSE;
}
if (g_sampling_tx.frequency_setting)
{
/* Send SET_CUR requests to set frequency. */
err = haud_app_sampling_frequency_set(g_sampling_tx.endpoint_address, g_sampling_tx.frequency);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
}
}
else if ((g_sampling_tx.interface_number == p_usb_event->setup.request_index) &&
(ALT_NUM_0 == p_usb_event->setup.request_value))
{
g_sampling_tx.alternate_setting = USB_FALSE;
g_sampling_rx.channels = SAMPLING_FREQUENCY_CHANNNELS;
g_sampling_rx.frequency = SAMPLING_FREQUENCY_FREQUENCY;
g_sampling_rx.resolution = SAMPLING_FREQUENCY_RESOLUTION;
/* Get Alternate number for Isochronous-IN IF */
err = R_USB_HAUD_AlternateNumberGet(&g_basic0_ctrl, &g_sampling_rx, USB_EP_DIR_IN, g_device_address);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
/* SET_INTERFACE (Use the acquired ALT number) */
err = haud_app_interface_set(g_sampling_rx.alternate_number, g_sampling_rx.interface_number);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
}
else if ((g_sampling_rx.interface_number == p_usb_event->setup.request_index) &&
(g_sampling_rx.alternate_number == p_usb_event->setup.request_value))
{
g_sampling_rx.alternate_setting = USB_TRUE;
err = R_USB_HAUD_PipeSet(&g_basic0_ctrl,
g_sampling_rx.interface_number,
g_sampling_rx.alternate_number,
g_device_address);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
g_sampling_rx.frequency_setting = USB_TRUE;
/* Check FormatTypeI::bSamFreqType@7, tSamFreq@8, tSamFreq@11. */
/* If there is only one frequency, no need to set. */
if ((g_sampling_rx.p_sampling_descriptor[7] == 1) ||
((g_sampling_rx.p_sampling_descriptor[7] == 0) &&
(g_sampling_rx.
p_sampling_descriptor[8] == g_sampling_rx.p_sampling_descriptor[11]) &&
(g_sampling_rx.
p_sampling_descriptor[9] == g_sampling_rx.p_sampling_descriptor[12]) &&
(g_sampling_rx.
p_sampling_descriptor[10] == g_sampling_rx.p_sampling_descriptor[13])))
{
g_sampling_rx.frequency_setting = USB_FALSE;
}
if (g_sampling_rx.frequency_setting)
{
/* Send SET_CUR requests to set frequency. */
err = haud_app_sampling_frequency_set(g_sampling_rx.endpoint_address, g_sampling_rx.frequency);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
}
}
else if ((g_sampling_rx.interface_number == p_usb_event->setup.request_index) &&
(ALT_NUM_0 == p_usb_event->setup.request_value))
{
g_sampling_rx.alternate_setting = USB_FALSE;
}
else
{
APP_ERR_TRAP
}
}
} /* End of function haud_app_standard_request_complete */
/*******************************************************************************************************************
* Function Name : haud_app_audio_class_request_complete
* Description : Audio class request completion event processing.
* Arguments : none
* Return value : none
*******************************************************************************************************************/
static void haud_app_audio_class_request_complete (void)
{
uint32_t value;
fsp_err_t err = FSP_SUCCESS;
/* SET_CUR (Isochronous-OUT IF's EP) completed */
if ((USB_HAUD_AUDIO10_SET_CUR == (p_usb_event->setup.request_type & USB_BREQUEST)) &&
(g_sampling_tx.endpoint_address == p_usb_event->setup.request_index))
{
/* GET_CUR Request (Check whether the sampling frequency specified by SET_CUR has been set on the device.) */
err = haud_app_sampling_frequency_get(g_sampling_tx.endpoint_address);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
}
/* SET_CUR (Isochronous-IN IF's EP) completed */
else if ((USB_HAUD_AUDIO10_SET_CUR == (p_usb_event->setup.request_type & USB_BREQUEST)) &&
(g_sampling_rx.endpoint_address == p_usb_event->setup.request_index))
{
/* GET_CUR Request (Check whether the sampling frequency specified by SET_CUR has been set on the device.) */
err = haud_app_sampling_frequency_get(g_sampling_rx.endpoint_address);
if (FSP_SUCCESS != err)
{
APP_ERR_TRAP
}
}
/* GET_CUR (Isochronous-OUT IF's EP) completed */
else if ((USB_HAUD_AUDIO10_GET_CUR == (p_usb_event->setup.request_type & USB_BREQUEST)) &&
(g_sampling_tx.endpoint_address == p_usb_event->setup.request_index))
{
/* The fourth byte has no data so it is cleared. */
g_buf[3] = 0;
value = (ULONG) g_buf[0];
value |= (ULONG) g_buf[1] << 8;
value |= (ULONG) g_buf[2] << 16;
value |= (ULONG) g_buf[3] << 24;
if (value != g_sampling_tx.frequency)
{
/* Sampling frequency requested is not set to device. */
APP_ERR_TRAP
}
/* Data Write (Isochronous-OUT) */
err =
R_USB_Write(&g_basic0_ctrl, (uint8_t *) g_send_buffer, REQUEST_SIZE, g_device_address);
if (FSP_SUCCESS != err)
{
handle_error(err, "**R_USB_Write API FAILED**");
}
}
/* GET_CUR (Isochronous-IN IF's EP) completed */
else if ((USB_HAUD_AUDIO10_GET_CUR == (p_usb_event->setup.request_type & USB_BREQUEST)) &&
(g_sampling_rx.endpoint_address == p_usb_event->setup.request_index))
{
/* The fourth byte has no data so it is cleared. */
g_buf[3] = 0;
value = (ULONG) g_buf[0];
value |= (ULONG) g_buf[1] << 8;
value |= (ULONG) g_buf[2] << 16;
value |= (ULONG) g_buf[3] << 24;
if (value != g_sampling_rx.frequency)
{
/* Sampling frequency requested is not set to device. */
APP_ERR_TRAP
}
/* Data Read (Isochronous-IN) */
err = R_USB_Read(&g_basic0_ctrl, g_recv_buffer, g_sampling_rx.max_packet_size, g_device_address);
/* Handle Error */
if (FSP_SUCCESS != err)
{
handle_error(err, "**R_USB_Read API FAILED**");
}
}
else
{
APP_ERR_TRAP
}
} /* End of function haud_app_audio_class_request_complete */
/*******************************************************************************************************************
* Function Name : haud_app_interface_set
* Description : This function does a SET_INTERFACE with the specified Alternate number and interface number.
* Arguments : uint32_t value : Alternate number
* : uint32_t index : Interface number
* Return value : fsp_err_t err : Result of a control transfer request
*******************************************************************************************************************/
static fsp_err_t haud_app_interface_set (uint32_t value, uint32_t index)
{
fsp_err_t err = FSP_SUCCESS;
usb_setup_t setup;
setup.request_value = (uint16_t) value;
setup.request_index = (uint16_t) index;
setup.request_length = 0;
err = R_USB_HostControlTransfer(&g_basic0_ctrl, &setup, &g_usb_dummy, g_device_address);
return err;
} /* End of function haud_app_interface_set */
/*******************************************************************************************************************
* Function Name : haud_app_sampling_frequency_set
* Description : This function sets the sampling frequency on the device using the SET_CUR request.
* Arguments : uint8_t ep_address : End Point Address
* : uint32_t frequency : Sampling Furequency
* Return value : fsp_err_t err : Result of a control transfer request
*******************************************************************************************************************/
static fsp_err_t haud_app_sampling_frequency_set (uint8_t ep_address, uint32_t frequency)
{
fsp_err_t err = FSP_SUCCESS;
usb_setup_t setup;
setup.request_type = USB_HAUD_AUDIO10_SET_CUR | USB_HOST_TO_DEV | USB_CLASS | USB_ENDPOINT;
setup.request_value = USB_HAUD_AUDIO10_EP_SAMPLING_FREQ_CONTROL << 8;
setup.request_index = (uint16_t) ep_address;
setup.request_length = SAMPLING_FREQUENCY_DATA_SIZE;
g_buf[0] = (uint8_t) frequency;
g_buf[1] = (uint8_t) (frequency >> 8);
g_buf[2] = (uint8_t) (frequency >> 16);
g_buf[3] = 0;
/* Request Control transfer */
err = R_USB_HostControlTransfer(&g_basic0_ctrl, &setup, g_buf, g_device_address);
return err;
} /* End of function haud_app_sampling_frequency_set */
/*******************************************************************************************************************
* Function Name : haud_app_sampling_frequency_get
* Description : This function uses a GET_CUR request to get the sampling frequency of the device.
* Arguments : uint8_t ep_address : End Point Address
* Return value : fsp_err_t err : Result of a control transfer request
*******************************************************************************************************************/
static fsp_err_t haud_app_sampling_frequency_get (uint8_t ep_address)
{
fsp_err_t err = FSP_SUCCESS;
usb_setup_t setup;
setup.request_type = USB_HAUD_AUDIO10_GET_CUR | USB_DEV_TO_HOST | USB_CLASS | USB_ENDPOINT;
setup.request_value = USB_HAUD_AUDIO10_EP_SAMPLING_FREQ_CONTROL << 8;
setup.request_index = ep_address;
setup.request_length = SAMPLING_FREQUENCY_DATA_SIZE;
err = R_USB_HostControlTransfer(&g_basic0_ctrl, &setup, g_buf, g_device_address);
return err;
} /* End of function haud_app_sampling_frequency_get */
/*******************************************************************************************************************
* Function Name : handle_error
* Description : Print and traps error
* Arguments : fsp_err_t err
* : char * err_str
* Return value : none
*******************************************************************************************************************/
static void handle_error (fsp_err_t err, char * err_str)
{
fsp_err_t error = FSP_SUCCESS;
/* close opened USB module */
error = R_USB_Close(&g_basic0_ctrl);
/* Handle error */
if (FSP_SUCCESS != error)
{
APP_ERR_TRAP
}
} /* End of function handle_error() */
#if (BSP_CFG_RTOS == 2)
/*******************************************************************************************************************
* Function Name : usb_apl_callback
* Description : This function is callback for USB
* Arguments : usb_event_info_t *p_event_info
* : usb_hdl_t handler
* : usb_onoff_t usb_state
* Return value : none
*******************************************************************************************************************/
void usb_apl_callback (usb_event_info_t * p_event_info, usb_hdl_t handler, usb_onoff_t usb_state)
{
/* Send event received to queue */
if (USB_TRUE != (xQueueSend(g_usb_queue, (const void *) &p_event_info, (TickType_t) (NO_WAIT_TIME))))
{
g_err_flag = true;
}
} /* End of function usb_rtos_callback */
#endif

Function Documentation

◆ R_USB_HAUD_DeviceInfoGet()

fsp_err_t R_USB_HAUD_DeviceInfoGet ( usb_ctrl_t *const  p_api_ctrl,
usb_haud_device_info_t p_info,
uint8_t  device_address 
)

Check audio version of connected device.

Return values
FSP_SUCCESSSuccessfully completed.
FSP_ERR_USB_FAILEDThe function could not be completed successfully.
FSP_ERR_ASSERTIONParameter Null pointer error.
FSP_ERR_USB_PARAMETERParameter error.
Note
(1). Interrupt function.
(2). Callback function ( for RTOS ).

◆ R_USB_HAUD_AlternateNumberGet()

fsp_err_t R_USB_HAUD_AlternateNumberGet ( usb_ctrl_t *const  p_api_ctrl,
usb_haud_sampling_t p_info,
uint8_t  direction,
uint8_t  device_address 
)

Get the alternate number for SET_INTERFACE. (Audio 1.0 support only)

Return values
FSP_SUCCESSSuccessfully completed.
FSP_ERR_USB_FAILEDThe function could not be completed successfully.
FSP_ERR_ASSERTIONParameter Null pointer error.
FSP_ERR_USB_PARAMETERParameter error.
Note
(1). Interrupt function.
(2). Callback function ( for RTOS ).

◆ R_USB_HAUD_PipeSet()

fsp_err_t R_USB_HAUD_PipeSet ( usb_ctrl_t *const  p_api_ctrl,
uint32_t  interface_number,
uint32_t  alternate_number,
uint8_t  device_address 
)

Find the interface descriptor for streaming data transfer and configure the pipe.

Return values
FSP_SUCCESSSuccessfully completed.
FSP_ERR_USB_FAILEDThe function could not be completed successfully.
FSP_ERR_ASSERTIONParameter Null pointer error.
FSP_ERR_USB_PARAMETERParameter error.
Note
(1). Interrupt function.
(2). Callback function ( for RTOS ).