Implement application specific behavior of a Communication Device Class (CDC) USB Device using the sub-class Network Control Model (NCM) for Ethernet-over-USB applications.
More...
Implement application specific behavior of a Communication Device Class (CDC) USB Device using the sub-class Network Control Model (NCM) for Ethernet-over-USB applications.
The USB Component allows multiple instances of the CDC class. This feature is used to create USB Composite Devices. Each CDC class instance has a separate files and interface functions:
The necessary descriptors are automatically generated by the USB Middleware Component. The page USB Descriptors provides more information on the topic.
The thread USBD_CDCn_Int_Thread handles Interrupt IN Endpoint whereas the USBD_CDCn_Bulk_Thread handles the Bulk IN and Bulk OUT Endpoints.
The following source code contains all the required callback functions and can be used to implement the application specific behavior of a USB CDC (NCM) Device.
#include <stdio.h>
#include <string.h>
#include "rl_usb.h"
#include "USBD_Config_CDC_n.h"
#define USB_CDC_NUM n
#define MAX_IN_DATAGRAMS 10
static const wchar_t *wsMacAddress = USBD_CDCn_NCM_MAC_ADDRESS;
static uint8_t MacAddress[6];
static uint16_t LinkState;
static uint32_t LinkSpeed;
static struct {
uint32_t ntb_input_size;
uint16_t ntb_format;
uint16_t max_datagram_size;
uint16_t crc_mode;
#if ((USBD_CDCn_NCM_BM_NETWORK_CAPABILITIES & 0x02) != 0)
uint8_t net_address[6];
#endif
#if (USBD_CDCn_NCM_W_NUMBER_MC_FILTERS != 0)
uint8_t mc_filters[6*(USBD_CDCn_NCM_W_NUMBER_MC_FILTERS & 0x7FFF)];
#endif
#if (USBD_CDCn_NCM_B_NUMBER_POWER_FILTERS != 0)
uint8_t power_filter_active[(USBD_CDCn_NCM_B_NUMBER_POWER_FILTERS + 7)/8];
#endif
uint16_t packet_filter_bitmap;
#if (USBD_CDCn_NCM_BM_ETHERNET_STATISTICS != 0)
uint32_t eth_statistics[29];
#endif
} NCM_State;
static uint32_t FrameIN_Size;
static uint8_t FrameIN [USBD_CDCn_NCM_W_MAX_SEGMENT_SIZE];
static uint8_t FrameOUT[USBD_CDCn_NCM_W_MAX_SEGMENT_SIZE];
#ifdef USB_CMSIS_RTOS2
static void Connection_Thread (void *arg);
static void DataIN_Thread (void *arg);
static void DataOUT_Thread (void *arg);
#ifdef USB_CMSIS_RTOS2_RTX5
static osRtxThread_t connection_thread_cb_mem __SECTION(.bss.os.thread.cb);
static uint64_t connection_thread_stack_mem[512/8] __SECTION(.bss.os.thread.stack);
static osRtxThread_t data_in_thread_cb_mem __SECTION(.bss.os.thread.cb);
static uint64_t data_in_thread_stack_mem [512/8] __SECTION(.bss.os.thread.stack);
static osRtxThread_t data_out_thread_cb_mem __SECTION(.bss.os.thread.cb);
static uint64_t data_out_thread_stack_mem [512/8] __SECTION(.bss.os.thread.stack);
#endif
static const osThreadAttr_t connection_thread_attr = {
"Connection_Thread",
0U,
#ifdef USB_CMSIS_RTOS2_RTX5
&connection_thread_cb_mem,
sizeof(osRtxThread_t),
&connection_thread_stack_mem[0],
#else
NULL,
0U,
NULL,
#endif
512U,
osPriorityNormal,
0U,
0U
};
static const osThreadAttr_t data_in_thread_attr = {
"DataIN_Thread",
0U,
#ifdef USB_CMSIS_RTOS2_RTX5
&data_in_thread_cb_mem,
sizeof(osRtxThread_t),
&data_in_thread_stack_mem[0],
#else
NULL,
0U,
NULL,
#endif
512U,
osPriorityNormal,
0U,
0U
};
static const osThreadAttr_t data_out_thread_attr = {
"DataOUT_Thread",
0U,
#ifdef USB_CMSIS_RTOS2_RTX5
&data_out_thread_cb_mem,
sizeof(osRtxThread_t),
&data_out_thread_stack_mem[0],
#else
NULL,
0U,
NULL,
#endif
512U,
osPriorityNormal,
0U,
0U
};
#else
static void Connection_Thread (void const *arg);
static void DataIN_Thread (void const *arg);
static void DataOUT_Thread (void const *arg);
extern const osThreadDef_t os_thread_def_Connection_Thread;
osThreadDef(Connection_Thread, osPriorityNormal, 1, NULL);
extern const osThreadDef_t os_thread_def_DataIN_Thread;
osThreadDef(DataIN_Thread, osPriorityNormal, 1, NULL);
extern const osThreadDef_t os_thread_def_DataOUT_Thread;
osThreadDef(DataOUT_Thread, osPriorityNormal, 1, NULL);
#endif
static void *Connection_ThreadId;
static void *DataIN_ThreadId;
static void *DataOUT_ThreadId;
static void MAC_wstr_to_addr (const wchar_t *wstr, uint8_t *addr) {
uint8_t c;
uint8_t n;
uint32_t i;
for (i = 0U; i < 12U; i++) {
c = (uint8_t)wstr[i];
if ((c >= '0') && (c <= '9')) {
n = c - '0';
} else if ((c >= 'A') && (c <= 'F')) {
n = c - ('A' + 10U);
} else if ((c >= 'a') && (c <= 'f')) {
n = c - ('a' + 10U);
} else {
n = 0U;
}
if ((i & 1U) != 0U) {
addr[i>>1] |= n;
} else {
addr[i>>1] = (uint8_t)((uint32_t)n << 4);
}
}
}
MAC_wstr_to_addr(wsMacAddress, MacAddress);
memset(&NCM_State, 0, sizeof(NCM_State));
NCM_State.ntb_input_size = USBD_CDCn_NCM_DW_NTB_IN_MAX_SIZE;
NCM_State.max_datagram_size = USBD_CDCn_NCM_W_MAX_SEGMENT_SIZE;
#if ((USBD_CDCn_NCM_BM_NETWORK_CAPABILITIES & 0x02) != 0)
memcpy(NCM_State.net_address, MacAddress, 6);
#endif
NCM_State.packet_filter_bitmap = 0x0CU;
LinkState = 0U;
LinkSpeed = 0U;
FrameIN_Size = 0U;
memset(FrameIN, 0, sizeof(FrameIN));
#ifdef USB_CMSIS_RTOS2
Connection_ThreadId = osThreadNew(Connection_Thread, NULL, &connection_thread_attr);
DataIN_ThreadId = osThreadNew(DataIN_Thread, NULL, &data_in_thread_attr);
DataOUT_ThreadId = osThreadNew(DataOUT_Thread, NULL, &data_out_thread_attr);
#else
Connection_ThreadId = osThreadCreate(osThread(Connection_Thread), NULL);
DataIN_ThreadId = osThreadCreate(osThread(DataIN_Thread), NULL);
DataOUT_ThreadId = osThreadCreate(osThread(DataOUT_Thread), NULL);
#endif
}
(void)osThreadTerminate(Connection_ThreadId);
(void)osThreadTerminate(DataIN_ThreadId);
(void)osThreadTerminate(DataOUT_ThreadId);
}
}
#ifdef USB_CMSIS_RTOS2
(void)osThreadFlagsSet(Connection_ThreadId, 1U);
(void)osThreadFlagsSet(DataIN_ThreadId, 1U);
#else
(void)osSignalSet(Connection_ThreadId, 1U);
(void)osSignalSet(DataIN_ThreadId, 1U);
#endif
}
FrameIN_Size = 0U;
#ifdef USB_CMSIS_RTOS
osSignalClear(DataIN_ThreadId, 1U);
#endif
memset(&NCM_State, 0, sizeof(NCM_State));
NCM_State.ntb_input_size = USBD_CDCn_NCM_DW_NTB_IN_MAX_SIZE;
NCM_State.max_datagram_size = USBD_CDCn_NCM_W_MAX_SEGMENT_SIZE;
#if ((USBD_CDCn_NCM_BM_NETWORK_CAPABILITIES & 0x02) != 0)
memcpy(NCM_State.net_address, MacAddress, 6);
#endif
NCM_State.packet_filter_bitmap = 0x0CU;
}
#if (USBD_CDCn_NCM_W_NUMBER_MC_FILTERS != 0)
if (num_of_filters > (USBD_CDCn_NCM_W_NUMBER_MC_FILTERS & 0x7FFF)) { return false; }
memcpy(NCM_State.mc_filters, addr_list, num_of_filters * 6);
return true;
#else
(void)addr_list;
(void)num_of_filters;
return false;
#endif
}
#if (USBD_CDCn_NCM_B_NUMBER_POWER_FILTERS != 0)
if (filter_number >= USBD_CDCn_NCM_B_NUMBER_POWER_FILTERS) { return false; }
NCM_State.power_filter_active[filter_number / 8] |= 1U << (filter_number % 8);
return true;
#else
(void)filter_number;
(void)pattern_filter;
(void)pattern_filter_size;
return false;
#endif
}
#if (USBD_CDCn_NCM_B_NUMBER_POWER_FILTERS != 0)
*pattern_active = (NCM_State.power_filter_active[filter_number / 8] & (1U << (filter_number % 8))) ? 1 : 0;
return true;
#else
(void)filter_number;
(void)pattern_active;
return false;
#endif
}
#if ((USBD_CDCn_NCM_BM_NETWORK_CAPABILITIES & 0x01) != 0)
NCM_State.packet_filter_bitmap = packet_filter_bitmap;
return true;
#else
(void)packet_filter_bitmap;
return false;
#endif
}
#if (USBD_CDCn_NCM_BM_ETHERNET_STATISTICS != 0)
if (feature_selector == 0x00U) { return true; }
if (feature_selector > 0x1DU) { return false; }
*data = NCM_State.eth_statistics[feature_selector - 1];
return true;
#else
(void)feature_selector;
(void)data;
return false;
#endif
}
ntb_params->Reserved0 = 0U;
ntb_params->Reserved1 = 0U;
return true;
}
#if ((USBD_CDCn_NCM_BM_NETWORK_CAPABILITIES & 0x02) != 0)
memcpy(net_addr, NCM_State.net_address, 6);
return true;
#else
(void)net_addr;
return false;
#endif
}
#if ((USBD_CDCn_NCM_BM_NETWORK_CAPABILITIES & 0x02) != 0)
memcpy(NCM_State.net_address, net_addr, 6);
return true;
#else
(void)net_addr;
return false;
#endif
}
*ntb_format = NCM_State.ntb_format;
return true;
}
#if (USBD_CDCn_NCM_BM_NTB_FORMATS_SUPPORTED > 1)
if (ntb_format > 1) { return false; }
#else
if (ntb_format > 0) { return false; }
#endif
NCM_State.ntb_format = ntb_format;
return true;
}
*ntb_input_size = NCM_State.ntb_input_size;
return true;
}
if (ntb_input_size > USBD_CDCn_NCM_DW_NTB_IN_MAX_SIZE) { return false; }
NCM_State.ntb_input_size = ntb_input_size;
return true;
}
#if ((USBD_CDCn_NCM_BM_NETWORK_CAPABILITIES & 0x08) != 0)
*max_datagram_size = NCM_State.max_datagram_size;
return true;
#else
(void)max_datagram_size;
return false;
#endif
}
#if ((USBD_CDCn_NCM_BM_NETWORK_CAPABILITIES & 0x08) != 0)
if (max_datagram_size > USBD_CDCn_NCM_W_MAX_SEGMENT_SIZE) { return false; }
NCM_State.max_datagram_size = max_datagram_size;
return true;
#else
(void)max_datagram_size;
return false;
#endif
}
#if ((USBD_CDCn_NCM_BM_NETWORK_CAPABILITIES & 0x10) != 0)
*crc_mode = NCM_State.crc_mode;
return true;
#else
(void)crc_mode;
return false;
#endif
}
#if ((USBD_CDCn_NCM_BM_NETWORK_CAPABILITIES & 0x10) != 0)
if (crc_mode > 1) { return false; }
NCM_State.crc_mode = crc_mode;
return true;
#else
(void)crc_mode;
return false;
#endif
}
#ifdef USB_CMSIS_RTOS2
(void)osThreadFlagsSet(DataIN_ThreadId, 1U);
#else
(void)osSignalSet(DataIN_ThreadId, 1U);
#endif
}
#ifdef USB_CMSIS_RTOS2
(void)osThreadFlagsSet(DataOUT_ThreadId, 1U);
#else
(void)osSignalSet(DataOUT_ThreadId, 1U);
#endif
}
#ifdef USB_CMSIS_RTOS2
__NO_RETURN static void Connection_Thread (void *arg) {
#else
__NO_RETURN static void Connection_Thread (void const *arg) {
#endif
#ifdef USB_CMSIS_RTOS
osEvent os_event;
#endif
uint32_t event;
uint32_t speed;
uint16_t state;
int32_t status;
(void)(arg);
for (;;) {
#ifdef USB_CMSIS_RTOS2
event = osThreadFlagsWait(1U, osFlagsWaitAll, 500U);
#else
os_event = osSignalWait(1U, 500U);
if (os_event.status == osEventSignal) {
event = (uint32_t)os_event.value.signals;
} else {
event = 0x80000000U;
}
#endif
state = 1U;
speed = 100000000U;
if (speed != LinkSpeed) {
LinkSpeed = speed;
do {
}
if (state != LinkState) {
LinkState = state;
do {
}
if ((event & 0x80000000U) == 0U) {
if (LinkState == 1U) {
do {
}
do {
}
}
}
#ifdef USB_CMSIS_RTOS2
__NO_RETURN static void DataIN_Thread (void *arg) {
#else
__NO_RETURN static void DataIN_Thread (void const *arg) {
#endif
uint32_t size;
uint32_t len;
int32_t status;
(void)arg;
size = 0U;
len = 0U;
for (;;) {
#ifdef USB_CMSIS_RTOS2
(void)osThreadFlagsWait(3U, osFlagsWaitAll, osWaitForever);
#else
(void)osSignalWait(3U, osWaitForever);
#endif
if (status != (int32_t)
usbOK) {
continue; }
if (status != (int32_t)
usbOK) {
continue; }
for (;;) {
if (FrameIN_Size != 0) {
FrameIN_Size = 0;
}
(void)size;
(void)len;
break;
}
}
}
#ifdef USB_CMSIS_RTOS2
__NO_RETURN static void DataOUT_Thread (void *arg) {
#else
__NO_RETURN static void DataOUT_Thread (void const *arg) {
#endif
uint32_t size;
int32_t len, status;
(void)(arg);
for (;;) {
#ifdef USB_CMSIS_RTOS2
(void)osThreadFlagsWait(1U, osFlagsWaitAll, osWaitForever);
#else
(void)osSignalWait(1U, osWaitForever);
#endif
for (;;) {
if (status != (int32_t)
usbOK) {
break; }
for (;;) {
if (size == 0U) { break; }
if ((size < 14U) || (size > NCM_State.max_datagram_size)) {
continue;
}
if (len > 0) {
}
}
}
}
}
The following source code contains all the required callback functions and can be used to implement the application specific behavior of a USB CDC (NCM) Device with Ethernet-over-USB functionality.
#include <stdio.h>
#include <string.h>
#include "rl_usb.h"
#include "Driver_ETH_MAC.h"
#include "Driver_ETH_PHY.h"
#include "USBD_Config_CDC_n.h"
#define ETH_MAC_NUM 0
#define ETH_PHY_NUM 0
#define USB_CDC_NUM n
#define MAX_IN_DATAGRAMS 10
extern ARM_DRIVER_ETH_MAC ARM_Driver_ETH_MAC_(ETH_MAC_NUM);
extern ARM_DRIVER_ETH_PHY ARM_Driver_ETH_PHY_(ETH_PHY_NUM);
static ARM_DRIVER_ETH_MAC *EthMac = &ARM_Driver_ETH_MAC_(ETH_MAC_NUM);
static ARM_DRIVER_ETH_PHY *EthPhy = &ARM_Driver_ETH_PHY_(ETH_PHY_NUM);
static const wchar_t *wsMacAddress = USBD_CDCn_NCM_MAC_ADDRESS;
static ARM_ETH_MAC_ADDR MacAddress;
static ARM_ETH_LINK_STATE LinkState;
static ARM_ETH_LINK_INFO LinkInfo;
static uint32_t LinkSpeed;
static uint32_t PacketFilter;
static struct {
uint32_t ntb_input_size;
uint16_t ntb_format;
uint16_t max_datagram_size;
uint16_t crc_mode;
#if ((USBD_CDCn_NCM_BM_NETWORK_CAPABILITIES & 0x02) != 0)
uint8_t net_address[6];
#endif
#if (USBD_CDCn_NCM_W_NUMBER_MC_FILTERS != 0)
uint8_t mc_filters[6*(USBD_CDCn_NCM_W_NUMBER_MC_FILTERS & 0x7FFF)];
#endif
#if (USBD_CDCn_NCM_B_NUMBER_POWER_FILTERS != 0)
uint8_t power_filter_active[(USBD_CDCn_NCM_B_NUMBER_POWER_FILTERS + 7)/8];
#endif
uint16_t packet_filter_bitmap;
#if (USBD_CDCn_NCM_BM_ETHERNET_STATISTICS != 0)
uint32_t eth_statistics[29];
#endif
} NCM_State;
static uint32_t FrameIN_Size;
static uint8_t FrameIN [USBD_CDCn_NCM_W_MAX_SEGMENT_SIZE];
static uint8_t FrameOUT[USBD_CDCn_NCM_W_MAX_SEGMENT_SIZE];
static void EthMac_Notify (uint32_t event);
#ifdef USB_CMSIS_RTOS2
static void Connection_Thread (void *arg);
static void DataIN_Thread (void *arg);
static void DataOUT_Thread (void *arg);
#ifdef USB_CMSIS_RTOS2_RTX5
static osRtxThread_t connection_thread_cb_mem __SECTION(.bss.os.thread.cb);
static uint64_t connection_thread_stack_mem[512/8] __SECTION(.bss.os.thread.stack);
static osRtxThread_t data_in_thread_cb_mem __SECTION(.bss.os.thread.cb);
static uint64_t data_in_thread_stack_mem [512/8] __SECTION(.bss.os.thread.stack);
static osRtxThread_t data_out_thread_cb_mem __SECTION(.bss.os.thread.cb);
static uint64_t data_out_thread_stack_mem [512/8] __SECTION(.bss.os.thread.stack);
#endif
static const osThreadAttr_t connection_thread_attr = {
"Connection_Thread",
0U,
#ifdef USB_CMSIS_RTOS2_RTX5
&connection_thread_cb_mem,
sizeof(osRtxThread_t),
&connection_thread_stack_mem[0],
#else
NULL,
0U,
NULL,
#endif
512U,
osPriorityNormal,
0U,
0U
};
static const osThreadAttr_t data_in_thread_attr = {
"DataIN_Thread",
0U,
#ifdef USB_CMSIS_RTOS2_RTX5
&data_in_thread_cb_mem,
sizeof(osRtxThread_t),
&data_in_thread_stack_mem[0],
#else
NULL,
0U,
NULL,
#endif
512U,
osPriorityNormal,
0U,
0U
};
static const osThreadAttr_t data_out_thread_attr = {
"DataOUT_Thread",
0U,
#ifdef USB_CMSIS_RTOS2_RTX5
&data_out_thread_cb_mem,
sizeof(osRtxThread_t),
&data_out_thread_stack_mem[0],
#else
NULL,
0U,
NULL,
#endif
512U,
osPriorityNormal,
0U,
0U
};
#else
static void Connection_Thread (void const *arg);
static void DataIN_Thread (void const *arg);
static void DataOUT_Thread (void const *arg);
extern const osThreadDef_t os_thread_def_Connection_Thread;
osThreadDef(Connection_Thread, osPriorityNormal, 1, NULL);
extern const osThreadDef_t os_thread_def_DataIN_Thread;
osThreadDef(DataIN_Thread, osPriorityNormal, 1, NULL);
extern const osThreadDef_t os_thread_def_DataOUT_Thread;
osThreadDef(DataOUT_Thread, osPriorityNormal, 1, NULL);
#endif
static void *Connection_ThreadId;
static void *DataIN_ThreadId;
static void *DataOUT_ThreadId;
static void MAC_wstr_to_addr (const wchar_t *wstr, uint8_t *addr) {
uint8_t c;
uint8_t n;
uint32_t i;
for (i = 0U; i < 12U; i++) {
c = (uint8_t)wstr[i];
if ((c >= '0') && (c <= '9')) {
n = c - '0';
} else if ((c >= 'A') && (c <= 'F')) {
n = c - ('A' + 10U);
} else if ((c >= 'a') && (c <= 'f')) {
n = c - ('a' + 10U);
} else {
n = 0U;
}
if ((i & 1U) != 0U) {
addr[i>>1] |= n;
} else {
addr[i>>1] = (uint8_t)((uint32_t)n << 4);
}
}
}
ARM_ETH_MAC_CAPABILITIES capabilities;
int32_t status;
MAC_wstr_to_addr(wsMacAddress, (uint8_t *)&MacAddress);
memset(&NCM_State, 0, sizeof(NCM_State));
NCM_State.ntb_input_size = USBD_CDCn_NCM_DW_NTB_IN_MAX_SIZE;
NCM_State.max_datagram_size = USBD_CDCn_NCM_W_MAX_SEGMENT_SIZE;
#if ((USBD_CDCn_NCM_BM_NETWORK_CAPABILITIES & 0x02) != 0)
memcpy(NCM_State.net_address, &MacAddress, 6);
#endif
NCM_State.packet_filter_bitmap = 0x0CU;
LinkState = ARM_ETH_LINK_DOWN;
LinkInfo.speed = 0U;
LinkInfo.duplex = 0U;
LinkSpeed = 0U;
PacketFilter = ARM_ETH_MAC_ADDRESS_BROADCAST;
FrameIN_Size = 0U;
memset(FrameIN, 0, sizeof(FrameIN));
capabilities = EthMac->GetCapabilities();
status = EthMac->Initialize(EthMac_Notify);
if (status != ARM_DRIVER_OK) { return; }
status = EthMac->PowerControl(ARM_POWER_FULL);
if (status != ARM_DRIVER_OK) { return; }
status = EthMac->SetMacAddress(&MacAddress);
if (status != ARM_DRIVER_OK) { return; }
status = EthPhy->Initialize(EthMac->PHY_Read, EthMac->PHY_Write);
if (status != ARM_DRIVER_OK) { return; }
status = EthPhy->PowerControl(ARM_POWER_FULL);
if (status != ARM_DRIVER_OK) { return; }
status = EthPhy->SetInterface(capabilities.media_interface);
if (status != ARM_DRIVER_OK) { return; }
status = EthPhy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE);
if (status != ARM_DRIVER_OK) { return; }
#ifdef USB_CMSIS_RTOS2
Connection_ThreadId = osThreadNew(Connection_Thread, NULL, &connection_thread_attr);
DataIN_ThreadId = osThreadNew(DataIN_Thread, NULL, &data_in_thread_attr);
DataOUT_ThreadId = osThreadNew(DataOUT_Thread, NULL, &data_out_thread_attr);
#else
Connection_ThreadId = osThreadCreate(osThread(Connection_Thread), NULL);
DataIN_ThreadId = osThreadCreate(osThread(DataIN_Thread), NULL);
DataOUT_ThreadId = osThreadCreate(osThread(DataOUT_Thread), NULL);
#endif
}
(void)osThreadTerminate(Connection_ThreadId);
(void)osThreadTerminate(DataIN_ThreadId);
(void)osThreadTerminate(DataOUT_ThreadId);
(void)EthPhy->PowerControl(ARM_POWER_OFF);
(void)EthPhy->Uninitialize();
(void)EthMac->PowerControl(ARM_POWER_OFF);
(void)EthMac->Uninitialize();
}
}
#ifdef USB_CMSIS_RTOS2
(void)osThreadFlagsSet(Connection_ThreadId, 1U);
(void)osThreadFlagsSet(DataIN_ThreadId, 1U);
#else
(void)osSignalSet(Connection_ThreadId, 1U);
(void)osSignalSet(DataIN_ThreadId, 1U);
#endif
}
FrameIN_Size = 0U;
#ifdef USB_CMSIS_RTOS
osSignalClear(DataIN_ThreadId, 1U);
#endif
memset(&NCM_State, 0, sizeof(NCM_State));
NCM_State.ntb_input_size = USBD_CDCn_NCM_DW_NTB_IN_MAX_SIZE;
NCM_State.max_datagram_size = USBD_CDCn_NCM_W_MAX_SEGMENT_SIZE;
#if ((USBD_CDCn_NCM_BM_NETWORK_CAPABILITIES & 0x02) != 0)
memcpy(NCM_State.net_address, &MacAddress, 6);
#endif
NCM_State.packet_filter_bitmap = 0x0CU;
PacketFilter = ARM_ETH_MAC_ADDRESS_BROADCAST;
(void)EthMac->SetMacAddress(&MacAddress);
(void)EthMac->SetAddressFilter(NULL, 0);
(void)EthMac->Control(ARM_ETH_MAC_CONFIGURE,
(uint32_t)(LinkInfo.speed ) |
(uint32_t)(LinkInfo.duplex << ARM_ETH_MAC_DUPLEX_Pos) |
PacketFilter);
}
#if (USBD_CDCn_NCM_W_NUMBER_MC_FILTERS != 0)
int32_t status;
if (num_of_filters > (USBD_CDCn_NCM_W_NUMBER_MC_FILTERS & 0x7FFF)) { return false; }
status = EthMac->SetAddressFilter((ARM_ETH_MAC_ADDR *)((uint32_t)addr_list), num_of_filters);
if (status != ARM_DRIVER_OK) { return false; }
memcpy(NCM_State.mc_filters, addr_list, num_of_filters * 6);
return true;
#else
(void)addr_list;
(void)num_of_filters;
return false;
#endif
}
#if (USBD_CDCn_NCM_B_NUMBER_POWER_FILTERS != 0)
if (filter_number >= USBD_CDCn_NCM_B_NUMBER_POWER_FILTERS) { return false; }
NCM_State.power_filter_active[filter_number / 8] |= 1U << (filter_number % 8);
return true;
#else
(void)filter_number;
(void)pattern_filter;
(void)pattern_filter_size;
return false;
#endif
}
#if (USBD_CDCn_NCM_B_NUMBER_POWER_FILTERS != 0)
*pattern_active = (NCM_State.power_filter_active[filter_number / 8] & (1U << (filter_number % 8))) ? 1 : 0;
return true;
#else
(void)filter_number;
(void)pattern_active;
return false;
#endif
}
#if ((USBD_CDCn_NCM_BM_NETWORK_CAPABILITIES & 0x01) != 0)
int32_t status;
PacketFilter = ((packet_filter_bitmap & 0x01U) ? ARM_ETH_MAC_ADDRESS_ALL : 0) |
((packet_filter_bitmap & 0x02U) ? ARM_ETH_MAC_ADDRESS_MULTICAST : 0) |
((packet_filter_bitmap & 0x08U) ? ARM_ETH_MAC_ADDRESS_BROADCAST : 0);
status = EthMac->Control(ARM_ETH_MAC_CONFIGURE,
(uint32_t)(LinkInfo.speed ) |
(uint32_t)(LinkInfo.duplex << ARM_ETH_MAC_DUPLEX_Pos) |
PacketFilter);
if (status != ARM_DRIVER_OK) { return false; }
NCM_State.packet_filter_bitmap = packet_filter_bitmap;
return true;
#else
(void)packet_filter_bitmap;
return false;
#endif
}
#if (USBD_CDCn_NCM_BM_ETHERNET_STATISTICS != 0)
if (feature_selector == 0x00U) { return true; }
if (feature_selector > 0x1DU) { return false; }
*data = NCM_State.eth_statistics[feature_selector - 1];
return true;
#else
(void)feature_selector;
(void)data;
return false;
#endif
}
ntb_params->Reserved0 = 0U;
ntb_params->Reserved1 = 0U;
return true;
}
#if ((USBD_CDCn_NCM_BM_NETWORK_CAPABILITIES & 0x02) != 0)
memcpy(net_addr, NCM_State.net_address, 6);
return true;
#else
(void)net_addr;
return false;
#endif
}
#if ((USBD_CDCn_NCM_BM_NETWORK_CAPABILITIES & 0x02) != 0)
int32_t status;
status = EthMac->SetMacAddress((ARM_ETH_MAC_ADDR *)((uint32_t)net_addr));
if (status != ARM_DRIVER_OK) { return false; }
memcpy(NCM_State.net_address, net_addr, 6);
return true;
#else
(void)net_addr;
return false;
#endif
}
*ntb_format = NCM_State.ntb_format;
return true;
}
#if (USBD_CDCn_NCM_BM_NTB_FORMATS_SUPPORTED > 1)
if (ntb_format > 1) { return false; }
#else
if (ntb_format > 0) { return false; }
#endif
NCM_State.ntb_format = ntb_format;
return true;
}
*ntb_input_size = NCM_State.ntb_input_size;
return true;
}
if (ntb_input_size > USBD_CDCn_NCM_DW_NTB_IN_MAX_SIZE) { return false; }
NCM_State.ntb_input_size = ntb_input_size;
return true;
}
#if ((USBD_CDCn_NCM_BM_NETWORK_CAPABILITIES & 0x08) != 0)
*max_datagram_size = NCM_State.max_datagram_size;
return true;
#else
(void)max_datagram_size;
return false;
#endif
}
#if ((USBD_CDCn_NCM_BM_NETWORK_CAPABILITIES & 0x08) != 0)
if (max_datagram_size > USBD_CDCn_NCM_W_MAX_SEGMENT_SIZE) { return false; }
NCM_State.max_datagram_size = max_datagram_size;
return true;
#else
(void)max_datagram_size;
return false;
#endif
}
#if ((USBD_CDCn_NCM_BM_NETWORK_CAPABILITIES & 0x10) != 0)
*crc_mode = NCM_State.crc_mode;
return true;
#else
(void)crc_mode;
return false;
#endif
}
#if ((USBD_CDCn_NCM_BM_NETWORK_CAPABILITIES & 0x10) != 0)
if (crc_mode > 1) { return false; }
NCM_State.crc_mode = crc_mode;
return true;
#else
(void)crc_mode;
return false;
#endif
}
#ifdef USB_CMSIS_RTOS2
(void)osThreadFlagsSet(DataIN_ThreadId, 1U);
#else
(void)osSignalSet(DataIN_ThreadId, 1U);
#endif
}
#ifdef USB_CMSIS_RTOS2
(void)osThreadFlagsSet(DataOUT_ThreadId, 1U);
#else
(void)osSignalSet(DataOUT_ThreadId, 1U);
#endif
}
static void EthMac_Notify (uint32_t event) {
switch (event) {
case ARM_ETH_MAC_EVENT_RX_FRAME:
#ifdef USB_CMSIS_RTOS2
(void)osThreadFlagsSet(DataIN_ThreadId, 2U);
#else
(void)osSignalSet(DataIN_ThreadId, 2U);
#endif
break;
default:
break;
}
}
#ifdef USB_CMSIS_RTOS2
__NO_RETURN static void Connection_Thread (void *arg) {
#else
__NO_RETURN static void Connection_Thread (void const *arg) {
#endif
ARM_ETH_LINK_STATE link_state;
#ifdef USB_CMSIS_RTOS
osEvent os_event;
#endif
uint32_t event;
uint32_t speed;
uint16_t state;
int32_t status;
(void)(arg);
for (;;) {
#ifdef USB_CMSIS_RTOS2
event = osThreadFlagsWait(1U, osFlagsWaitAll, 500U);
#else
os_event = osSignalWait(1U, 500U);
if (os_event.status == osEventSignal) {
event = (uint32_t)os_event.value.signals;
} else {
event = 0x80000000U;
}
#endif
link_state = EthPhy->GetLinkState();
if (link_state == ARM_ETH_LINK_UP) {
LinkInfo = EthPhy->GetLinkInfo();
switch (LinkInfo.speed) {
case 0: speed = 10000000U; break;
case 1: speed = 100000000U; break;
case 2: speed = 1000000000U; break;
default: speed = 0U;
}
} else {
speed = 0U;
}
if (speed != LinkSpeed) {
LinkSpeed = speed;
if (link_state == ARM_ETH_LINK_UP) {
do {
}
}
if (link_state != LinkState) {
LinkState = link_state;
if (link_state == ARM_ETH_LINK_UP) {
(void)EthMac->Control(ARM_ETH_MAC_CONFIGURE,
(uint32_t)(LinkInfo.speed ) |
(uint32_t)(LinkInfo.duplex << ARM_ETH_MAC_DUPLEX_Pos) |
PacketFilter);
(void)EthMac->Control(ARM_ETH_MAC_CONTROL_TX, 1U);
(void)EthMac->Control(ARM_ETH_MAC_CONTROL_RX, 1U);
} else {
(void)EthMac->Control(ARM_ETH_MAC_FLUSH,
ARM_ETH_MAC_FLUSH_TX |
ARM_ETH_MAC_FLUSH_RX);
(void)EthMac->Control(ARM_ETH_MAC_CONTROL_TX, 0U);
(void)EthMac->Control(ARM_ETH_MAC_CONTROL_RX, 0U);
}
state = (link_state == ARM_ETH_LINK_UP) ? 1U : 0U;
do {
}
if ((event & 0x80000000U) == 0U) {
if (LinkState == ARM_ETH_LINK_UP) {
do {
}
state = (LinkState == ARM_ETH_LINK_UP) ? 1U : 0U;
do {
}
}
}
#ifdef USB_CMSIS_RTOS2
__NO_RETURN static void DataIN_Thread (void *arg) {
#else
__NO_RETURN static void DataIN_Thread (void const *arg) {
#endif
uint32_t size;
int32_t status;
(void)arg;
for (;;) {
#ifdef USB_CMSIS_RTOS2
(void)osThreadFlagsWait(3U, osFlagsWaitAll, osWaitForever);
#else
(void)osSignalWait(3U, osWaitForever);
#endif
do {
if (status != (int32_t)
usbOK) {
continue; }
if (status != (int32_t)
usbOK) {
continue; }
for (;;) {
if (FrameIN_Size != 0) {
FrameIN_Size = 0;
}
size = EthMac->GetRxFrameSize();
if (size == 0U) {
break;
}
if ((size < 14U) || (size > NCM_State.max_datagram_size)) {
(void)EthMac->ReadFrame(NULL, 0U);
continue;
}
(void)EthMac->ReadFrame(FrameIN, size);
if (size > 0) {
#if ((USBD_CDCn_NCM_BM_ETHERNET_STATISTICS & 0x00000002) != 0)
NCM_State.eth_statistics[1]++;
#endif
if (status != (int32_t)
usbOK) {
FrameIN_Size = size;
break;
}
}
}
} while (FrameIN_Size);
}
}
#ifdef USB_CMSIS_RTOS2
__NO_RETURN static void DataOUT_Thread (void *arg) {
#else
__NO_RETURN static void DataOUT_Thread (void const *arg) {
#endif
uint32_t size;
int32_t len, status;
(void)(arg);
for (;;) {
#ifdef USB_CMSIS_RTOS2
(void)osThreadFlagsWait(1U, osFlagsWaitAll, osWaitForever);
#else
(void)osSignalWait(1U, osWaitForever);
#endif
for (;;) {
if (status != (int32_t)
usbOK) {
break; }
for (;;) {
if (size == 0U) { break; }
if ((size < 14U) || (size > NCM_State.max_datagram_size)) {
continue;
}
if (len > 0) {
do {
status = EthMac->SendFrame(FrameOUT, (uint32_t)(len), 0U);
} while (status == ARM_DRIVER_ERROR_BUSY);
#if ((USBD_CDCn_NCM_BM_ETHERNET_STATISTICS & 0x00000001) != 0)
NCM_State.eth_statistics[0]++;
#endif
}
}
}
}
}