RA Flexible Software Package Documentation  Release v5.2.0

 
USB PHID (r_usb_phid)

This module is USB Peripheral Human Interface Device Class Driver (PHID). It implements the USB PHID 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_phid module combines with the r_usb_basic module to provide a USB Peripheral Human Interface Device Class (PHID) driver. The PHID driver conforms to the USB Human Interface Device class specifications and implements communication with a HID host.

Features

The r_usb_phid module has the following functions:

Note
This driver is not guaranteed to provide USB HID operation in all scenarios. The developer must verify correct operation when connected to the targeted USB hosts.

Configuration

Build Time Configurations for r_usb_phid

The following build time configurations are defined in fsp_cfg/r_usb_phid_cfg.h:

ConfigurationOptionsDefaultDescription
Interrupt In Pipe
  • USB PIPE6
  • USB PIPE7
  • USB PIPE8
  • USB PIPE9
USB PIPE6 Select the pipe number for input interrupt events.
Interrupt Out Pipe
  • USB PIPE6
  • USB PIPE7
  • USB PIPE8
  • USB PIPE9
USB PIPE7 Select the pipe number for output interrupt events.

Configurations for Connectivity > USB PHID (r_usb_phid)

This module can be added to the Stacks tab via New Stack > Connectivity > USB PHID (r_usb_phid).

ConfigurationOptionsDefaultDescription
NameName must be a valid C symbolg_phid0 Module name.

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
Get_Report 0x01 Receives a report from the HID host
Set_Report 0x09 Sends a report to the HID host
Get_Idle 0x02 Receives a duration (time) from the HID host
Set_Idle 0x0A Sends a duration (time) to the HID host
Get_Protocol 0x03 Reads a protocol from the HID host
Set_Protocol 0x0B Sends a protocol to the HID host
Get_Descriptor 0x06 Transmits a report or HID descriptor

The data format of supported class requests is described below:

bmRequestType bRequest wValue wIndex wLength Data
0xA1 GET_REPORT (0x01) ReportType & ReportID Interface ReportLength Report
0x21 SET_REPORT (0x09) ReportType & ReportID Interface ReportLength Report
0xA1 GET_IDLE (0x02) 0 & ReportID Interface 1 Idle rate
0x21 SET_IDLE (0x0A) Duration & ReportID Interface 0 Idle rate
0xA1 GET_PROTOCOL (0x03) 0 Interface 0 0 (Boot) or 1 (Report)
0x21 SET_PROTOCOL (0x0B) 0 (Boot) or 1 (Report) Interface 0 Not applicable

Limitations

Examples

r_usb_phid_operating_environment.svg
Example Operating Environment

USB PHID Example

This is a minimal example for implementing PHID in a non-RTOS application.

r_usb_phid_task_flow_sample.svg
Main Loop processing for non-RTOS example

This is a minimal example for implementing PHID in an RTOS application.

r_usb_phid_task_flow_sample_rtos.svg
Main Loop processing for RTOS example
#define USB_RECEIVE_REPORT_DESCRIPTOR (76)
#define USB_RECEIVE_HID_DESCRIPTOR (9)
#define USB_WAIT_1000MS (1000)
#define SW_ACTIVE 0
#define SW R_PFS->PORT[0].PIN[8].PmnPFS_b.PIDR
#define SW_PDR R_PFS->PORT[0].PIN[8].PmnPFS_b.PDR
#define SW_PMR R_PFS->PORT[0].PIN[8].PmnPFS_b.PMR
static uint8_t g_buf[] = {0, 0, 0, 0, 0, 0, 0, 0}; /* HID data */
static const uint8_t g_zero_data[] = {0, 0, 0, 0, 0, 0, 0, 0}; /* zero data */
static uint16_t g_numlock = 0;
static uint8_t g_idle = 0;
uint8_t g_remote_wakeup_enable = USB_OFF;
uint8_t g_status = NO_WRITING;
/******************************************************************************
* Function Name : usb_cpu_getkeyno
* Description : input key port
* Arguments : none
* Return value : uint16_t : key_no
******************************************************************************/
uint8_t usb_cpu_getkeyno (void)
{
uint8_t key_buf = 0;
if (SW_ACTIVE == SW)
{
if (sw_on_count[0] < SW_ON_THRESHOLD)
{
sw_on_count[0]++;
}
}
else
{
if (sw_on_count[0] >= SW_ON_THRESHOLD)
{
key_buf |= SW_PUSH;
}
sw_on_count[0] = 0;
}
return key_buf;
} /* End of function usb_cpu_getkeyno() */
/******************************************************************************
* Function Name : set_key_data
* Description : Set key data to buffer
* Arguments : none
* Return value : none
******************************************************************************/
void set_key_data (uint8_t * p_buf)
{
static uint8_t key_data;
key_data = KBD_CODE_A;
*(p_buf + 2) = key_data;
} /* End of function set_key_data() */
#if (BSP_CFG_RTOS == 2)
/******************************************************************************
* Function Name : usb_apl_callback
* Description : Callback function for Application program
* Arguments : usb_event_info_t *p_api_event : Control structure for USB API.
* : usb_hdl_t cur_task : Task Handle
* : uint8_t usb_state : USB_ON(USB_STATUS_REQUEST) / USB_OFF
* Return value : none
******************************************************************************/
void usb_apl_callback (usb_event_info_t * p_api_event, usb_hdl_t cur_task, usb_onoff_t usb_state)
{
(void) usb_state;
(void) cur_task;
xQueueSend(g_apl_mbx_hdl, (const void *) &p_api_event, (TickType_t) (0));
} /* End of function usb_apl_callback() */
#endif /* (BSP_CFG_RTOS == 2) */
/******************************************************************************
* Function Name : usb_phid_example
* Description : Peripheral HID application main process
* Arguments : none
* Return value : none
******************************************************************************/
void usb_phid_example (void)
{
usb_event_info_t event_info;
#if (BSP_CFG_RTOS == 2)
usb_event_info_t * p_mess;
#endif
usb_status_t event;
uint8_t * p_idle_value;
uint8_t sw_data;
usb_info_t info;
fsp_err_t ret_code = FSP_SUCCESS;
uint8_t send_data[16] BSP_ALIGN_VARIABLE(4);
g_usb_on_usb.open(&g_basic0_ctrl, &g_basic0_cfg);
set_key_data(g_buf);
while (1)
{
#if (BSP_CFG_RTOS == 2) /* FreeRTOS */
xQueueReceive(g_apl_mbx_hdl, (void *) &p_mess, portMAX_DELAY);
event_info = *p_mess;
event = event_info.event;
#else /* (BSP_CFG_RTOS == 2) */
/* Get USB event data */
g_usb_on_usb.eventGet(&event_info, &event);
#endif /* (BSP_CFG_RTOS == 2) */
switch (event)
{
break;
if (DATA_WRITING == g_status)
{
g_status = ZERO_WRITING;
g_usb_on_usb.write(&g_basic0_ctrl, (uint8_t *) g_zero_data, DATA_LEN, USB_CLASS_PHID); /* Sending the zero data (8 bytes) */
}
else
{
g_status = DATA_WRITING;
usb_cpu_delay_xms(USB_WAIT_1000MS);
g_usb_on_usb.write(&g_basic0_ctrl, g_buf, DATA_LEN, USB_CLASS_PHID);
}
break;
case USB_STATUS_REQUEST: /* Receive Class Request */
if (USB_SET_REPORT == (event_info.setup.request_type & USB_BREQUEST))
{
g_usb_on_usb.periControlDataGet(&g_basic0_ctrl, (uint8_t *) &g_numlock, 2); /* Get the NumLock data (NumLock data is not used) */
}
else if (USB_GET_DESCRIPTOR == (event_info.setup.request_type & USB_BREQUEST))
{
if (USB_GET_REPORT_DESCRIPTOR == event_info.setup.request_value)
{
g_usb_on_usb.periControlDataSet(&g_basic0_ctrl,
(uint8_t *) g_apl_report,
USB_RECEIVE_REPORT_DESCRIPTOR);
}
else if (USB_GET_HID_DESCRIPTOR == event_info.setup.request_value)
{
for (uint8_t i = 0; i < USB_RECEIVE_HID_DESCRIPTOR; i++)
{
send_data[i] = g_apl_configuration[18 + i];
}
/* Configuration Descriptor address set. */
g_usb_on_usb.periControlDataSet(&g_basic0_ctrl, send_data, USB_RECEIVE_HID_DESCRIPTOR);
}
else
{
g_usb_on_usb.periControlStatusSet(&g_basic0_ctrl, USB_SETUP_STATUS_STALL);
}
}
else if (USB_SET_IDLE == (event_info.setup.request_type & USB_BREQUEST))
{
/* Get SetIdle value */
p_idle_value = (uint8_t *) &event_info.setup.request_value;
g_idle = p_idle_value[1];
g_usb_on_usb.periControlStatusSet(&g_basic0_ctrl, USB_SETUP_STATUS_ACK);
}
else if (USB_GET_IDLE == (event_info.setup.request_type & USB_BREQUEST))
{
g_usb_on_usb.periControlDataSet(&g_basic0_ctrl, &g_idle, 1);
}
else if (USB_SET_PROTOCOL == (event_info.setup.request_type & USB_BREQUEST))
{
g_usb_on_usb.periControlStatusSet(&g_basic0_ctrl, USB_SETUP_STATUS_ACK);
g_status = DATA_WRITING;
g_usb_on_usb.write(&g_basic0_ctrl, g_buf, DATA_LEN, USB_CLASS_PHID);
}
else if (USB_GET_PROTOCOL == (event_info.setup.request_type & USB_BREQUEST))
{
g_usb_on_usb.periControlStatusSet(&g_basic0_ctrl, USB_SETUP_STATUS_STALL);
}
else
{
g_usb_on_usb.periControlStatusSet(&g_basic0_ctrl, USB_SETUP_STATUS_STALL);
}
break;
case USB_STATUS_REQUEST_COMPLETE: /* Complete Class Request */
if (USB_SET_IDLE == (event_info.setup.request_type & USB_BREQUEST))
{
p_idle_value = (uint8_t *) &event_info.setup.request_value;
g_idle = p_idle_value[1];
}
else if (USB_SET_PROTOCOL == (event_info.setup.request_type & USB_BREQUEST))
{
/* None */
}
else
{
g_status = DATA_WRITING;
g_usb_on_usb.write(&g_basic0_ctrl, g_buf, DATA_LEN, USB_CLASS_PHID);
}
break;
break;
g_remote_wakeup_enable = USB_OFF;
break;
default:
break;
}
ret_code = g_usb_on_usb.infoGet(&g_basic0_ctrl, &info, 0);
if (FSP_SUCCESS == ret_code)
{
sw_data = usb_cpu_getkeyno();
if (USB_STATUS_SUSPEND == info.device_status)
{
if (0 != (sw_data & SW_PUSH))
{
g_usb_on_usb.remoteWakeup(&g_basic0_ctrl);
}
}
}
}
} /* End of function usb_phid_example() */

Descriptors

A template for PHID descriptors can be found in ra/fsp/src/r_usb_phid. Be sure to replace the vendor ID with your own.
Keyboard templates should be referred to r_usb_phid_descriptor_keyboard.c.template.
Mouse templates should be referred to r_usb_phid_descriptor_mouse.c.template.