From 56868b513ac1375b71770ec14b2e194e0073e9ca Mon Sep 17 00:00:00 2001 From: Runcheng Lu Date: Fri, 16 Jun 2023 10:25:53 +0800 Subject: [PATCH] third_party: freertos: add adapt rndis_host APIs - add adapt rndis_host APIs Signed-off-by: Runcheng Lu --- .../FreeRTOS-10.4/rndis_host/rndis_host.c | 286 ++++++++++++++++++ 1 file changed, 286 insertions(+) create mode 100644 third_party/FreeRTOS-10.4/rndis_host/rndis_host.c diff --git a/third_party/FreeRTOS-10.4/rndis_host/rndis_host.c b/third_party/FreeRTOS-10.4/rndis_host/rndis_host.c new file mode 100644 index 00000000..a0cf21f0 --- /dev/null +++ b/third_party/FreeRTOS-10.4/rndis_host/rndis_host.c @@ -0,0 +1,286 @@ +/* FreeRTOS kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" +#include "timers.h" + +#include +#include "board.h" +#include "netif/etharp.h" +#include "lwip/init.h" +#include "lwip/tcp.h" +#include "lwip/tcpip.h" +#include "lwip/netif.h" +#include "lwip/pbuf.h" +#include "lwip/icmp.h" +#include "lwip/udp.h" +#include "lwip/opt.h" +#include "lwip/arch.h" +#include "lwip/api.h" +#include "lwip/inet.h" +#include "lwip/dhcp.h" +#include "lwip/prot/dhcp.h" +#include +#include +#include +#include "usbh_core.h" +#include "usbh_rndis.h" +#include "rndis_protocol.h" + +/* Macro Definition */ +/*--------------- Tasks Priority -------------*/ +#define RNDIS_RECV_DATA_TASK_PRIO (tskIDLE_PRIORITY + 6) + +#define RNDIS_ETH_BUFFER_LEN (sizeof(rndis_data_packet_t) + 1514 + 42) +#define RNDIS_RXETH_BUFFER_LEN (RNDIS_ETH_BUFFER_LEN * 3) + +/* Static Variable Definition*/ +static struct usbh_rndis *s_rndis_class_ptr; +static struct netif netif_data; +static ip4_addr_t ipaddr; +static ip4_addr_t netmask; +static ip4_addr_t gateway; +USB_NOCACHE_RAM_SECTION uint8_t tx_buffer[RNDIS_ETH_BUFFER_LEN]; +USB_NOCACHE_RAM_SECTION uint8_t rx_buffer[RNDIS_RXETH_BUFFER_LEN]; +static uint8_t *rx_buf_ptr; +SemaphoreHandle_t mutex_sem_handle; +SemaphoreHandle_t sig_sem_handle; +TimerHandle_t timer_handle; +TaskHandle_t data_recv_task_handle; + +/* Static Function Declaration */ +static void rndis_dev_keepalive_timeout(void *pdata); +static err_t netif_init_cb(struct netif *netif); +static err_t linkoutput_fn(struct netif *netif, struct pbuf *p); +static int usbh_rndis_eth_tx(struct pbuf *p); +static int rndis_msg_data_send(struct usbh_rndis *rndis_class, uint8_t *buffer, int nbytes); +static void lwip_rx_handle(void *pdata); + +extern int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, + uint32_t oid, uint32_t query_len, + uint8_t *info, uint32_t *info_len); + +void usbh_rndis_run(struct usbh_rndis *rndis_class) +{ + struct netif *netif = &netif_data; + + s_rndis_class_ptr = rndis_class; + rx_buf_ptr = rx_buffer; + + /* Create tcp_ip stack thread */ + tcpip_init(NULL, NULL); + + netif->hwaddr_len = 6; + memcpy(netif->hwaddr, rndis_class->mac, 6); + + IP4_ADDR(&ipaddr, 0, 0, 0, 0); + IP4_ADDR(&netmask, 0, 0, 0, 0); + IP4_ADDR(&gateway, 0, 0, 0, 0); + + netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, tcpip_input); + netif_set_default(netif); + netif_set_up(netif); + + mutex_sem_handle = xSemaphoreCreateMutex(); + if (NULL == mutex_sem_handle) { + printf("mutex semaphore creat faile!\r\n"); + for (;;) { + ; + } + } + + sig_sem_handle = xSemaphoreCreateCounting(1, 0); + if (NULL == sig_sem_handle) { + printf("Rndis sig semaphore creat faile!\r\n"); + for (;;) { + ; + } + } + + timer_handle = + xTimerCreate((const char *)NULL, (TickType_t)5000, (UBaseType_t)pdTRUE, (void *const)1, (TimerCallbackFunction_t)rndis_dev_keepalive_timeout); + if (NULL != timer_handle) { + xTimerStart(timer_handle, 0); + } else { + printf("timer creation failed!.\n"); + for (;;) { + ; + } + } + + if (xTaskCreate(lwip_rx_handle, "rndis_lwip_rx", configMINIMAL_STACK_SIZE + 2048U, rndis_class, RNDIS_RECV_DATA_TASK_PRIO, &data_recv_task_handle) != + pdPASS) { + printf("rndis_lwip_rx Task creation failed!.\n"); + for (;;) { + ; + } + } +} + +void usbh_rndis_stop(struct usbh_rndis *rndis_class) +{ + vTaskDelete(data_recv_task_handle); + + xTimerStop(timer_handle, 0); + xTimerDelete(timer_handle, 0); + + vSemaphoreDelete(mutex_sem_handle); + vSemaphoreDelete(sig_sem_handle); + + netif_remove(&netif_data); + + printf("rndis dev stop!\n"); +} + +static void rndis_dev_keepalive_timeout(void *pdata) +{ + int ret; + + xSemaphoreTake(mutex_sem_handle, portMAX_DELAY); + ret = usbh_rndis_keepalive(s_rndis_class_ptr); + xSemaphoreGive(mutex_sem_handle); + if (ret < 0) { + printf("rndis dev keepalive timeout!\n"); + } +} + +static void lwip_rx_handle(void *pdata) +{ + err_t err; + int ret = 0; + struct pbuf *p; + rndis_data_packet_t *pmsg; + int pmg_offset; + int payload_offset; + + struct usbh_rndis *rndis_class = (struct usbh_rndis *)pdata; + rx_buf_ptr = rx_buffer; + + while (1) { + pmg_offset = 0; + payload_offset = 0; + ret = usbh_rndis_bulk_in_transfer(rndis_class, rx_buf_ptr, RNDIS_RXETH_BUFFER_LEN, portMAX_DELAY); + if (ret <= 0) { + vTaskDelay(1); + continue; + } + while (ret > 0) { + pmsg = (rndis_data_packet_t *)(rx_buf_ptr + pmg_offset); + if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG) { + /* allocate buffer */ + p = pbuf_alloc(PBUF_RAW, pmsg->DataLength, PBUF_POOL); + if (p != NULL) { + struct pbuf *q; + for (q = p; q != NULL; q = q->next) { + /* Copy the received frame into buffer from memory pointed by the current ETHERNET DMA Rx descriptor */ + memcpy(q->payload, ((uint8_t *)(&pmsg->DataOffset) + pmsg->DataOffset + payload_offset), q->len); + payload_offset += q->len; + } + /* entry point to the LwIP stack */ + err = netif_data.input(p, &netif_data); + if (err != ERR_OK) { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + pbuf_free(p); + } + pmg_offset += pmsg->MessageLength; + ret -= pmsg->MessageLength; + } + } + } + } +} + +static err_t netif_init_cb(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + netif->mtu = 1500; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + netif->state = NULL; + netif->name[0] = 'E'; + netif->name[1] = 'X'; + netif->linkoutput = linkoutput_fn; + netif->output = etharp_output; + return ERR_OK; +} + +static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) +{ + int ret; + + ret = usbh_rndis_eth_tx(p); + + if (-EBUSY == ret) { + ret = ERR_BUF; + } + + return ret; +} + +static int usbh_rndis_eth_tx(struct pbuf *p) +{ + struct pbuf *q; + uint8_t *buffer; + rndis_data_packet_t *hdr; + int ret; + int recount = 5; + uint8_t data[4]; + uint32_t info_len = 0; + + if (!s_rndis_class_ptr->link_status) { + printf("linkdown, drop pkg\r\n"); + while (recount--) { + ret = usbh_rndis_query_msg_transfer(s_rndis_class_ptr, OID_GEN_MEDIA_CONNECT_STATUS, sizeof(data), data, &info_len); + if (ret < 0) { + return -EBUSY; + } + if (NDIS_MEDIA_STATE_CONNECTED == data[0]) { + s_rndis_class_ptr->link_status = true; + break; + } else { + s_rndis_class_ptr->link_status = false; + } + vTaskDelay(1000); + } + return 0; + } + + assert((p->tot_len + sizeof(rndis_data_packet_t)) < sizeof(tx_buffer)); + if (p->tot_len > sizeof(tx_buffer)) { + printf("RNDIS MTU is:%d, but the send packet size is %d\r\n", sizeof(tx_buffer), p->tot_len); + p->tot_len = sizeof(tx_buffer); + } + + hdr = (rndis_data_packet_t *)tx_buffer; + memset(hdr, 0, sizeof(rndis_data_packet_t)); + hdr->MessageType = REMOTE_NDIS_PACKET_MSG; + hdr->MessageLength = sizeof(rndis_data_packet_t) + p->tot_len; + hdr->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t); + hdr->DataLength = p->tot_len; + + buffer = (uint8_t *)(tx_buffer + sizeof(rndis_data_packet_t)); + for (q = p; q != NULL; q = q->next) { + memcpy(buffer, q->payload, q->len); + buffer += q->len; + } + /* send */ + if ((hdr->MessageLength & 0x1FF) == 0) { + /* pad a dummy. */ + hdr->MessageLength += 1; + } + return rndis_msg_data_send(s_rndis_class_ptr, (uint8_t *)tx_buffer, hdr->MessageLength); +} + +static int rndis_msg_data_send(struct usbh_rndis *rndis_class, uint8_t *buffer, + int nbytes) +{ + int ret = ERR_OK; + int len = 0; + xSemaphoreTake(mutex_sem_handle, portMAX_DELAY); + len = usbh_rndis_bulk_out_transfer(rndis_class, buffer, nbytes, 5000); + xSemaphoreGive(mutex_sem_handle); + if (len != nbytes) { + printf("rndis msg send fail\r\n"); + ret = -EBUSY; + } + return ret; +}