This module provides a USB Host Communications Device Class (HCDC) driver. It implements the USB HCDC Interface .
Refer to USB (r_usb_basic) for the common API (r_usb_basic) to be called from the application.
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:
Checks for connected devices
Implementation of communication line settings
Acquisition of the communication line state
Data transfer to and from a CDC peripheral device
Configuration
Build Time Configurations for r_usb_hcdc
The following build time configurations are defined in fsp_cfg/r_usb_hcdc_cfg.h:
Configuration Options Default Description
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).
Configuration Options Default Description
Name Name must be a valid C symbol g_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:
Verify connected devices
Make communication line settings
Acquire the communication line state
Transfer data to and from the CDC peripheral device
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.
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:
Suspend is not supported when a data transfer is in progress. Confirm that data transfer has completed before executing suspend.
Use of compound USB devices with CDC class support is not supported.
This module must be incorporated into a project using r_usb_basic and does not provide any public APIs.
This driver does not support Low-speed.
This driver does not support simultaneous operation with the other device class.
CDC-ECM requires a TCP/IP driver for USB driver on the upper layer.
The user needs to support the porting layer for TCP/IP when using CDC-ECM.
CDC-ECM works on FreeRTOS.
CDC-ECM was evaluated using the following USB to Ethernet adapter.
UGREEN USB to Ethernet Adapater RJ45 (Manufacture: Ugreen Group Limited, Item modle number: 50922)
Examples
USB HCDC Loopback Example
The main functions of the HCDC loopback example are as follows:
Virtual UART control settings are configured by transmitting the class request SET_LINE_CODING to the CDC device.
Sends receive (Bulk In transfer) requests to a CDC peripheral device and receives data.
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)
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));
}
#endif
void usb_hcdc_example (void )
{
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)
xQueueReceive(g_apl_mbx_hdl, (void *) &p_mess, portMAX_DELAY);
event_info = *p_mess;
event = event_info.event;
#else
g_usb_on_usb.
eventGet (&event_info, &event);
#endif
switch (event)
{
set_line_coding(&g_basic0_ctrl, event_info.device_address);
break ;
{
if (event_info.data_size > 0)
{
g_usb_on_usb.
write (&g_basic0_ctrl, g_snd_buf, event_info.data_size, USB_DEVICE_ADDRESS_1);
}
else
{
g_usb_on_usb.
read (&g_basic0_ctrl, g_rcv_buf, CDC_DATA_LEN, USB_DEVICE_ADDRESS_1);
}
}
else
{
g_usb_on_usb.
read (&g_basic0_ctrl,
(uint8_t *) &g_serial_state,
USB_HCDC_SERIAL_STATE_MSG_LEN,
USB_DEVICE_ADDRESS_1);
}
break ;
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_control_line_state(&g_basic0_ctrl, event_info.device_address);
}
else if (USB_CDC_SET_CONTROL_LINE_STATE == (event_info.setup.request_type &
USB_BREQUEST ))
{
get_line_coding(&g_basic0_ctrl, event_info.device_address);
}
else if (USB_CDC_GET_LINE_CODING == (event_info.setup.request_type &
USB_BREQUEST ))
{
g_usb_on_usb.
read (&g_basic0_ctrl, g_snd_buf, CDC_DATA_LEN, USB_DEVICE_ADDRESS_1);
}
else
{
}
break ;
default :
break ;
}
}
}
{
usb_setup_t setup;
setup.request_type = SET_CONTROL_LINE_STATE;
setup.request_value = 0x0000;
setup.request_index = 0x0000;
setup.request_length = 0x0000;
}
{
usb_setup_t setup;
setup.request_type = SET_LINE_CODING;
setup.request_value = 0x0000;
setup.request_index = 0x0000;
setup.request_length = LINE_CODING_LENGTH;
}
{
usb_setup_t setup;
setup.request_type = GET_LINE_CODING;
setup.request_value = 0x0000;
setup.request_index = 0x0000;
setup.request_length = LINE_CODING_LENGTH;
}
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
char * domain_name = USR_TEST_DOMAIN_NAME;
#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)
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 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 )
{
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)
{
return (ulSourceAddress + ulDestinationAddress + usSourcePort + usDestinationPort) && ulRand();
}
BaseType_t vSendPing (const char * pcIPAddress)
{
uint32_t ulIPAddress = RESET_VALUE;
ulIPAddress = FreeRTOS_inet_addr(pcIPAddress);
return FreeRTOS_SendPingRequest(ulIPAddress, 8, 1000000 / portTICK_PERIOD_MS);
}
void vApplicationPingReplyHook (ePingReplyStatus_t eStatus, uint16_t usIdentifier)
{
(void) usIdentifier;
switch (eStatus)
{
case eSuccess:
ping_data.received++;
break ;
case eInvalidData:
default :
ping_data.lost++;
break ;
}
}
uint32_t isNetworkUp (void )
{
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)
{
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;
#if defined USE_PING_SEND_DEMO
#elif defined USE_TCP_CLIENT_DEMO
Socket_t xClientSocket;
BaseType_t lBytesReceived;
#endif
APP_PRINT(BANNER_INFO,
EP_VERSION,
version.version_id_b.
major ,
version.version_id_b.
minor ,
version.version_id_b.
patch );
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,
&xLinkStatusCheckTaskHandle);
#endif
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)
if (SUCCESS == isNetworkUp())
{
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))
{
updateDhcpResponseToUsr();
print_ipconfig();
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)
{
status = vSendPing((char *) remote_ip_address);
if (status != pdFALSE)
{
ping_data.sent++;
APP_PRINT("!" );
}
else
{
ping_data.lost++;
APP_PRINT("." );
}
usrPingCount++;
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
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())
{
xClientSocket = vCreateTCPClientSocket();
while (1)
{
if (pdTRUE == xConnectToTCPServer(xClientSocket))
{
break ;
}
vTaskDelay(1000);
}
lBytesReceived = FreeRTOS_recv(xClientSocket, &cRxedData, BUFFER_SIZE, 0);
if (lBytesReceived > 0)
{
memcpy(&cTxData, &cRxedData, (size_t ) lBytesReceived);
FreeRTOS_send(xClientSocket, &cTxData, (size_t ) lBytesReceived, 0);
vTaskDelay(1000);
}
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);
xClientSocket = FreeRTOS_socket(FREERTOS_AF_INET,
FREERTOS_SOCK_STREAM,
FREERTOS_IPPROTO_TCP);
configASSERT(xClientSocket != FREERTOS_INVALID_SOCKET);
FreeRTOS_setsockopt(xClientSocket, 0, FREERTOS_SO_RCVTIMEO, &xTimeOut, sizeof (xTimeOut));
FreeRTOS_setsockopt(xClientSocket, 0, FREERTOS_SO_SNDTIMEO, &xTimeOut, sizeof (xTimeOut));
if (xClientSocket != FREERTOS_INVALID_SOCKET)
{
xBindAddress.sin_port = FreeRTOS_htons(9999);
if (FreeRTOS_bind(xClientSocket, &xBindAddress, sizeof (xBindAddress)) == 0)
{
}
else
{
while (1)
{
;
}
}
}
else
{
while (1)
{
;
}
}
return xClientSocket;
}
BaseType_t xConnectToTCPServer (Socket_t xSocket)
{
BaseType_t ret;
struct freertos_sockaddr xRemoteAddress;
xRemoteAddress.sin_addr = FreeRTOS_inet_addr_quick(192, 168, 10, 1);
xRemoteAddress.sin_port = FreeRTOS_htons(4000);
ret = FreeRTOS_connect(xSocket, &xRemoteAddress, sizeof (xRemoteAddress));
if (ret == 0)
{
ret = pdTRUE;
}
else
{
ret = pdFALSE;
}
return ret;
}
void vCloseTCPClientSocket (Socket_t xSocket)
{
FreeRTOS_shutdown(xSocket, FREERTOS_SHUT_RDWR);
while (FreeRTOS_recv(xSocket, &cRxedData, BUFFER_SIZE, 0) >= 0)
{
vTaskDelay(250);
}
FreeRTOS_closesocket(xSocket);
}
#endif
#if (USE_DHCP_CLIENT_DEMO != 0)
eDHCPCallbackAnswer_t xApplicationDHCPHook (eDHCPCallbackPhase_t eDHCPPhase, uint32_t ulIPAddress)
{
eDHCPCallbackAnswer_t eReturn = eDHCPContinue;
switch (eDHCPPhase)
{
case eDHCPPhasePreDiscover:
break ;
case eDHCPPhasePreRequest:
xNetworkAddressing.ulDefaultIPAddress = ulIPAddress;
dhcp_in_use = 1;
break ;
default :
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};
ulIPAddress = FreeRTOS_gethostbyname((char *) domain);
if (ulIPAddress != 0)
{
FreeRTOS_inet_ntoa(ulIPAddress, (char *) cBuffer);
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
#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)
#define USB_ECM_TEST_DEVICE_PID (0x1790)
volatile bool g_err_flag = false ;
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;
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};
static uint8_t g_rcv_buf[CDC_READ_DATA_LEN] BSP_ALIGN_VARIABLE(4) = {VALUE_ZERO};
static uint32_t g_usb_max_packet_size;
static uint8_t g_interrupt_in_rcv_buf[64] BSP_ALIGN_VARIABLE(4) = {VALUE_ZERO};
static uint8_t g_usb_dummy = VALUE_ZERO;
static uint8_t g_disc_buf[512] BSP_ALIGN_VARIABLE(4) = {VALUE_ZERO};
static uint8_t g_subclass = VALUE_ZERO;
static const uint8_t g_notification_networkconnection_connect[8] =
{
0xA1,
0x00,
0x01,
0x00,
0x01,
0x00,
0x00,
0x00
};
static const uint8_t g_notification_networkconnection_disconnect[8] =
{
0xA1,
0x00,
0x00,
0x00,
0x01,
0x00,
0x00,
0x00
};
extern void vSpecificDeviceRegistration(void );
extern void vEventProcess(usb_event_info_t * p_event_info);
void handle_error(
fsp_err_t err,
char * err_str);
void vSpecificDeviceRegistration(void );
void vEventProcess(usb_event_info_t * p_event_info);
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);
uint8_t device_address,
uint16_t length);
static void set_interface_for_asix_ax88179(
usb_instance_ctrl_t * p_ctrl, uint8_t device_address);
BaseType_t xNetworkInterfaceInitialise (void )
{
BaseType_t xReturn = pdFAIL;
g_utr.ipp = usb_hstd_get_usb_ip_adr((uint16_t) g_basic0_cfg.
module_number );
#if (USB_CFG_DMA == USB_CFG_ENABLE)
#endif
{
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();
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)
{
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
{
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)
{
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)
{
iptraceNETWORK_INTERFACE_TRANSMIT();
}
}
}
if (xReleaseAfterSend == pdTRUE)
{
vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);
}
return xReturn;
}
void vNetworkInterfaceAllocateRAMToBuffers (
NetworkBufferDescriptor_t pxNetworkBuffers[ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS])
{
(void) pxNetworkBuffers;
}
static BaseType_t prvNetworkInterfaceInput (void ) {
BaseType_t xResult = pdFAIL;
usb_event_info_t * p_event_info;
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;
}
xQueueReceive(g_usb_read_complete_queue, &p_event_info, (TickType_t) portMAX_DELAY);
if (FSP_ERR_USB_FAILED != p_event_info->status)
{
memcpy(pxBufferDescriptor->pucEthernetBuffer, g_rcv_buf, p_event_info->data_size);
pxBufferDescriptor->xDataLength = (size_t) p_event_info->data_size;
}
else
{
}
if (FSP_SUCCESS == err)
{
if (eConsiderFrameForProcessing(pxBufferDescriptor->pucEthernetBuffer) == eProcessBuffer)
{
xRxEvent.eEventType = eNetworkRxEvent;
xRxEvent.pvData = (void *) pxBufferDescriptor;
if (pdPASS == xSendEventStructToIPTask(&xRxEvent, 0))
{
iptraceNETWORK_INTERFACE_RECEIVE();
xResult = pdPASS;
}
}
}
if (pdPASS != xResult)
{
vReleaseNetworkBufferAndDescriptor(pxBufferDescriptor);
iptraceETHERNET_RX_EVENT_LOST();
}
}
return xResult;
}
static void prvRXHandlerTask (void * pvParameters) {
BaseType_t xResult = pdFALSE;
(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;
(void) pvParameters;
for ( ; ; )
{
if (true == g_err_flag)
{
handle_error(g_err_flag, "Error in sending usb event through queue" );
}
xResult = xQueueReceive(g_usb_callback_queue, &g_p_event_info, (portMAX_DELAY));
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)
{
uint32_t ulRandomValue = 0;
ulRandomValue = ((((uint32_t) rand()) & UNSIGNED_SHORT_RANDOM_NUMBER_MASK)) |
((((uint32_t) rand()) & UNSIGNED_SHORT_RANDOM_NUMBER_MASK) << 16);
*(pulNumber) = ulRandomValue;
return pdTRUE;
}
BSP_WEAK_REFERENCE uint32_t ulApplicationGetNextSequenceNumber (uint32_t ulSourceAddress,
uint16_t usSourcePort,
uint32_t ulDestinationAddress,
uint16_t usDestinationPort)
{
uint32_t ulResult = 0;
while (0 == ulResult)
{
xApplicationGetRandomNumber(&ulResult);
}
return ulResult;
}
void handle_error (
fsp_err_t err,
char * err_str)
{
}
void usb_rtos_callback (usb_event_info_t * p_event_info, usb_hdl_t cur_task,
usb_onoff_t usb_state)
{
if (pdTRUE != (xQueueSend(g_usb_callback_queue, (const void *) &p_event_info, (TickType_t) (NO_WAIT_TIME))))
{
g_err_flag = true ;
}
}
void vSpecificDeviceRegistration (void )
{
if (FSP_SUCCESS != err)
{
handle_error(g_err_flag, "R_USB_HCDC_SpecificDeviceRegister API FAILED" );
}
}
void vEventProcess (usb_event_info_t * p_event_info)
{
switch (p_event_info->event)
{
{
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)
{
}
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 ;
}
{
{
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)))
{
g_ecm_connected = 1;
}
else if (0 ==
memcmp((void *) g_notification_networkconnection_disconnect, g_interrupt_in_rcv_buf,
sizeof (g_notification_networkconnection_disconnect)))
{
g_ecm_connected = 0;
}
&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 ;
}
{
(VALUE_ZERO == p_event_info->setup.request_value))
{
set_configuration3_for_asix_ax88179(&g_basic0_ctrl, p_event_info->device_address);
}
(VALUE_0003H == p_event_info->setup.request_value))
{
get_configration_descriptor_for_asix_ax88179(&g_basic0_ctrl,
p_event_info->device_address,
(uint16_t) VALUE_9);
}
(p_event_info->data_size == VALUE_9))
{
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]));
}
(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);
}
{
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
{
}
break ;
}
{
g_ecm_connected = 0;
break ;
}
default :
{
break ;
}
}
}
static void set_configuration0_for_asix_ax88179 (
usb_instance_ctrl_t * p_ctrl, uint8_t device_address)
{
usb_setup_t setup;
setup.request_value = VALUE_ZERO;
setup.request_index = VALUE_ZERO;
setup.request_length = VALUE_ZERO;
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;
setup.request_value = VALUE_0003H;
setup.request_index = VALUE_ZERO;
setup.request_length = VALUE_ZERO;
if (FSP_SUCCESS != err)
{
handle_error(g_err_flag, "R_USB_HostControlTransfer API FAILED" );
}
}
uint8_t device_address,
uint16_t length)
{
usb_setup_t setup;
setup.request_value = (uint16_t) USB_CONF_DESCRIPTOR | VALUE_0002H;
setup.request_index = VALUE_ZERO;
setup.request_length = length;
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;
setup.request_value = VALUE_0001H;
setup.request_index = VALUE_0001H;
setup.request_length = VALUE_ZERO;
if (FSP_SUCCESS != err)
{
handle_error(g_err_flag, "R_USB_HostControlTransfer API FAILED" );
}
}
{
usb_setup_t setup;
setup.request_value = VALUE_001FH;
setup.request_index = VALUE_0001H;
setup.request_length = VALUE_ZERO;
if (FSP_SUCCESS != err)
{
handle_error(g_err_flag, "R_USB_HostControlTransfer API FAILED" );
}
}
◆ 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_SUCCESS Successfully completed (Data read request completed).
FSP_ERR_USB_FAILED The function could not be completed successfully.
FSP_ERR_USB_BUSY Data receive request already in process for USB device with same device address.
FSP_ERR_ASSERTION Parameter is NULL error.
FSP_ERR_USB_PARAMETER Parameter 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_SUCCESS Successfully completed.
FSP_ERR_USB_FAILED The function could not be completed successfully.
FSP_ERR_ASSERTION Parameter Null pointer error.
FSP_ERR_USB_PARAMETER Parameter error.
Note (1). Interrupt function.
(2). Callback function ( for RTOS ).
◆ R_USB_HCDC_DeviceInfoGet()
Get the VID, PID and subclass code of the connected device.
Return values
FSP_SUCCESS Successfully completed.
FSP_ERR_USB_FAILED The function could not be completed successfully.
FSP_ERR_ASSERTION Parameter Null pointer error.
FSP_ERR_USB_PARAMETER Parameter error.
Note (1). Interrupt function.
(2). Callback function ( for RTOS ).