RA Flexible Software Package Documentation  Release v5.2.0

 
USB HCDC (r_usb_hcdc)

Functions

fsp_err_t R_USB_HCDC_ControlDataRead (usb_ctrl_t *const p_api_ctrl, uint8_t *p_buf, uint32_t size, uint8_t device_address)
 Read Control Data.(CDC Interrupt IN data) More...
 
fsp_err_t R_USB_HCDC_SpecificDeviceRegister (usb_ctrl_t *const p_api_ctrl, uint16_t vendor_id, uint16_t product_id)
 Register the specified vendor class device in the device table. More...
 
fsp_err_t R_USB_HCDC_DeviceInfoGet (usb_ctrl_t *const p_api_ctrl, usb_hcdc_device_info_t *p_info, uint8_t device_address)
 Get the VID, PID and subclass code of the connected device. More...
 

Detailed Description

This module provides a USB Host Communications Device Class (HCDC) driver. It implements the USB HCDC 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_hcdc module, when used in combination with the r_usb_basic module, operates as a USB Host Communications Device Class (HCDC) driver. The HCDC conforms to the PSTN device subclass abstract control model of the USB Communications Device Class (CDC) specification and enables communication with a CDC peripheral device.

Features

The r_usb_hcdc module has the following key features:

Configuration

Build Time Configurations for r_usb_hcdc

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

ConfigurationOptionsDefaultDescription
Target Peripheral Device Class ID
  • CDC class supported device
  • Vendor class device
CDC class supported device Specify the device class ID of the CDC device to be connected.
Bulk Input Transfer Pipe
  • USB PIPE1
  • USB PIPE2
  • USB PIPE3
  • USB PIPE4
  • USB PIPE5
USB PIPE4 Select the USB pipe to use for bulk input transfers.
Bulk Output Transfer Pipe
  • USB PIPE1
  • USB PIPE2
  • USB PIPE3
  • USB PIPE4
  • USB PIPE5
USB PIPE5 Select the USB pipe to use for bulk output transfers.
Interrupt In Pipe
  • USB PIPE6
  • USB PIPE7
  • USB PIPE8
  • USB PIPE9
USB PIPE6 Select the USB pipe to use for interrupts.

Configurations for Connectivity > USB HCDC (r_usb_hcdc)

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

ConfigurationOptionsDefaultDescription
NameName must be a valid C symbolg_hcdc0 Module name.

Note
Refer to the USB (r_usb_basic) module for hardware configuration options.

Clock Configuration

Refer to the USB (r_usb_basic) module.

Pin Configuration

Refer to the USB (r_usb_basic) module.

Usage Notes

Communications Device Class (CDC), PSTN and ACM

This software conforms to the Abstract Control Model (ACM) subclass of the Communications Device Class specification as defined in the "USB Communications Class Subclass Specification for PSTN Devices", Revision 1.2. The Abstract Control Model subclass is a technology that bridges the gap between USB devices and earlier modems (employing RS-232C connections) enabling use of application programs designed for older modems.

Basic Functions

The main functions of HCDC are the following:

Abstract Control Model Class Requests - Host to Device

This driver supports the following class requests:

Request Code Description
SendEncapsulatedCommand 0x00 Transmits an AT command as defined by the protocol used by the device (normally 0 for USB).
GetEncapsulatedResponse 0x01 Requests a response to a command transmitted by SendEncapsulatedCommand.
SetCommFeature 0x02 Enables or disables features such as device-specific 2-byte code and country setting.
GetCommFeature 0x03 Acquires the enabled/disabled state of features such as device-specific 2-byte code and country setting.
ClearCommFeature 0x04 Restores the default enabled/disabled settings of features such as device-specific 2-byte code and country setting.
SetLineCoding 0x20 Makes communication line settings (communication speed, data length, parity bit, and stop bit length).
GetLineCoding 0x21 Acquires the communication line setting state.
SetControlLineState 0x22 Makes communication line control signal (RTS, DTR) settings.
SendBreak 0x23 Transmits a break signal.
Note
For more information about Abstract Control Model requests, refer to Table 11 "Requests - Abstract Control Model" in the "USB Communications Class Subclass Specification for PSTN Devices", Revision 1.2.

The expected data format for each command is shown below followed by dependent structures.

bmRequestType bRequest wValue wIndex wLength Data
0x21 SEND_ENCAPSULATED_COMMAND (0x00) 0x0000 0x0000 Data length usb_hcdc_encapsulated_t
0x21 GET_ENCAPSULATED_RESPONSE (0x01) 0x0000 0x0000 Data length usb_hcdc_encapsulated_t
0x21 SET_COMM_FEATURE (0x02) usb_hcdc_feature_selector_t 0x0000 Data length usb_hcdc_commfeature_t
0x21 GET_COMM_FEATURE (0x03) usb_hcdc_feature_selector_t 0x0000 Data length usb_hcdc_commfeature_t
0x21 CLEAR_COMM_FEATURE (0x04) usb_hcdc_feature_selector_t 0x0000 Data length None
0x21 SET_LINE_CODING (0x20) 0x0000 0x0000 0x0000 usb_hcdc_linecoding_t
0xA1 GET_LINE_CODING (0x21) 0x0000 0x0000 0x0007 usb_hcdc_linecoding_t
0x21 SET_CONTROL_LINE_STATE (0x22) usb_hcdc_controllinestate_t 0x0000 0x0000 None
0x21 SEND_BREAK (0x23) usb_hcdc_breakduration_t 0x0000 0x0000 None

ACM Notifications from Device to Host

The following class notifications are supported:

Notification Code Description
RESPONSE_AVAILABLE 0x01 Response to GET_ENCAPSULATED_RESPONSE
SERIAL_STATE 0x20 Notification of serial line state

The data types returned are as follows:

bmRequestType bRequest wValue wIndex wLength Data
0xA1 RESPONSE_AVAILABLE (0x01) 0x0000 0x0000 0x0000 None
0xA1 SERIAL_STATE (0x20) 0x0000 0x0000 0x0002 usb_hcdc_serialstate_t
Note
The host is notified with SERIAL_STATE whenever a change in the UART port state is detected.

Limitations

This driver is subject to the following limitations:

Examples

USB HCDC Loopback Example

The main functions of the HCDC loopback example are as follows:

  1. Virtual UART control settings are configured by transmitting the class request SET_LINE_CODING to the CDC device.
  2. Sends receive (Bulk In transfer) requests to a CDC peripheral device and receives data.
  3. Loops received data back to the peripheral by means of Bulk Out transfers.
r_usb_hcdc_data_Transfer.svg
Data Transfer (Loopback)

The main loop performs loopback processing in which data received from a CDC peripheral device is transmitted unaltered back to the peripheral.

#define SET_LINE_CODING (USB_CDC_SET_LINE_CODING | USB_HOST_TO_DEV | USB_CLASS | USB_INTERFACE)
#define GET_LINE_CODING (USB_CDC_GET_LINE_CODING | USB_DEV_TO_HOST | USB_CLASS | USB_INTERFACE)
#define SET_CONTROL_LINE_STATE (USB_CDC_SET_CONTROL_LINE_STATE | USB_HOST_TO_DEV | USB_CLASS | USB_INTERFACE)
#define COM_SPEED (9600U)
#define COM_DATA_BIT (8U)
#define COM_STOP_BIT (0)
#define COM_PARITY_BIT (0)
#define LINE_CODING_LENGTH (7)
#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_hcdc_example
* Description : Host CDC application main process
* Arguments : none
* Return value : none
******************************************************************************/
void usb_hcdc_example (void)
{
usb_status_t event;
usb_event_info_t event_info;
#if (BSP_CFG_RTOS == 2)
usb_event_info_t * p_mess;
#endif
g_usb_on_usb.open(&g_basic0_ctrl, &g_basic0_cfg);
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) */
/* Handle the received event (if any) */
switch (event)
{
/* Configure virtual UART settings */
set_line_coding(&g_basic0_ctrl, event_info.device_address); /* CDC Class request "SetLineCoding" */
break;
if (USB_CLASS_HCDC == event_info.type)
{
if (event_info.data_size > 0)
{
/* Send the received data back to the connected peripheral */
g_usb_on_usb.write(&g_basic0_ctrl, g_snd_buf, event_info.data_size, USB_DEVICE_ADDRESS_1);
}
else
{
/* Send the data reception request when the zero-length packet is received. */
g_usb_on_usb.read(&g_basic0_ctrl, g_rcv_buf, CDC_DATA_LEN, USB_DEVICE_ADDRESS_1);
}
}
else /* USB_HCDCC */
{
/* Control Class notification "SerialState" receive start */
g_usb_on_usb.read(&g_basic0_ctrl,
(uint8_t *) &g_serial_state,
USB_HCDC_SERIAL_STATE_MSG_LEN,
USB_DEVICE_ADDRESS_1);
}
break;
/* Start receive operation */
g_usb_on_usb.read(&g_basic0_ctrl, g_rcv_buf, CDC_DATA_LEN, USB_DEVICE_ADDRESS_1);
break;
if (USB_CDC_SET_LINE_CODING == (event_info.setup.request_type & USB_BREQUEST))
{
/* Set virtual RTS/DTR signal state */
set_control_line_state(&g_basic0_ctrl, event_info.device_address); /* CDC Class request "SetControlLineState" */
}
/* Check Complete request "SetControlLineState" */
else if (USB_CDC_SET_CONTROL_LINE_STATE == (event_info.setup.request_type & USB_BREQUEST))
{
/* Read back virtual UART settings */
get_line_coding(&g_basic0_ctrl, event_info.device_address); /* CDC Class request "SetLineCoding" */
}
else if (USB_CDC_GET_LINE_CODING == (event_info.setup.request_type & USB_BREQUEST))
{
/* Now that setup is complete, start loopback operation */
g_usb_on_usb.read(&g_basic0_ctrl, g_snd_buf, CDC_DATA_LEN, USB_DEVICE_ADDRESS_1);
}
else
{
/* Unsupported request */
}
break;
default:
/* Other event */
break;
}
}
} /* End of function usb_hcdc_example() */
/******************************************************************************
* Function Name : set_control_line_state
* Description : Send the class request (SetControLineState) to CDC device.
* Arguments : device_address : device address of CDC device.
* Return value : none
******************************************************************************/
void set_control_line_state (usb_instance_ctrl_t * p_ctrl, uint8_t device_address)
{
usb_setup_t setup;
setup.request_type = SET_CONTROL_LINE_STATE; /* bRequestCode:SET_CONTROL_LINE_STATE, bmRequestType */
setup.request_value = 0x0000; /* wValue:Zero */
setup.request_index = 0x0000; /* wIndex:Interface */
setup.request_length = 0x0000; /* wLength:Zero */
g_usb_on_usb.hostControlTransfer(p_ctrl, &setup, (uint8_t *) &g_usb_dummy, device_address);
} /* End of function set_control_line_state() */
/******************************************************************************
* Function Name : set_line_coding
* Description : Send the class request (SetLineCoding) to CDC device.
* Arguments : device_address : device address of CDC device.
* Return value : none
******************************************************************************/
void set_line_coding (usb_instance_ctrl_t * p_ctrl, uint8_t device_address)
{
usb_setup_t setup;
g_com_parm.dwdte_rate = (usb_hcdc_line_speed_t) COM_SPEED;
g_com_parm.bchar_format = (usb_hcdc_stop_bit_t) COM_STOP_BIT;
g_com_parm.bparity_type = (usb_hcdc_parity_bit_t) COM_PARITY_BIT;
g_com_parm.bdata_bits = (usb_hcdc_data_bit_t) COM_DATA_BIT;
setup.request_type = SET_LINE_CODING; /* bRequestCode:SET_LINE_CODING, bmRequestType */
setup.request_value = 0x0000; /* wValue:Zero */
setup.request_index = 0x0000; /* wIndex:Interface */
setup.request_length = LINE_CODING_LENGTH; /* Data:Line Coding Structure */
/* Request Control transfer */
g_usb_on_usb.hostControlTransfer(p_ctrl, &setup, (uint8_t *) &g_com_parm, device_address);
} /* End of function set_line_coding() */
/******************************************************************************
* Function Name : get_line_coding
* Description : Send the class request (GetLineCoding) to CDC device.
* Arguments : device_address : device address of CDC device.
* Return value : none
******************************************************************************/
void get_line_coding (usb_instance_ctrl_t * p_ctrl, uint8_t device_address)
{
usb_setup_t setup;
setup.request_type = GET_LINE_CODING; /* bRequestCode:GET_LINE_CODING, bmRequestType */
setup.request_value = 0x0000; /* wValue:Zero */
setup.request_index = 0x0000; /* wIndex:Interface */
setup.request_length = LINE_CODING_LENGTH; /* Data:Line Coding Structure */
/* Request Control transfer */
g_usb_on_usb.hostControlTransfer(p_ctrl, &setup, (uint8_t *) &g_com_parm, device_address);
} /* End of function get_line_coding() */

USB HCDC-ECM Example

The following is the porting layere example code for FreeRTOS Plus TCP

#if defined USE_PING_SEND_DEMO
#elif defined USE_TCP_CLIENT_DEMO
#define BUFFER_SIZE 1514 * 2 // 1024
static char cRxedData[BUFFER_SIZE];
static char cTxData[BUFFER_SIZE];
Socket_t vCreateTCPClientSocket(void);
void vCloseTCPClientSocket(Socket_t xSocket);
BaseType_t xConnectToTCPServer(Socket_t xSocket);
#endif
/* Domain for the DNS Host lookup is used in this Example Project.
* The project can be built with different *domain_name to validate the DNS client
*/
char * domain_name = USR_TEST_DOMAIN_NAME;
/* IP address of the PC or any Device on the LAN/WAN where the Ping request is sent.
* Note: Users needs to change this according to the LAN settings of your Test PC or device
* when running this project.
*/
// char *remote_ip_address = "132.158.142.140";
// char *remote_ip_address = "192.168.1.140";
#if (USE_DHCP_CLIENT_DEMO != 0)
char * remote_ip_address = USR_TEST_PING_IP;
#else
char * remote_ip_address = "192.168.10.1";
#endif
#if (USE_DHCP_CLIENT_DEMO != 0)
/* DHCP populates these IP address, Sub net mask and Gateway Address. So start with this is zeroed out values
* The MAC address is Test MAC address.
*/
static uint8_t ucMACAddress[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
static uint8_t ucIPAddress[4] = {RESET_VALUE};
static uint8_t ucNetMask[4] = {255, 255, 255, 128};
static uint8_t ucGatewayAddress[4] = {132, 158, 124, 1};
static uint8_t ucDNSServerAddress[4] = {RESET_VALUE};
#else
/* Static IP configuration, when DHCP mode is not used for the Example Project.
* This needs to be populated by the user according to the Network Settings of your LAN.
* This sample address taken from the LAN where it is tested. This is different for different LAN.
* get the Address using the PC IPconfig details.
*/
static uint8_t ucMACAddress[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
static uint8_t ucIPAddress[4] = {192, 168, 10, 2};
static uint8_t ucNetMask[4] = {255, 255, 255, 0};
static uint8_t ucGatewayAddress[4] = {192, 168, 10, 0};
static uint8_t ucDNSServerAddress[4] = {10, 60, 1, 2};
#endif
#if (USE_DHCP_CLIENT_DEMO != 0)
extern NetworkAddressingParameters_t xNetworkAddressing;
NetworkAddressingParameters_t xNd = {RESET_VALUE, RESET_VALUE, RESET_VALUE, RESET_VALUE, RESET_VALUE};
uint32_t usrPingCount = RESET_VALUE;
static uint32_t usr_print_ability = RESET_VALUE;
#endif
uint32_t dhcp_in_use = RESET_VALUE;
ping_data_t ping_data = {RESET_VALUE, RESET_VALUE, RESET_VALUE};
uint32_t ulRand (void)
{
/* example of a 32-bit random number generator.
* Here rand() returns a 15-bit number. so create 32 bit Random number using 15 bit rand()
*/
uint32_t ulResult =
((((uint32_t) rand()) & 0x7fffuL)) |
((((uint32_t) rand()) & 0x7fffuL) << 15) |
((((uint32_t) rand()) & 0x0003uL) << 30);
return ulResult;
}
uint32_t ulApplicationGetNextSequenceNumber (uint32_t ulSourceAddress,
uint16_t usSourcePort,
uint32_t ulDestinationAddress,
uint16_t usDestinationPort)
{
/* Here we need to get random number for the sequence number.
* This is just for testing purpose, so software rand() is okay.
* This can also be tied to the TRNG.
*/
return (ulSourceAddress + ulDestinationAddress + usSourcePort + usDestinationPort) && ulRand();
}
BaseType_t vSendPing (const char * pcIPAddress)
{
uint32_t ulIPAddress = RESET_VALUE;
/*
* The pcIPAddress parameter holds the destination IP address as a string in
* decimal dot notation (for example, ?192.168.0.200?). Convert the string into
* the required 32-bit format.
*/
ulIPAddress = FreeRTOS_inet_addr(pcIPAddress);
/*
* Send a ping request containing 8 data bytes. Wait (in the Blocked state) a
* maximum of 100ms for a network buffer into which the generated ping request
* can be written and sent.
*/
return FreeRTOS_SendPingRequest(ulIPAddress, 8, 1000000 / portTICK_PERIOD_MS);
}
void vApplicationPingReplyHook (ePingReplyStatus_t eStatus, uint16_t usIdentifier)
{
(void) usIdentifier;
switch (eStatus)
{
/* A valid ping reply has been received */
case eSuccess:
ping_data.received++;
break;
/* A reply was received but it was not valid. */
case eInvalidData:
default:
ping_data.lost++;
break;
}
}
uint32_t isNetworkUp (void)
{
fsp_err_t eth_link_status = FSP_ERR_NOT_OPEN;
BaseType_t networkUp = pdFALSE;
uint32_t network_status = (IP_LINK_UP | ETHERNET_LINK_UP);
networkUp = FreeRTOS_IsNetworkUp();
eth_link_status = xGetPhyLinkStatus();
if ((pdPASS == eth_link_status) && (pdTRUE == networkUp))
{
return network_status;
}
else
{
if (pdPASS != eth_link_status)
{
network_status |= ETHERNET_LINK_DOWN;
}
else if (pdPASS == eth_link_status)
{
network_status |= ETHERNET_LINK_UP;
}
if (pdTRUE != networkUp)
{
network_status |= IP_LINK_DOWN;
}
else if (pdTRUE == networkUp)
{
network_status |= IP_LINK_UP;
}
return network_status;
}
}
#if defined USE_LINK_STATUS_CHECK
static void prvLinkStatusCheckTask (void * pvParameters)
{
fsp_err_t eth_link_status = pdFAIL;
fsp_err_t eth_link_pre_status = pdFAIL;
while (1)
{
eth_link_status = xGetPhyLinkStatus();
if ((pdPASS == eth_link_status) && (pdFAIL == eth_link_pre_status))
{
APP_PRINT("\r\n-- Link Up --");
eth_link_pre_status = pdPASS;
}
else if ((pdFAIL == eth_link_status) && (pdPASS == eth_link_pre_status))
{
APP_PRINT("\r\n-- Link Down --");
eth_link_pre_status = pdFAIL;
}
vTaskDelay(100);
}
}
#endif
void new_thread0_entry (void * pvParameters)
{
BaseType_t status = pdFALSE;
fsp_pack_version_t version = {RESET_VALUE};
#if defined USE_PING_SEND_DEMO
#elif defined USE_TCP_CLIENT_DEMO
Socket_t xClientSocket;
BaseType_t lBytesReceived;
#endif
FSP_PARAMETER_NOT_USED(pvParameters);
/* version get API for FLEX pack information */
R_FSP_VersionGet(&version);
/* Example Project information printed on the RTT */
APP_PRINT(BANNER_INFO,
EP_VERSION,
version.version_id_b.major,
version.version_id_b.minor,
version.version_id_b.patch);
/* Prints the Ethernet Configuration prior to the IP Init*/
APP_PRINT(ETH_PREINIT);
print_ipconfig();
#if defined USE_LINK_STATUS_CHECK
static TaskHandle_t xLinkStatusCheckTaskHandle = NULL;
BaseType_t xReturn = pdFAIL;
xReturn = xTaskCreate(prvLinkStatusCheckTask,
"LinkStatusCheckTask",
configMINIMAL_STACK_SIZE,
NULL,
2, // configMAX_PRIORITIES - 3,
&xLinkStatusCheckTaskHandle);
#endif
/* FreeRTOS IP Initialization: This init initializes the IP stack */
status = FreeRTOS_IPInit(ucIPAddress, ucNetMask, ucGatewayAddress, ucDNSServerAddress, ucMACAddress);
if (pdFALSE == status)
{
APP_ERR_PRINT("FreeRTOS_IPInit Failed");
APP_ERR_TRAP(status);
}
APP_PRINT(ETH_POSTINIT);
while (true)
{
#if (USE_DHCP_CLIENT_DEMO != 0)
/* Check if Both the Ethernet Link and IP link are UP */
if (SUCCESS == isNetworkUp())
{
/* usr_print_ability is added to avoid multiple UP messages or Down Messages repeating*/
if (!(PRINT_UP_MSG_DISABLE & usr_print_ability))
{
APP_PRINT("\r\nNetwork is Up");
usr_print_ability |= PRINT_UP_MSG_DISABLE;
}
if (!(PRINT_NWK_USR_MSG_DISABLE & usr_print_ability))
{
/* Display the New IP credentials obtained from the DHCP server */
updateDhcpResponseToUsr();
/* Updated IP credentials on to the RTT console */
print_ipconfig();
/*DNS lookup for the Domain name requested. This is Synchronous Activity */
dnsQuerryFunc(domain_name);
}
if (!(PRINT_NWK_USR_MSG_DISABLE & usr_print_ability))
{
APP_PRINT("\r\nPinging %s:\r\n\r\n", (char *) remote_ip_address);
}
while (usrPingCount < USR_PING_COUNT)
{
/* Send a ICMP Ping request to the requested IP address
* USR_PING_COUNT (100) is used in this Example Project
* For Continuous testing the count can be increased to bigger number
*/
status = vSendPing((char *) remote_ip_address);
if (status != pdFALSE)
{
ping_data.sent++;
APP_PRINT("!");
}
else
{
ping_data.lost++;
APP_PRINT(".");
}
usrPingCount++;
/* Add some delay between Pings */
vTaskDelay(10);
}
if (!(PRINT_NWK_USR_MSG_DISABLE & usr_print_ability))
{
print_pingResult();
usr_print_ability |= PRINT_NWK_USR_MSG_DISABLE;
}
}
else
{
if (!(PRINT_DOWN_MSG_DISABLE & usr_print_ability))
{
APP_PRINT("\r\nNetwork is Down");
usr_print_ability |= PRINT_DOWN_MSG_DISABLE;
}
else
{
APP_PRINT(".");
}
}
vTaskDelay(100);
#else
#if defined USE_PING_SEND_DEMO
/* [Provisional processing] Wait until the link is up */
if (SUCCESS == isNetworkUp())
{
while (1)
{
status = vSendPing((char *) remote_ip_address);
if (status != pdFALSE)
{
if (SUCCESS != isNetworkUp())
{
break;
}
vTaskDelay(2000);
}
else
{
break;
}
}
}
vTaskDelay(100);
#elif defined USE_TCP_CLIENT_DEMO
if (SUCCESS == isNetworkUp())
{
/* Create, bind and connect a socket */
xClientSocket = vCreateTCPClientSocket();
while (1)
{
if (pdTRUE == xConnectToTCPServer(xClientSocket))
{
break;
}
vTaskDelay(1000);
}
/* Receive data from TCP Server. */
lBytesReceived = FreeRTOS_recv(xClientSocket, &cRxedData, BUFFER_SIZE, 0);
if (lBytesReceived > 0)
{
memcpy(&cTxData, &cRxedData, (size_t) lBytesReceived);
/* Send data to TCP Server. (Loopback received data) */
FreeRTOS_send(xClientSocket, &cTxData, (size_t) lBytesReceived, 0);
vTaskDelay(1000);
}
/* Close socket */
vCloseTCPClientSocket(xClientSocket);
}
vTaskDelay(1000);
#else
vTaskDelay(100);
#endif
vTaskDelay(100);
#endif
}
}
#if defined USE_PING_SEND_DEMO
#elif defined USE_TCP_CLIENT_DEMO
Socket_t vCreateTCPClientSocket (void)
{
Socket_t xClientSocket;
struct freertos_sockaddr xBindAddress;
static const TickType_t xTimeOut = pdMS_TO_TICKS(10000);
// static const TickType_t xTimeOut = pdMS_TO_TICKS( 2000 );
/* Attempt to open the socket. */
xClientSocket = FreeRTOS_socket(FREERTOS_AF_INET,
FREERTOS_SOCK_STREAM, /* SOCK_STREAM for TCP. */
FREERTOS_IPPROTO_TCP);
/* Check the socket was created. */
configASSERT(xClientSocket != FREERTOS_INVALID_SOCKET);
/* If FREERTOS_SO_RCVBUF or FREERTOS_SO_SNDBUF are to be used with
* FreeRTOS_setsockopt() to change the buffer sizes from their default then do
* it here!. (see the FreeRTOS_setsockopt() documentation. */
/* If ipconfigUSE_TCP_WIN is set to 1 and FREERTOS_SO_WIN_PROPERTIES is to
* be used with FreeRTOS_setsockopt() to change the sliding window size from
* its default then do it here! (see the FreeRTOS_setsockopt()
* documentation. *//* Set send and receive time outs. */
FreeRTOS_setsockopt(xClientSocket, 0, FREERTOS_SO_RCVTIMEO, &xTimeOut, sizeof(xTimeOut));
FreeRTOS_setsockopt(xClientSocket, 0, FREERTOS_SO_SNDTIMEO, &xTimeOut, sizeof(xTimeOut));
/* Bind the socket, but pass in NULL to let FreeRTOS-Plus-TCP choose the port number.
* See the next source code snipped for an example of how to bind to a specific
* port number. */
if (xClientSocket != FREERTOS_INVALID_SOCKET)
{
xBindAddress.sin_port = FreeRTOS_htons(9999);
if (FreeRTOS_bind(xClientSocket, &xBindAddress, sizeof(xBindAddress)) == 0)
{
/* The bind was successful. */
}
else
{
while (1)
{
; /* error */
}
}
}
else
{
while (1)
{
; /* error */
}
}
return xClientSocket;
}
BaseType_t xConnectToTCPServer (Socket_t xSocket)
{
BaseType_t ret;
struct freertos_sockaddr xRemoteAddress;
/* Connect to TCP Server */
xRemoteAddress.sin_addr = FreeRTOS_inet_addr_quick(192, 168, 10, 1); /* 192.168.10.1 : Remote IP Address */
xRemoteAddress.sin_port = FreeRTOS_htons(4000);
ret = FreeRTOS_connect(xSocket, &xRemoteAddress, sizeof(xRemoteAddress));
if (ret == 0)
{
/* Success */
ret = pdTRUE;
}
else
{
// while(1); /* error */
ret = pdFALSE;
}
return ret;
}
void vCloseTCPClientSocket (Socket_t xSocket)
{
/* Initiate graceful shutdown. */
FreeRTOS_shutdown(xSocket, FREERTOS_SHUT_RDWR);
/* Wait for the socket to disconnect gracefully (indicated by FreeRTOS_recv()
* returning a -pdFREERTOS_ERRNO_EINVAL error) before closing the socket. */
while (FreeRTOS_recv(xSocket, &cRxedData, BUFFER_SIZE, 0) >= 0)
{
/* Wait for shutdown to complete. If a receive block time is used then
* this delay will not be necessary as FreeRTOS_recv() will place the RTOS task
* into the Blocked state anyway. */
vTaskDelay(250);
/* Note - real applications should implement a timeout here, not just
* loop forever. */
}
/* The socket has shut down and is safe to close. */
FreeRTOS_closesocket(xSocket);
}
#endif
#if (USE_DHCP_CLIENT_DEMO != 0)
eDHCPCallbackAnswer_t xApplicationDHCPHook (eDHCPCallbackPhase_t eDHCPPhase, uint32_t ulIPAddress)
{
eDHCPCallbackAnswer_t eReturn = eDHCPContinue;
/*
* This hook is called in a couple of places during the DHCP process, as identified by the eDHCPPhase parameter.
*/
switch (eDHCPPhase)
{
case eDHCPPhasePreDiscover:
/*
* A DHCP discovery is about to be sent out. eDHCPContinue is returned to allow the discovery to go out.
* If eDHCPUseDefaults had been returned instead then the DHCP process would be stopped and the statically
* configured IP address would be used.
* If eDHCPStopNoChanges had been returned instead then the DHCP process would be stopped and whatever the
* current network configuration was would continue to be used.
*/
break;
case eDHCPPhasePreRequest:
/* An offer has been received from the DHCP server, and the offered IP address is passed in the ulIPAddress
* parameter.
*/
/*
* The sub-domains don?t match, so continue with the DHCP process so the offered IP address is used.
*/
/* Update the Structure, the DHCP state Machine is not updating this */
xNetworkAddressing.ulDefaultIPAddress = ulIPAddress;
dhcp_in_use = 1;
break;
default:
/*
* Cannot be reached, but set eReturn to prevent compiler warnings where compilers are disposed to generating one.
*/
break;
}
return eReturn;
}
#endif
void print_pingResult (void)
{
APP_PRINT("\r\n \r\nPing Statistics for %s :\r\n", (char *) remote_ip_address);
APP_PRINT("\r\nPackets: Sent = %02d, Received = %02d, Lost = %02d \r\n",
ping_data.sent,
ping_data.received,
ping_data.lost);
}
void print_ipconfig (void)
{
#if (USE_DHCP_CLIENT_DEMO != 0)
if (dhcp_in_use)
{
ucNetMask[3] = (uint8_t) ((xNd.ulNetMask & 0xFF000000) >> 24);
ucNetMask[2] = (uint8_t) ((xNd.ulNetMask & 0x00FF0000) >> 16);
ucNetMask[1] = (uint8_t) ((xNd.ulNetMask & 0x0000FF00) >> 8);
ucNetMask[0] = (uint8_t) (xNd.ulNetMask & 0x000000FF);
ucGatewayAddress[3] = (uint8_t) ((xNd.ulGatewayAddress & 0xFF000000) >> 24);;
ucGatewayAddress[2] = (uint8_t) ((xNd.ulGatewayAddress & 0x00FF0000) >> 16);
ucGatewayAddress[1] = (uint8_t) ((xNd.ulGatewayAddress & 0x0000FF00) >> 8);
ucGatewayAddress[0] = (uint8_t) (xNd.ulGatewayAddress & 0x000000FF);
ucDNSServerAddress[3] = (uint8_t) ((xNd.ulDNSServerAddress & 0xFF000000) >> 24);
ucDNSServerAddress[2] = (uint8_t) ((xNd.ulDNSServerAddress & 0x00FF0000) >> 16);
ucDNSServerAddress[1] = (uint8_t) ((xNd.ulDNSServerAddress & 0x0000FF00) >> 8);
ucDNSServerAddress[0] = (uint8_t) (xNd.ulDNSServerAddress & 0x000000FF);
ucIPAddress[3] = (uint8_t) ((xNd.ulDefaultIPAddress & 0xFF000000) >> 24);
ucIPAddress[2] = (uint8_t) ((xNd.ulDefaultIPAddress & 0x00FF0000) >> 16);
ucIPAddress[1] = (uint8_t) ((xNd.ulDefaultIPAddress & 0x0000FF00) >> 8);
ucIPAddress[0] = (uint8_t) (xNd.ulDefaultIPAddress & 0x000000FF);
}
#endif
APP_PRINT("\r\nEthernet adapter for Renesas "KIT_NAME ":\r\n")
APP_PRINT("\tDescription . . . . . . . . . . . : Renesas "KIT_NAME " Ethernet\r\n");
APP_PRINT("\tPhysical Address. . . . . . . . . : %02x-%02x-%02x-%02x-%02x-%02x\r\n",
ucMACAddress[0],
ucMACAddress[1],
ucMACAddress[2],
ucMACAddress[3],
ucMACAddress[4],
ucMACAddress[5]);
APP_PRINT("\tDHCP Enabled. . . . . . . . . . . : %s\r\n", dhcp_in_use ? "Yes" : "No")
APP_PRINT("\tIPv4 Address. . . . . . . . . . . : %d.%d.%d.%d\r\n",
ucIPAddress[0],
ucIPAddress[1],
ucIPAddress[2],
ucIPAddress[3]);
APP_PRINT("\tSubnet Mask . . . . . . . . . . . : %d.%d.%d.%d\r\n",
ucNetMask[0],
ucNetMask[1],
ucNetMask[2],
ucNetMask[3]);
APP_PRINT("\tDefault Gateway . . . . . . . . . : %d.%d.%d.%d\r\n",
ucGatewayAddress[0],
ucGatewayAddress[1],
ucGatewayAddress[2],
ucGatewayAddress[3]);
APP_PRINT("\tDNS Servers . . . . . . . . . . . : %d.%d.%d.%d\r\n",
ucDNSServerAddress[0],
ucDNSServerAddress[1],
ucDNSServerAddress[2],
ucDNSServerAddress[3]);
}
void dnsQuerryFunc (char * domain)
{
uint32_t ulIPAddress = RESET_VALUE;
int8_t cBuffer[16] = {RESET_VALUE};
/* Lookup the IP address of the FreeRTOS.org website. */
ulIPAddress = FreeRTOS_gethostbyname((char *) domain);
if (ulIPAddress != 0)
{
/* Convert the IP address to a string. */
FreeRTOS_inet_ntoa(ulIPAddress, (char *) cBuffer);
/* Print out the IP address obtained from the DNS lookup. */
APP_PRINT("\r\nDNS Lookup for \"www.freertos.org\" is : %s \r\n", cBuffer);
}
else
{
APP_PRINT("\r\nDNS Lookup failed for \"www.freertos.org\" \r\n");
}
}
#if (USE_DHCP_CLIENT_DEMO != 0)
void updateDhcpResponseToUsr (void)
{
if (dhcp_in_use)
{
memcpy(&xNd, &xNetworkAddressing, sizeof(xNd));
}
}
#endif
#if (ipconfigDHCP_REGISTER_HOSTNAME == 1)
const char * pcApplicationHostnameHook (void)
{
return KIT_NAME;
}
#endif

USB HCDC-ECM FreeRTOS Plus TCP Porting Layer Example

The following is HCDC-ECM example code sample for FreeRTOS Plus TCP

/***********************************************************************************************************************
* Macro definitions
***********************************************************************************************************************/
/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
* driver will filter incoming packets and only pass the stack those packets it
* considers need processing. */
#if (ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0)
#define ipCONSIDER_FRAME_FOR_PROCESSING(pucEthernetBuffer) eProcessBuffer
#else
#define ipCONSIDER_FRAME_FOR_PROCESSING(pucEthernetBuffer) eConsiderFrameForProcessing((pucEthernetBuffer))
#endif
#define MAXIMUM_ETHERNET_FRAME_SIZE (1514U)
#define UNSIGNED_SHORT_RANDOM_NUMBER_MASK (0xFFFFUL)
#define ETHER_LINK_STATUS_CHECK_INTERVAL (100)
#define USB_MAX_PACKET_SIZE_FS (64)
#define USB_MAX_PACKET_SIZE_HS (512)
#define USB_CALLBACK_QUEUE_SIZE (10)
#define CDC_READ_DATA_LEN MAXIMUM_ETHERNET_FRAME_SIZE * 2
#define NO_WAIT_TIME (0)
#define VALUE_ZERO (0)
#define VALUE_9 (9)
#define VALUE_0001H (0x0001)
#define VALUE_0002H (0x0002)
#define VALUE_0003H (0x0003)
#define VALUE_001FH (0x001F)
#define CDC_SUB_CLASS_ACM (0x02)
#define CDC_SUB_CLASS_ECM (0x06)
#define CDC_INTERRUPT_READ_DATA_LEN (16)
#define SET_ETHERNET_PACKET_FILTER (0x4300)
#define VALUE_ZERO (0)
#define VALUE_9 (9)
#define VALUE_0001H (0x0001)
#define VALUE_0002H (0x0002)
#define VALUE_0003H (0x0003)
#define VALUE_001FH (0x001F)
#define USB_ECM_TEST_DEVICE_VID (0x0b95) /* USB-LAN conversion adapter's Vendor ID */
#define USB_ECM_TEST_DEVICE_PID (0x1790) /* USB-LAN conversion adapter's Product ID */
/***********************************************************************************************************************
* Exported global variables (to be accessed by other files)
**********************************************************************************************************************/
volatile bool g_err_flag = false; /* flag bit */
QueueHandle_t g_usb_read_complete_queue;
QueueHandle_t g_usb_write_complete_queue;
usb_utr_t g_utr;
uint32_t g_ecm_connected = 0;
extern volatile bool g_err_flag;
extern QueueHandle_t g_usb_read_complete_queue;
extern QueueHandle_t g_usb_write_complete_queue;
extern uint32_t g_ecm_connected;
extern usb_utr_t g_utr;
/***********************************************************************************************************************
* Private global variables
**********************************************************************************************************************/
static TaskHandle_t xRxHanderTaskHandle = NULL;
static QueueHandle_t g_usb_callback_queue;
static usb_event_info_t * g_p_event_info = NULL;
static uint8_t g_snd_buf[CDC_READ_DATA_LEN] BSP_ALIGN_VARIABLE(4) = {VALUE_ZERO}; /* Send buffer (Bulk OUT) */
static uint8_t g_rcv_buf[CDC_READ_DATA_LEN] BSP_ALIGN_VARIABLE(4) = {VALUE_ZERO}; /* Receive buffer (Bulk IN) */
static uint32_t g_usb_max_packet_size;
static uint8_t g_interrupt_in_rcv_buf[64] BSP_ALIGN_VARIABLE(4) = {VALUE_ZERO}; /* Receive buffer (Interrupt IN) */
static uint8_t g_usb_dummy = VALUE_ZERO; /* dummy variable to send */
static uint8_t g_disc_buf[512] BSP_ALIGN_VARIABLE(4) = {VALUE_ZERO}; /* Receive buffer for GetDescriptor Request */
static uint8_t g_subclass = VALUE_ZERO;
static const uint8_t g_notification_networkconnection_connect[8] =
{
0xA1, /* bmRequestType */
0x00, /* bRequest */
0x01, /* wValue (lo) */
0x00, /* wValue (hi) */
0x01, /* wIndex (lo) */
0x00, /* wIndex (hi) */
0x00, /* wLength (lo) */
0x00 /* wLength (hi) */
};
static const uint8_t g_notification_networkconnection_disconnect[8] =
{
0xA1, /* bmRequestType */
0x00, /* bRequest */
0x00, /* wValue (lo) */
0x00, /* wValue (hi) */
0x01, /* wIndex (lo) */
0x00, /* wIndex (hi) */
0x00, /* wLength (lo) */
0x00 /* wLength (hi) */
};
/***********************************************************************************************************************
* Exported global function
***********************************************************************************************************************/
extern void vSpecificDeviceRegistration(void);
extern void vEventProcess(usb_event_info_t * p_event_info);
/***********************************************************************************************************************
* Prototype declaration of global functions
**********************************************************************************************************************/
void handle_error(fsp_err_t err, char * err_str);
void vSpecificDeviceRegistration(void);
void vEventProcess(usb_event_info_t * p_event_info);
/***********************************************************************************************************************
* Prototype declaration of private functions
**********************************************************************************************************************/
static BaseType_t prvNetworkInterfaceInput(void);
static void prvRXHandlerTask(void * pvParameters);
static void prvUsbEventProcessTask(void * pvParameters);
static void set_configuration0_for_asix_ax88179(usb_instance_ctrl_t * p_ctrl, uint8_t device_address);
static void set_configuration3_for_asix_ax88179(usb_instance_ctrl_t * p_ctrl, uint8_t device_address);
static void get_configration_descriptor_for_asix_ax88179(usb_instance_ctrl_t * p_ctrl,
uint8_t device_address,
uint16_t length);
static void set_interface_for_asix_ax88179(usb_instance_ctrl_t * p_ctrl, uint8_t device_address);
static void set_ethernet_packet_filter(usb_instance_ctrl_t * p_ctrl, uint8_t device_address);
/***********************************************************************************************************************
* Interface functions
**********************************************************************************************************************/
BaseType_t xNetworkInterfaceInitialise (void)
{
fsp_err_t err;
BaseType_t xReturn = pdFAIL;
g_utr.ip = g_basic0_cfg.module_number;
g_utr.ipp = usb_hstd_get_usb_ip_adr((uint16_t) g_basic0_cfg.module_number);
#if (USB_CFG_DMA == USB_CFG_ENABLE)
g_utr.p_transfer_rx = g_basic0_cfg.p_transfer_rx;
g_utr.p_transfer_tx = g_basic0_cfg.p_transfer_tx;
#endif
if (USB_SPEED_FS == g_basic0_cfg.usb_speed)
{
g_usb_max_packet_size = USB_MAX_PACKET_SIZE_FS;
}
else
{
g_usb_max_packet_size = USB_MAX_PACKET_SIZE_HS;
}
g_usb_callback_queue = xQueueCreate(USB_CALLBACK_QUEUE_SIZE, sizeof(void *));
g_usb_read_complete_queue = xQueueCreate(1, sizeof(unsigned long));
g_usb_write_complete_queue = xQueueCreate(1, sizeof(unsigned long));
if ((NULL != g_usb_callback_queue) &&
(NULL != g_usb_read_complete_queue) &&
(NULL != g_usb_write_complete_queue))
{
xReturn = xTaskCreate(prvUsbEventProcessTask,
"UsbEventProcessTask",
configMINIMAL_STACK_SIZE,
NULL,
configMAX_PRIORITIES - 3,
NULL);
}
vSpecificDeviceRegistration();
err = R_USB_Open(&g_basic0_ctrl, &g_basic0_cfg);
if (FSP_SUCCESS != err)
{
return pdFAIL;
}
xReturn = xTaskCreate(prvRXHandlerTask,
"RXHandlerTask",
configMINIMAL_STACK_SIZE,
NULL,
configMAX_PRIORITIES - 3,
&xRxHanderTaskHandle);
return xReturn;
}
BaseType_t xGetPhyLinkStatus (void)
{
BaseType_t xReturn = pdPASS;
if (1 == g_ecm_connected)
{
xReturn = pdPASS;
}
else
{
xReturn = pdFAIL;
}
return xReturn;
}
BaseType_t xNetworkInterfaceOutput (NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t xReleaseAfterSend)
{
fsp_err_t err;
BaseType_t xReturn = pdFAIL;
usb_event_info_t * p_event_info;
if (1 == g_ecm_connected)
{
if ((USB_IP1 == g_utr.ip) && (0 != ((uint32_t) pxNetworkBuffer->pucEthernetBuffer) % sizeof(uint32_t)))
{
memcpy(g_snd_buf, pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength);
err = R_USB_Write(&g_basic0_ctrl, g_snd_buf, pxNetworkBuffer->xDataLength, g_p_event_info->device_address);
}
else
{
err = R_USB_Write(&g_basic0_ctrl,
pxNetworkBuffer->pucEthernetBuffer,
pxNetworkBuffer->xDataLength,
g_p_event_info->device_address);
}
if (FSP_SUCCESS == err)
{
xQueueReceive(g_usb_write_complete_queue, &p_event_info, (TickType_t) portMAX_DELAY);
if (FSP_ERR_USB_FAILED != p_event_info->status)
{
if (0 == pxNetworkBuffer->xDataLength % g_usb_max_packet_size)
{
/* Send 0-Length Packet */
err = R_USB_Write(&g_basic0_ctrl, NULL, VALUE_ZERO, g_p_event_info->device_address);
xQueueReceive(g_usb_write_complete_queue, &p_event_info, (TickType_t) portMAX_DELAY);
}
xReturn = pdPASS;
}
if (pdFAIL != xReturn)
{
/* Call the standard trace macro to log the send event. */
iptraceNETWORK_INTERFACE_TRANSMIT();
}
}
}
/* The Ethernet buffer is therefore no longer needed, and must be freed for re-use. */
if (xReleaseAfterSend == pdTRUE)
{
vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);
}
return xReturn;
}
void vNetworkInterfaceAllocateRAMToBuffers (
NetworkBufferDescriptor_t pxNetworkBuffers[ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS])
{
/* Remove compiler warning about unused parameter. */
(void) pxNetworkBuffers;
}
/***********************************************************************************************************************
* private functions
**********************************************************************************************************************/
static BaseType_t prvNetworkInterfaceInput (void) {
BaseType_t xResult = pdFAIL;
fsp_err_t err;
usb_event_info_t * p_event_info;
/* Used to indicate that xSendEventStructToIPTask() is being called because
* of an Ethernet receive event. */
IPStackEvent_t xRxEvent;
NetworkBufferDescriptor_t * pxBufferDescriptor;
pxBufferDescriptor = pxGetNetworkBufferWithDescriptor((size_t) MAXIMUM_ETHERNET_FRAME_SIZE, 0);
if (NULL != pxBufferDescriptor)
{
err = R_USB_Read(&g_basic0_ctrl, g_rcv_buf, CDC_READ_DATA_LEN, g_p_event_info->device_address);
if (err != FSP_SUCCESS)
{
vReleaseNetworkBufferAndDescriptor(pxBufferDescriptor);
return xResult;
}
/* Wait for read complete */
xQueueReceive(g_usb_read_complete_queue, &p_event_info, (TickType_t) portMAX_DELAY);
if (FSP_ERR_USB_FAILED != p_event_info->status)
{
/* Setting of Recieved data and data length */
memcpy(pxBufferDescriptor->pucEthernetBuffer, g_rcv_buf, p_event_info->data_size);
pxBufferDescriptor->xDataLength = (size_t) p_event_info->data_size;
}
else
{
}
/* When driver received any data. */
if (FSP_SUCCESS == err)
{
if (eConsiderFrameForProcessing(pxBufferDescriptor->pucEthernetBuffer) == eProcessBuffer)
{
/* The event about to be sent to the TCP/IP is an Rx event. */
xRxEvent.eEventType = eNetworkRxEvent;
/* pvData is used to point to the network buffer descriptor that
* now references the received data. */
xRxEvent.pvData = (void *) pxBufferDescriptor;
/* Send the data to the TCP/IP stack. */
if (pdPASS == xSendEventStructToIPTask(&xRxEvent, 0))
{
/* The message was successfully sent to the TCP/IP stack.
* Call the standard trace macro to log the occurrence. */
iptraceNETWORK_INTERFACE_RECEIVE();
xResult = pdPASS;
}
}
}
if (pdPASS != xResult)
{
/* The buffer could not be sent to the IP task so the buffer must be released. */
vReleaseNetworkBufferAndDescriptor(pxBufferDescriptor);
iptraceETHERNET_RX_EVENT_LOST();
}
}
return xResult;
}
static void prvRXHandlerTask (void * pvParameters) {
BaseType_t xResult = pdFALSE;
/* Avoid compiler warning about unreferenced parameter. */
(void) pvParameters;
for ( ; ; )
{
vTaskDelay(ETHER_LINK_STATUS_CHECK_INTERVAL);
if (1 == g_ecm_connected)
{
while (1)
{
xResult = prvNetworkInterfaceInput();
if (pdFAIL == xResult)
{
if (1 != g_ecm_connected)
{
break;
}
}
}
}
}
}
static void prvUsbEventProcessTask (void * pvParameters) {
BaseType_t xResult = pdFALSE;
/* Avoid compiler warning about unreferenced parameter. */
(void) pvParameters;
for ( ; ; )
{
/* Handle error if queue send fails*/
if (true == g_err_flag)
{
handle_error(g_err_flag, "Error in sending usb event through queue");
}
/* Receive message from queue and analyzing the received message*/
xResult = xQueueReceive(g_usb_callback_queue, &g_p_event_info, (portMAX_DELAY));
/* Handle error */
if (pdTRUE != xResult)
{
handle_error(g_err_flag, "Error in receiving USB event message through queue");
}
vEventProcess(g_p_event_info);
}
}
__attribute__((weak)) BaseType_t xApplicationGetRandomNumber (uint32_t * pulNumber)
{
/* example of a 32-bit random number generator.
* rand() in returns a 16-bit number. so create 32 bit Random number using 16 bit rand().
* In this case just a psuedo random number is used so THIS IS NOT RECOMMENDED FOR PRODUCTION SYSTEMS.
*/
uint32_t ulRandomValue = 0;
ulRandomValue = ((((uint32_t) rand()) & UNSIGNED_SHORT_RANDOM_NUMBER_MASK)) | // NOLINT (rand() has limited randomness. But c99 does not support random)
((((uint32_t) rand()) & UNSIGNED_SHORT_RANDOM_NUMBER_MASK) << 16); // NOLINT (rand() has limited randomness. But c99 does not support random)
*(pulNumber) = ulRandomValue;
return pdTRUE;
}
BSP_WEAK_REFERENCE uint32_t ulApplicationGetNextSequenceNumber (uint32_t ulSourceAddress,
uint16_t usSourcePort,
uint32_t ulDestinationAddress,
uint16_t usDestinationPort)
{
/*
* Callback that provides the inputs necessary to generate a randomized TCP
* Initial Sequence Number per RFC 6528. In this case just a psuedo random
* number is used so THIS IS NOT RECOMMENDED FOR PRODUCTION SYSTEMS.
*/
FSP_PARAMETER_NOT_USED(ulSourceAddress);
FSP_PARAMETER_NOT_USED(ulDestinationAddress);
FSP_PARAMETER_NOT_USED(usSourcePort);
FSP_PARAMETER_NOT_USED(usDestinationPort);
uint32_t ulResult = 0;
while (0 == ulResult)
{
xApplicationGetRandomNumber(&ulResult);
}
return ulResult;
}
void handle_error (fsp_err_t err, char * err_str)
{
/* close opened USB module */
R_USB_Close(&g_basic0_ctrl);
} /* End of function handle_error() */
void usb_rtos_callback (usb_event_info_t * p_event_info, usb_hdl_t cur_task, usb_onoff_t usb_state)
{
/* Send event received to queue */
if (pdTRUE != (xQueueSend(g_usb_callback_queue, (const void *) &p_event_info, (TickType_t) (NO_WAIT_TIME))))
{
g_err_flag = true;
}
} /* End of function usb_rtos_callback */
void vSpecificDeviceRegistration (void)
{
fsp_err_t err;
err = R_USB_HCDC_SpecificDeviceRegister(&g_basic0_ctrl, USB_ECM_TEST_DEVICE_VID, USB_ECM_TEST_DEVICE_PID);
if (FSP_SUCCESS != err)
{
handle_error(g_err_flag, "R_USB_HCDC_SpecificDeviceRegister API FAILED");
}
}
void vEventProcess (usb_event_info_t * p_event_info)
{
fsp_err_t err;
switch (p_event_info->event)
{
{
err = R_USB_HCDC_DeviceInfoGet(&g_basic0_ctrl, &device_info, p_event_info->device_address);
if (FSP_SUCCESS == err)
{
if (CDC_SUB_CLASS_ECM == device_info.subclass)
{
&g_interrupt_in_rcv_buf[VALUE_ZERO],
CDC_INTERRUPT_READ_DATA_LEN,
p_event_info->device_address);
}
else if (CDC_SUB_CLASS_ACM == g_subclass)
{
/* none */
}
else
{
if ((USB_ECM_TEST_DEVICE_VID == device_info.vendor_id) &&
(USB_ECM_TEST_DEVICE_PID == device_info.product_id))
{
set_configuration0_for_asix_ax88179(&g_basic0_ctrl, p_event_info->device_address);
}
}
}
break;
}
{
if (USB_CLASS_HCDC == p_event_info->type)
{
xQueueSend(g_usb_read_complete_queue, &p_event_info, (TickType_t) portMAX_DELAY);
}
else
{
if (0 ==
memcmp((void *) g_notification_networkconnection_connect, g_interrupt_in_rcv_buf,
sizeof(g_notification_networkconnection_connect)))
{
/* Received NETWORKCONNECTION "Connected". */
g_ecm_connected = 1; /* link up */
}
else if (0 ==
memcmp((void *) g_notification_networkconnection_disconnect, g_interrupt_in_rcv_buf,
sizeof(g_notification_networkconnection_disconnect)))
{
/* Received NETWORKCONNECTION "Disconnect". */
g_ecm_connected = 0; /* link down */
}
&g_interrupt_in_rcv_buf[VALUE_ZERO],
CDC_INTERRUPT_READ_DATA_LEN,
p_event_info->device_address);
}
break;
}
{
xQueueSend(g_usb_write_complete_queue, &p_event_info, (TickType_t) portMAX_DELAY);
break;
}
{
if ((USB_SET_CONFIGURATION == (p_event_info->setup.request_type & USB_BREQUEST)) &&
(VALUE_ZERO == p_event_info->setup.request_value))
{
/* Set Configuration (3) */
set_configuration3_for_asix_ax88179(&g_basic0_ctrl, p_event_info->device_address);
}
else if ((USB_SET_CONFIGURATION == (p_event_info->setup.request_type & USB_BREQUEST)) &&
(VALUE_0003H == p_event_info->setup.request_value))
{
/* Get Configuration Descrptor (9 byte) */
get_configration_descriptor_for_asix_ax88179(&g_basic0_ctrl,
p_event_info->device_address,
(uint16_t) VALUE_9);
}
else if ((USB_GET_DESCRIPTOR == (p_event_info->setup.request_type & USB_BREQUEST)) &&
(p_event_info->data_size == VALUE_9))
{
/* Get Configuration Descrptor (all byte) */
get_configration_descriptor_for_asix_ax88179(&g_basic0_ctrl,
p_event_info->device_address,
(uint16_t) (((uint16_t) g_disc_buf[3] << 8) +
(uint16_t) g_disc_buf[2]));
}
else if ((USB_GET_DESCRIPTOR == (p_event_info->setup.request_type & USB_BREQUEST)) &&
(p_event_info->data_size > VALUE_9))
{
set_ethernet_packet_filter(&g_basic0_ctrl, p_event_info->device_address);
}
else if (SET_ETHERNET_PACKET_FILTER == (p_event_info->setup.request_type & USB_BREQUEST))
{
set_interface_for_asix_ax88179(&g_basic0_ctrl, p_event_info->device_address);
}
else if (USB_SET_INTERFACE == (p_event_info->setup.request_type & USB_BREQUEST))
{
/* Pipe setting */
memcpy(g_usb_hstd_config_descriptor[g_utr.ip], g_disc_buf,
(uint16_t) (((uint16_t) g_disc_buf[3] << 8) + (uint16_t) g_disc_buf[2]));
usb_hcdc_pipe_info(&g_utr,
(uint8_t *) g_usb_hstd_config_descriptor[g_utr.ip],
g_usb_hcdc_speed[g_utr.ip],
(uint16_t) (((uint16_t) g_disc_buf[3] << 8) + (uint16_t) g_disc_buf[2]));
usb_hcdc_set_pipe_registration(&g_utr, p_event_info->device_address);
&g_interrupt_in_rcv_buf[VALUE_ZERO],
CDC_INTERRUPT_READ_DATA_LEN,
p_event_info->device_address);
}
else
{
/* Not support request */
}
break;
}
{
g_ecm_connected = 0; /* link down */
break;
}
default:
{
/* No operation to do*/
break;
}
}
}
static void set_configuration0_for_asix_ax88179 (usb_instance_ctrl_t * p_ctrl, uint8_t device_address)
{
usb_setup_t setup;
fsp_err_t err = FSP_SUCCESS;
setup.request_value = VALUE_ZERO;
setup.request_index = VALUE_ZERO;
setup.request_length = VALUE_ZERO;
/* Request Control transfer */
err = R_USB_HostControlTransfer(p_ctrl, &setup, (uint8_t *) &g_usb_dummy, device_address);
if (FSP_SUCCESS != err)
{
handle_error(g_err_flag, "R_USB_HostControlTransfer API FAILED");
}
}
static void set_configuration3_for_asix_ax88179 (usb_instance_ctrl_t * p_ctrl, uint8_t device_address)
{
usb_setup_t setup;
fsp_err_t err = FSP_SUCCESS;
setup.request_value = VALUE_0003H;
setup.request_index = VALUE_ZERO;
setup.request_length = VALUE_ZERO;
/* Request Control transfer */
err = R_USB_HostControlTransfer(p_ctrl, &setup, (uint8_t *) &g_usb_dummy, device_address);
if (FSP_SUCCESS != err)
{
handle_error(g_err_flag, "R_USB_HostControlTransfer API FAILED");
}
}
static void get_configration_descriptor_for_asix_ax88179 (usb_instance_ctrl_t * p_ctrl,
uint8_t device_address,
uint16_t length)
{
usb_setup_t setup;
fsp_err_t err = FSP_SUCCESS;
setup.request_value = (uint16_t) USB_CONF_DESCRIPTOR | VALUE_0002H; /* 0x0002 : index of config disc */
setup.request_index = VALUE_ZERO;
setup.request_length = length;
/* Request Control transfer */
err = R_USB_HostControlTransfer(p_ctrl, &setup, (uint8_t *) &g_disc_buf, device_address);
if (FSP_SUCCESS != err)
{
handle_error(g_err_flag, "R_USB_HostControlTransfer API FAILED");
}
}
static void set_interface_for_asix_ax88179 (usb_instance_ctrl_t * p_ctrl, uint8_t device_address)
{
usb_setup_t setup;
fsp_err_t err = FSP_SUCCESS;
setup.request_value = VALUE_0001H;
setup.request_index = VALUE_0001H;
setup.request_length = VALUE_ZERO;
/* Request Control transfer */
err = R_USB_HostControlTransfer(p_ctrl, &setup, (uint8_t *) &g_usb_dummy, device_address);
if (FSP_SUCCESS != err)
{
handle_error(g_err_flag, "R_USB_HostControlTransfer API FAILED");
}
}
static void set_ethernet_packet_filter (usb_instance_ctrl_t * p_ctrl, uint8_t device_address)
{
usb_setup_t setup;
fsp_err_t err = FSP_SUCCESS;
setup.request_type = (SET_ETHERNET_PACKET_FILTER | USB_HOST_TO_DEV | USB_CLASS | USB_INTERFACE);
setup.request_value = VALUE_001FH; /* No packet filter */
setup.request_index = VALUE_0001H; /* wIndex:Interface */
setup.request_length = VALUE_ZERO; /* wLength:Zero */
err = R_USB_HostControlTransfer(p_ctrl, &setup, &g_usb_dummy, device_address);
if (FSP_SUCCESS != err)
{
handle_error(g_err_flag, "R_USB_HostControlTransfer API FAILED");
}
}

Function Documentation

◆ R_USB_HCDC_ControlDataRead()

fsp_err_t R_USB_HCDC_ControlDataRead ( usb_ctrl_t *const  p_api_ctrl,
uint8_t *  p_buf,
uint32_t  size,
uint8_t  device_address 
)

Read Control Data.(CDC Interrupt IN data)

Return values
FSP_SUCCESSSuccessfully completed (Data read request completed).
FSP_ERR_USB_FAILEDThe function could not be completed successfully.
FSP_ERR_USB_BUSYData receive request already in process for USB device with same device address.
FSP_ERR_ASSERTIONParameter is NULL error.
FSP_ERR_USB_PARAMETERParameter error.
Note
1. Do not call this API in the following function.
(1). Interrupt function.
(2). Callback function ( for RTOS ).

◆ R_USB_HCDC_SpecificDeviceRegister()

fsp_err_t R_USB_HCDC_SpecificDeviceRegister ( usb_ctrl_t *const  p_api_ctrl,
uint16_t  vendor_id,
uint16_t  product_id 
)

Register the specified vendor class device in the device table.

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_HCDC_DeviceInfoGet()

fsp_err_t R_USB_HCDC_DeviceInfoGet ( usb_ctrl_t *const  p_api_ctrl,
usb_hcdc_device_info_t p_info,
uint8_t  device_address 
)

Get the VID, PID and subclass code of the 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 ).