Modify rndis_host.c according to CherryUSB v0.10.2

This commit is contained in:
songyanguang 2024-07-23 09:24:27 +08:00
parent 098d39181d
commit f81170c61d
3 changed files with 241 additions and 0 deletions

View File

@ -1 +1,240 @@
/* FreeRTOS kernel includes. */
/*************************************************
File name: rndis_host.c
Description: adopt cherry USB to XiZi AIOT.
Others: CherryUSB v0.10.2/CherryUSB/third_party/FreeRTOS-10.4/rndis_host/rndis_host.c for references
https://github.com/cherry-embedded/CherryUSB/blob/v0.10.2/third_party/FreeRTOS-10.4/rndis_host/rndis_host.c
History:
1. Date: 2024-07-22
Author: AIIT XUOS Lab
Modification: Modify rndis_host.c according to
https://github.com/cherry-embedded/CherryUSB/blob/v0.10.2/third_party/FreeRTOS-10.4/rndis_host/rndis_host.c
https://github.com/cherry-embedded/CherryUSB/blob/v0.10.2/third_party/rt-thread-4.1.1/rndis_host/rndis_host_lwip2.1.2.c
and https://github.com/longtengmcu/USB-HOST-driver-4G-rndis-device/components/drivers/usb/usbhost/class/rndis_dev.c (Zhaoshimin).
*************************************************/
#include <usb_osal.h>
#include "usbh_core.h"
#include "usbh_rndis.h"
#include "rndis_protocol.h"
/* define the rdnis device state*/
#define RNDIS_BUS_UNINITIALIZED 0
#define RNDIS_BUS_INITIALIZED 1
#define RNDIS_INITIALIZED 2
#define RNDIS_DATA_INITIALIZED 3
#define USB_ETH_MTU (1500 + 14)
#define RNDIS_THREAD_STACK_SIZE (4096)
#define NIOCTL_GADDR 0x01
#define MAX_ADDR_LEN 6
/* rndis device keepalive time 5000ms*/
#define RNDIS_DEV_KEEPALIVE_TIMEOUT 5000
/*should be the usb Integer multiple of maximum packet length N*64*/
#define RNDIS_ETH_BUFFER_LEN (sizeof(rndis_data_packet_t) + USB_ETH_MTU + 42)
#define RNDIS_RXETH_BUFFER_LEN (RNDIS_ETH_BUFFER_LEN * 5)
#define RT_TRUE 1 /**< boolean true */
#define RT_FALSE 0 /**< boolean fails */
/* Static Variable Definition*/
static struct usbh_rndis *s_rndis_class_ptr;
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;
usb_osal_sem_t mutex_sem_handle;
usb_osal_thread_t timer_handle;
usb_osal_thread_t data_recv_task_handle;
extern void eth_device_linkchange(bool up); //todo IPC function
extern void eth_device_ready(void *dataptr, size_t len); //todo IPC function
static void rndis_dev_keepalive_timeout(void *pdata)
{
int ret;
while (1) {
usb_osal_msleep(RNDIS_DEV_KEEPALIVE_TIMEOUT);
usb_osal_sem_take(mutex_sem_handle, USB_OSAL_WAITING_FOREVER);
ret = usbh_rndis_keepalive(s_rndis_class_ptr);
usb_osal_sem_give(mutex_sem_handle);
if (ret < 0) {
printf("rndis dev keepalive timeout!\n");
}
}
}
static void usbh_rndis_data_recv_entry(void *pdata)
{
int ret = 0;
rndis_data_packet_t *pmsg;
int pmg_offset;
int recount = 5;
uint8_t data[4];
uint32_t info_len = 0;
struct usbh_rndis *rndis_class = (struct usbh_rndis *)pdata;
rx_buf_ptr = rx_buffer;
if (!rndis_class->link_status) {
printf("linkdown, drop pkg\r\n");
while(recount--) {
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MEDIA_CONNECT_STATUS, sizeof(data), data, &info_len);
if (ret < 0) {
continue;;
}
if (NDIS_MEDIA_STATE_CONNECTED == data[0]) {
s_rndis_class_ptr->link_status = true;
eth_device_linkchange(RT_TRUE);
printf("linkup, drop pkg\r\n");
break;
} else {
s_rndis_class_ptr->link_status = false;
eth_device_linkchange(RT_FALSE);
}
usb_osal_msleep(100);
}
}
while (1) {
pmg_offset = 0;
ret = usbh_rndis_bulk_in_transfer(rndis_class, rx_buf_ptr, RNDIS_RXETH_BUFFER_LEN, USB_OSAL_WAITING_FOREVER);
if (ret <= 0) {
usb_osal_msleep(1);
continue;
}
while (ret > 0) {
pmsg = (rndis_data_packet_t *)(rx_buf_ptr + pmg_offset);
if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG) {
eth_device_ready((uint8_t *)(&pmsg->DataOffset) + pmsg->DataOffset, pmsg->MessageLength);
pmg_offset += pmsg->MessageLength;
ret -= pmsg->MessageLength;
}
}
}
}
void usbh_rndis_run(struct usbh_rndis *rndis_class)
{
s_rndis_class_ptr = rndis_class;
rx_buf_ptr = rx_buffer;
mutex_sem_handle = usb_osal_sem_create(0);
if (NULL == mutex_sem_handle) {
printf("mutex semaphore creat faile!\r\n");
return;
}
timer_handle = usb_osal_thread_create("keepalive", RNDIS_THREAD_STACK_SIZE, 5, rndis_dev_keepalive_timeout, rndis_class);
if (NULL == timer_handle) {
printf("timer creation failed!\n");
return;
}
data_recv_task_handle = usb_osal_thread_create("rndis_recv", RNDIS_THREAD_STACK_SIZE, 5, usbh_rndis_data_recv_entry, rndis_class);
if (NULL == data_recv_task_handle) {
printf("rndis_lwip_rx Task creation failed!\n");
return;
}
}
void usbh_rndis_stop(struct usbh_rndis *rndis_class)
{
usb_osal_thread_delete(data_recv_task_handle);
usb_osal_thread_delete(timer_handle);
usb_osal_sem_delete(mutex_sem_handle);
printf("rndis dev stop!\n");
}
static int rndis_msg_data_send(struct usbh_rndis *rndis_class, uint8_t *buffer,
int nbytes)
{
int ret = 0;
int len = 0;
usb_osal_sem_take(mutex_sem_handle, USB_OSAL_WAITING_FOREVER);
len = usbh_rndis_bulk_out_transfer(rndis_class, buffer, nbytes, 5000);
usb_osal_sem_give(mutex_sem_handle);
if (len != nbytes) {
printf("rndis msg send fail\r\n");
ret = -EBUSY;
}
return ret;
}
int usbh_rndis_eth_tx(void *dataptr, size_t tot_len)
{
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;
eth_device_linkchange(RT_TRUE);
printf("linkup, drop pkg\r\n");
break;
} else {
s_rndis_class_ptr->link_status = false;
eth_device_linkchange(RT_FALSE);
}
usb_osal_msleep(100);
}
return 0;
}
USB_ASSERT((tot_len + sizeof(rndis_data_packet_t)) < sizeof(tx_buffer));
if (tot_len > sizeof(tx_buffer)) {
printf("RNDIS MTU is:%d, but the send packet size is %d\r\n", sizeof(tx_buffer), tot_len);
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) + tot_len;
hdr->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t);
hdr->DataLength = tot_len;
buffer = (uint8_t *)(tx_buffer + sizeof(rndis_data_packet_t));
memcpy(buffer, dataptr, tot_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);
}
int usbh_rndis_eth_control(int cmd, void *args)
{
switch (cmd) {
case NIOCTL_GADDR:
/* get mac address */
if (args) {
memcpy(args, s_rndis_class_ptr->mac, MAX_ADDR_LEN);
} else {
return -EINVAL;
}
break;
default:
break;
}
return 0;
}

View File

@ -50,6 +50,7 @@ int usbh_rndis_bulk_out_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer
int usbh_rndis_bulk_in_transfer(struct usbh_rndis *rndis_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
int usbh_rndis_keepalive(struct usbh_rndis *rndis_class);
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);
void usbh_rndis_stop(struct usbh_rndis *rndis_class);

View File

@ -22,6 +22,7 @@ Modification: introduce message queue mechanism.
#include <string.h>
#include "usb_config.h"
#define USB_OSAL_WAITING_FOREVER (0xFFFFFFFFU)
typedef void *usb_osal_thread_t;
typedef void *usb_osal_sem_t;