USB composite device works as a USB Peripheral by combining two peripheral device classes and r_usb_basic module.
This USB driver supports the following composite devices:
The following shows FSP configuration procedure for USB composite device.
Please determine by the member "pipe" in "usb_event_info" structure when getting PCDC channel number which the write event is completed in PCDC + PCDC.
Don't refer to the member "type" in "usb_event_info" structure.
Templates for composite device descriptors can be found in ra/fsp/src/r_usb_composite folder. Also, please be sure to use your vendor ID.
void main_task (void)
{
#if (BSP_CFG_RTOS == 2)
usb_event_info_t * p_mess;
#endif
usb_event_info_t usb_event;
uint8_t * p_idle_value;
uint8_t sw_data;
usb_info_t info;
uint8_t send_data[16] BSP_ALIGN_VARIABLE(4);
uint8_t req_comp_flag = 0;
uint8_t count = 0;
g_usb_on_usb.
open(&g_basic0_ctrl, &g_basic0_cfg);
set_key_data(g_buf_phid);
while (1)
{
#if (BSP_CFG_RTOS == 2)
USB_APL_RCV_MSG(USB_APL_MBX, (usb_msg_t **) &p_mess);
usb_event = *p_mess;
event = usb_event.event;
#else
#endif
switch (event)
{
{
g_status = NO_WRITING;
break;
}
{
{
}
{
if (DATA_WRITING == g_status)
{
g_status = ZERO_WRITING;
}
else if (g_status == ZERO_WRITING)
{
g_status = NO_WRITING;
}
}
break;
}
{
{
if (req_comp_flag == 1)
{
if (g_status == NO_WRITING)
{
count++;
g_status = DATA_WRITING;
}
}
}
break;
}
{
{
}
{
}
else if (USB_SET_REPORT == (usb_event.setup.request_type &
USB_BREQUEST))
{
}
{
if (USB_GET_REPORT_DESCRIPTOR == usb_event.setup.request_value)
{
(uint8_t *) g_apl_report,
USB_RECEIVE_REPORT_DESCRIPTOR);
}
else if (USB_GET_HID_DESCRIPTOR == usb_event.setup.request_value)
{
for (uint8_t i = 0; i < USB_RECEIVE_HID_DESCRIPTOR; i++)
{
send_data[i] = g_apl_configuration[84 + i];
}
}
else
{
}
}
else if (USB_SET_IDLE == (usb_event.setup.request_type &
USB_BREQUEST))
{
p_idle_value = (uint8_t *) &usb_event.setup.request_value;
g_idle = p_idle_value[1];
}
else if (USB_GET_IDLE == (usb_event.setup.request_type &
USB_BREQUEST))
{
}
else if (USB_SET_PROTOCOL == (usb_event.setup.request_type &
USB_BREQUEST))
{
}
else if (USB_GET_PROTOCOL == (usb_event.setup.request_type &
USB_BREQUEST))
{
}
else
{
}
break;
}
{
if (USB_SET_IDLE == (usb_event.setup.request_type &
USB_BREQUEST))
{
p_idle_value = (uint8_t *) &usb_event.setup.request_value;
g_idle = p_idle_value[1];
}
else if (USB_SET_PROTOCOL == (usb_event.setup.request_type &
USB_BREQUEST))
{
}
else
{
req_comp_flag = 1;
}
break;
}
{
break;
}
default:
{
break;
}
}
}
}
void set_key_data (uint8_t * p_buf)
{
static uint8_t key_data;
key_data = KBD_CODE_A;
*(p_buf + 2) = key_data;
}
#if (BSP_CFG_RTOS == 2)
usb_er_t usb_apl_rec_msg (uint8_t id, usb_msg_t ** mess, usb_tm_t tm)
{
BaseType_t err;
QueueHandle_t handle;
usb_er_t result;
(void) tm;
if (NULL == mess)
{
return USB_APL_ERROR;
}
handle = (*(g_apl_mbx_table[id]));
*mess = NULL;
err = xQueueReceive(handle, (void *) mess, (portMAX_DELAY));
if ((pdTRUE == err) && (NULL != (*mess)))
{
result = USB_APL_OK;
}
else
{
result = USB_APL_ERROR;
}
return result;
}
usb_er_t usb_apl_snd_msg (uint8_t id, usb_msg_t * mess)
{
BaseType_t err;
QueueHandle_t handle;
usb_er_t result;
if (NULL == mess)
{
return USB_APL_ERROR;
}
handle = (*(g_apl_mbx_table[id]));
err = xQueueSend(handle, (const void *) &mess, (TickType_t) (0));
if (pdTRUE == err)
{
result = USB_APL_OK;
}
else
{
result = USB_APL_ERROR;
}
return result;
}
#endif
#include "r_usb_basic.h"
#include "r_usb_pcdc_api.h"
#include "r_usb_pcdc_cfg.h"
#define DATA_LEN 2048
#define RESET_VALUE 0
#define INT_EVT_TSK_STACK_SIZE 1024
#define INT_EVT_TSK_PRI 2
#define BUF_SIZE (2048)
#define REQ_SIZE (20)
#define USB_VALUE_FF (0xFFU)
#define USB_APL_MXPS (64U)
#define START_PIPE (USB_PIPE1)
#define END_PIPE (USB_PIPE9 + 1)
#define USB_SET_VENDOR_NO_DATA (0x0000U)
#define USB_SET_VENDOR (0x0100U)
#define USB_GET_VENDOR (0x0200U)
#define SET_VENDOR_NO_DATA (USB_SET_VENDOR_NO_DATA | USB_HOST_TO_DEV | USB_VENDOR | USB_INTERFACE)
#define SET_VENDOR (USB_SET_VENDOR | USB_HOST_TO_DEV | USB_VENDOR | USB_INTERFACE)
#define GET_VENDOR (USB_GET_VENDOR | USB_DEV_TO_HOST | USB_VENDOR | USB_INTERFACE)
#define DELAY (10U)
#define USB_STATUS_VENDOR_INTIN_TEST ((usb_status_t) 0x01)
#define USB_STATUS_VENDOR_INTOUT_TEST ((usb_status_t) 0x02)
#define USB_STATUS_COM_IN_TEST ((usb_status_t) 0x03)
#define USB_STATUS_RE_INIT_TEST ((usb_status_t) 0x04)
#define HS_MAX_PACKET_SIZE (512)
#define FS_MAX_PACKET_SIZE (64)
#define VALUE_A1H (0xA1)
#define LINE_CODING_LENGTH (0x07U)
static uint8_t g_cdc_buf[BUF_SIZE] = {RESET_VALUE};
static uint8_t g_vnd_buf[BUF_SIZE] = {RESET_VALUE};
static uint8_t g_request_buf[REQ_SIZE] = {RESET_VALUE};
static uint8_t g_bulk_in_pipe = RESET_VALUE;
static uint8_t g_bulk_out_pipe = RESET_VALUE;
static uint8_t g_interrupt_in_pipe = RESET_VALUE;
static uint8_t g_interrupt_out_pipe = RESET_VALUE;
static uint16_t g_max_packet_size = USB_APL_MXPS;
static volatile usb_event_info_t * p_usb_event = NULL;
static volatile bool g_err_flag = false;
static bool b_usb_attach = false;
#if (BSP_CFG_RTOS == 2)
static TaskHandle_t g_app_interrupt_event_notify_tsk_hdl;
#endif
static uint32_t g_interrupt_in_test_flag = 0;
static uint32_t g_interrupt_out_test_flag = 0;
static uint32_t g_interrupt_out_times = 0;
static uint32_t g_interrupt_com_event = 0;
static uint8_t g_interrupt_in_com_data[8] = {VALUE_A1H, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static uint32_t g_test_reinit_flag = 0;
#if (BSP_CFG_RTOS == 2)
static usb_event_info_t g_event_info2;
static usb_event_info_t * g_p_event_info2;
#else
static usb_event_info_t g_usb_event;
static uint32_t g_event2;
#endif
static fsp_err_t process_usb_events_for_interrupt(
void);
static fsp_err_t usb_configured_event_process(
void);
static fsp_err_t buffer_check(uint32_t length);
void usb_composite_thread_entry(void * pvParameters);
#if (BSP_CFG_RTOS == 2)
void usb_app_interrupt_event_task (void * pvParameters)
{
while (1)
{
if (1 == g_interrupt_in_test_flag)
{
g_interrupt_in_test_flag = 0;
g_event_info2.event = USB_STATUS_VENDOR_INTIN_TEST;
g_p_event_info2 = &g_event_info2;
if (pdTRUE != (xQueueSend(g_event_queue, (const void *) &g_p_event_info2, (TickType_t) (RESET_VALUE))))
{
g_err_flag = true;
}
}
if (1 == g_interrupt_out_test_flag)
{
g_interrupt_out_test_flag = 0;
g_event_info2.event = USB_STATUS_VENDOR_INTOUT_TEST;
g_p_event_info2 = &g_event_info2;
if (pdTRUE != (xQueueSend(g_event_queue, (const void *) &g_p_event_info2, (TickType_t) (RESET_VALUE))))
{
g_err_flag = true;
}
}
if (0 != g_interrupt_com_event)
{
g_interrupt_com_event = 0;
g_event_info2.event = USB_STATUS_COM_IN_TEST;
g_p_event_info2 = &g_event_info2;
if (pdTRUE != (xQueueSend(g_event_queue, (const void *) &g_p_event_info2, (TickType_t) (RESET_VALUE))))
{
g_err_flag = true;
}
}
if (0 != g_test_reinit_flag)
{
g_test_reinit_flag = 0;
g_event_info2.event = USB_STATUS_RE_INIT_TEST;
g_p_event_info2 = &g_event_info2;
if (pdTRUE != (xQueueSend(g_event_queue, (const void *) &g_p_event_info2, (TickType_t) (RESET_VALUE))))
{
g_err_flag = true;
}
}
vTaskDelay(100);
}
}
#endif
void usb_composite_thread_entry (void * pvParameters)
{
#if (BSP_CFG_RTOS == 2)
BaseType_t err_queue = pdFALSE;
BaseType_t err_task = pdFALSE;
#endif
{
g_max_packet_size = FS_MAX_PACKET_SIZE;
}
else
{
g_max_packet_size = HS_MAX_PACKET_SIZE;
}
#if (BSP_CFG_RTOS == 2)
err_task = xTaskCreate((TaskFunction_t) usb_app_interrupt_event_task,
"INT_EVT_TSK",
INT_EVT_TSK_STACK_SIZE,
NULL,
INT_EVT_TSK_PRI,
&g_app_interrupt_event_notify_tsk_hdl);
if (pdPASS != err_task)
{
return;
}
#endif
while (true)
{
if (true == g_err_flag)
{
}
#if (BSP_CFG_RTOS == 2)
err_queue = xQueueReceive(g_event_queue, &p_usb_event, (portMAX_DELAY));
if (pdTRUE != err_queue)
{
}
if (pdTRUE == err_queue)
{
if (p_usb_event == &g_event_info2)
{
err = process_usb_events_for_interrupt();
handle_error(err);
}
else
{
err = process_usb_events();
handle_error(err);
}
}
#else
{
if (1 == g_interrupt_in_test_flag)
{
g_interrupt_in_test_flag = 0;
g_event2 = USB_STATUS_VENDOR_INTIN_TEST;
err = process_usb_events_for_interrupt();
}
else if (1 == g_interrupt_out_test_flag)
{
g_interrupt_out_test_flag = 0;
g_event2 = USB_STATUS_VENDOR_INTOUT_TEST;
err = process_usb_events_for_interrupt();
}
else if (0 != g_interrupt_com_event)
{
g_interrupt_com_event = 0;
g_event2 = USB_STATUS_COM_IN_TEST;
err = process_usb_events_for_interrupt();
}
else if (0 != g_test_reinit_flag)
{
g_test_reinit_flag = 0;
g_event2 = USB_STATUS_RE_INIT_TEST;
err = process_usb_events_for_interrupt();
}
else
{
err = process_usb_events();
}
}
else
{
p_usb_event = &g_usb_event;
err = process_usb_events();
}
handle_error(err);
#endif
}
}
{
#if (BSP_CFG_RTOS == 2)
switch (p_usb_event->event)
#else
switch (g_event)
#endif
{
{
usb_configured_event_process();
memset(g_vnd_buf, RESET_VALUE, BUF_SIZE);
err =
R_USB_PipeRead(&g_basic0_ctrl, &g_vnd_buf[RESET_VALUE], BUF_SIZE, g_bulk_out_pipe);
break;
}
{
if (b_usb_attach)
{
if ((USB_CFG_PCDC_BULK_IN == p_usb_event->pipe) && (FSP_ERR_USB_FAILED != p_usb_event->status))
{
}
if ((g_bulk_in_pipe == p_usb_event->pipe) && (FSP_ERR_USB_FAILED != p_usb_event->status))
{
memset(g_vnd_buf, RESET_VALUE, BUF_SIZE);
err =
R_USB_PipeRead(&g_basic0_ctrl, &g_vnd_buf[RESET_VALUE], BUF_SIZE, g_bulk_out_pipe);
}
}
else
{
}
break;
}
{
if (b_usb_attach)
{
if ((USB_CFG_PCDC_BULK_OUT == p_usb_event->pipe) && (FSP_ERR_USB_FAILED != p_usb_event->status))
{
}
if ((g_bulk_out_pipe == p_usb_event->pipe) && (FSP_ERR_USB_FAILED != p_usb_event->status))
{
err = buffer_check(p_usb_event->data_size);
if (FSP_SUCCESS == err)
{
R_USB_PipeWrite(&g_basic0_ctrl, &g_vnd_buf[RESET_VALUE], p_usb_event->data_size,
g_bulk_in_pipe);
}
else
{
return FSP_ERR_USB_FAILED;
}
}
}
else
{
}
break;
}
{
err = usb_status_request();
break;
}
{
break;
}
{
b_usb_attach = false;
memset(g_cdc_buf, RESET_VALUE, sizeof(g_cdc_buf));
memset(g_vnd_buf, RESET_VALUE, sizeof(g_vnd_buf));
break;
}
{
b_usb_attach = true;
break;
}
default:
{
break;
}
}
return err;
}
static fsp_err_t process_usb_events_for_interrupt (
void)
{
uint8_t pipe = RESET_VALUE;
#if (BSP_CFG_RTOS == 2)
switch (p_usb_event->event)
#else
switch (g_event2)
#endif
{
case USB_STATUS_VENDOR_INTIN_TEST:
{
pipe = g_interrupt_in_pipe;
err =
R_USB_PipeWrite(&g_basic0_ctrl, (uint8_t *)
"interrupt-in-test", strlen(
"interrupt-in-test"), pipe);
break;
}
case USB_STATUS_VENDOR_INTOUT_TEST:
{
pipe = g_interrupt_out_pipe;
err =
R_USB_PipeRead(&g_basic0_ctrl, &g_vnd_buf[RESET_VALUE], (BUF_SIZE), pipe);
if (FSP_SUCCESS == err)
{
g_interrupt_out_times++;
}
break;
}
case USB_STATUS_COM_IN_TEST:
{
pipe = USB_CFG_PCDC_INT_IN;
err =
R_USB_PipeWrite(&g_basic0_ctrl, g_interrupt_in_com_data,
sizeof(g_interrupt_in_com_data), pipe);
break;
}
case USB_STATUS_RE_INIT_TEST:
{
g_usb_on_usb.
close(&g_basic0_ctrl);
g_usb_on_usb.
open(&g_basic0_ctrl, &g_basic0_cfg);
break;
}
default:
{
break;
}
}
return err;
}
static fsp_err_t usb_configured_event_process (
void)
{
uint16_t used_pipe = RESET_VALUE;
usb_pipe_t pipe_info = {RESET_VALUE};
uint8_t pipe = RESET_VALUE;
if (FSP_SUCCESS == err)
{
for (pipe = START_PIPE; pipe < END_PIPE; pipe++)
{
if ((used_pipe & (START_PIPE << pipe)) != RESET_VALUE)
{
{
{
if (pipe != USB_CFG_PCDC_BULK_OUT)
{
g_bulk_out_pipe = pipe;
}
}
{
g_interrupt_out_pipe = pipe;
}
else
{
}
}
else
{
{
if (pipe != USB_CFG_PCDC_BULK_IN)
{
g_bulk_in_pipe = pipe;
}
}
{
if (pipe != USB_CFG_PCDC_INT_IN)
{
g_interrupt_in_pipe = pipe;
}
}
else
{
}
}
}
else
{
}
}
}
return err;
}
{
uint16_t request_length = RESET_VALUE;
{
}
{
}
{
}
else if (USB_SET_VENDOR_NO_DATA == (p_usb_event->setup.request_type &
USB_BREQUEST))
{
}
else if (USB_SET_VENDOR == (p_usb_event->setup.request_type &
USB_BREQUEST))
{
request_length = p_usb_event->setup.request_length;
}
else if (USB_GET_VENDOR == (p_usb_event->setup.request_type &
USB_BREQUEST))
{
request_length = p_usb_event->setup.request_length;
}
else
{
}
return err;
}
#if (BSP_CFG_RTOS == 2)
void usb_composite_callback (usb_event_info_t * p_event_info, usb_hdl_t handler,
usb_onoff_t on_off)
{
if (pdTRUE != (xQueueSend(g_event_queue, (const void *) &p_event_info, (TickType_t) (RESET_VALUE))))
{
g_err_flag = true;
}
}
#endif
{
if (FSP_SUCCESS != err)
{
}
}
static fsp_err_t buffer_check (uint32_t length)
{
for (uint16_t cnt = RESET_VALUE; cnt < (uint16_t) length; cnt++)
{
if ((uint8_t) (cnt & USB_VALUE_FF) != g_vnd_buf[cnt])
{
}
}
return FSP_SUCCESS;
}