- add USB_OSAL_WAITING_FOREVER for Semaphore and Queue use Signed-off-by: Zhihong Chen <zhihong.chen@hpmicro.com>
619 lines
19 KiB
C
619 lines
19 KiB
C
#include <rtthread.h>
|
|
#include "usbh_core.h"
|
|
#include "usbh_rndis.h"
|
|
#include "rndis_protocol.h"
|
|
|
|
/* RT-Thread LWIP ethernet interface */
|
|
#include <netif/ethernetif.h>
|
|
#include <netdev.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 RNDIS_NET_DEV_NAME "u0"
|
|
#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(struct rndis_packet_msg) + USB_ETH_MTU + 42) * 5)
|
|
|
|
struct usbh_user_rndis {
|
|
struct usbh_rndis *rndis_class;
|
|
void *user_data;
|
|
};
|
|
|
|
struct rndis_packet_msg {
|
|
rt_uint32_t MessageType;
|
|
rt_uint32_t MessageLength;
|
|
rt_uint32_t DataOffset;
|
|
rt_uint32_t DataLength;
|
|
rt_uint32_t OOBDataOffset;
|
|
rt_uint32_t OOBDataLength;
|
|
rt_uint32_t NumOOBDataElements;
|
|
rt_uint32_t PerPacketInfoOffset;
|
|
rt_uint32_t PerPacketInfoLength;
|
|
rt_uint32_t VcHandle;
|
|
rt_uint32_t Reserved;
|
|
rt_uint8_t data[0];
|
|
};
|
|
typedef struct rndis_packet_msg* rndis_packet_msg_t;
|
|
|
|
struct rt_rndis_eth {
|
|
/* inherit from ethernet device */
|
|
struct eth_device parent;
|
|
|
|
struct usbh_user_rndis *rndis_class;
|
|
rt_mutex_t rndis_mutex;
|
|
/* interface address info */
|
|
rt_uint8_t dev_addr[MAX_ADDR_LEN];
|
|
rt_uint16_t res;
|
|
rt_uint32_t rndis_speed;
|
|
rt_uint32_t res32;
|
|
|
|
rt_uint8_t tx_buffer[RNDIS_ETH_BUFFER_LEN];
|
|
rt_uint8_t rx_buffer[RNDIS_ETH_BUFFER_LEN];
|
|
rt_uint8_t *rx_buf_ptr;
|
|
rt_uint32_t frame_debug;
|
|
rt_uint32_t send_packet_counter;
|
|
rt_uint32_t recv_packet_counter;
|
|
|
|
rt_uint32_t rndis_state;
|
|
rt_thread_t rndis_recv;
|
|
rt_thread_t keepalive_timer;
|
|
};
|
|
typedef struct rt_rndis_eth *rt_rndis_eth_t;
|
|
|
|
struct usbh_user_rndis *g_user_rndis = RT_NULL;
|
|
USB_NOCACHE_RAM_SECTION struct rt_rndis_eth usbh_rndis_eth_device = { 0 };
|
|
|
|
void hex_data_print(const char *name, const rt_uint8_t *buf, rt_size_t size)
|
|
{
|
|
#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
|
|
#define WIDTH_SIZE 32
|
|
|
|
rt_size_t i, j;
|
|
rt_tick_t tick = 0;
|
|
rt_uint32_t time = 0;
|
|
|
|
tick = rt_tick_get();
|
|
time = (tick * 1000) / RT_TICK_PER_SECOND;
|
|
|
|
rt_kprintf("%s time=%d.%ds,len = %d\n", name, time / 1000, time % 1000, size);
|
|
|
|
for (i = 0; i < size; i += WIDTH_SIZE) {
|
|
rt_kprintf("[HEX] %s: %04X-%04X: ", name, i, i + WIDTH_SIZE);
|
|
for (j = 0; j < WIDTH_SIZE; j++) {
|
|
if (i + j < size) {
|
|
rt_kprintf("%02X ", buf[i + j]);
|
|
} else {
|
|
rt_kprintf(" ");
|
|
}
|
|
if ((j + 1) % 8 == 0) {
|
|
rt_kprintf(" ");
|
|
}
|
|
}
|
|
rt_kprintf(" ");
|
|
for (j = 0; j < WIDTH_SIZE; j++) {
|
|
if (i + j < size) {
|
|
rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
|
|
}
|
|
}
|
|
rt_kprintf("\n");
|
|
}
|
|
}
|
|
|
|
#define RNDIS_DEV_DEBUG
|
|
#ifdef RNDIS_DEV_DEBUG
|
|
#define RNDIS_DEV_PRINTF \
|
|
rt_kprintf("[RNDIS_DEV] "); \
|
|
rt_kprintf
|
|
#else
|
|
#define RNDIS_DEV_PRINTF(...)
|
|
#endif /* RNDIS_DEBUG */
|
|
|
|
/**
|
|
* This function send the rndis data.
|
|
*
|
|
* @param rndis_class the usb interface instance.
|
|
*
|
|
* @return the error code, RT_EOK on successfully.
|
|
*/
|
|
static rt_err_t rt_rndis_msg_data_send(struct usbh_user_rndis *rndis_class, rt_uint8_t *buffer, int nbytes)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (rndis_class == RT_NULL) {
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
rt_rndis_eth_t info = RT_NULL;
|
|
|
|
info = (rt_rndis_eth_t)rndis_class->user_data;
|
|
rt_mutex_take(usbh_rndis_eth_device.rndis_mutex, RT_WAITING_FOREVER);
|
|
ret = usbh_rndis_bulk_out_transfer(rndis_class->rndis_class, buffer, nbytes, 5000);
|
|
rt_mutex_release(usbh_rndis_eth_device.rndis_mutex);
|
|
if (ret != nbytes) {
|
|
rt_kprintf("rndis msg send fail(%d %d)\r\n", ret, nbytes);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* This function recv the rndis data.
|
|
*
|
|
* @param rndis_class the usb interface instance.
|
|
*
|
|
* @return the error code, RT_EOK on successfully.
|
|
*/
|
|
static rt_err_t rndis_msg_data_recv(struct usbh_user_rndis *rndis_class, rt_uint8_t *buffer, int nbytes)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (rndis_class == RT_NULL) {
|
|
return -RT_ERROR;
|
|
}
|
|
ret = usbh_rndis_bulk_in_transfer(rndis_class->rndis_class, buffer, nbytes, USB_OSAL_WAITING_FOREVER);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* This function send the rndis set msg.
|
|
*
|
|
* @param rndis_class the usb interface instance.
|
|
*
|
|
* @return the error code, RT_EOK on successfully.
|
|
*/
|
|
static rt_err_t rt_rndis_keepalive_msg(struct usbh_user_rndis *rndis_class)
|
|
{
|
|
return usbh_rndis_keepalive(rndis_class->rndis_class);
|
|
}
|
|
|
|
/**
|
|
* This function will send the bulk data to the usb device instance,
|
|
*
|
|
* @param device the usb device instance.
|
|
* @param type the type of descriptor bRequest.
|
|
* @param buffer the data buffer to save requested data
|
|
* @param nbytes the size of buffer
|
|
*
|
|
* @return the error code, RT_EOK on successfully.
|
|
*/
|
|
void rt_usbh_rndis_data_recv_entry(void *pdata)
|
|
{
|
|
struct usbh_user_rndis *rndis_class = (struct usbh_user_rndis *)pdata;
|
|
rt_rndis_eth_t device = (rt_rndis_eth_t)rndis_class->user_data;
|
|
rndis_data_packet_t sRndisDataPkt;
|
|
|
|
//device->rx_buf_ptr = device->rx_buffer;
|
|
|
|
while (1) {
|
|
int ret = 0;
|
|
int pmg_offset = 0;
|
|
int payload_offset = 0;
|
|
ret = usbh_rndis_bulk_in_transfer(rndis_class->rndis_class, device->rx_buf_ptr, RNDIS_ETH_BUFFER_LEN, USB_OSAL_WAITING_FOREVER);
|
|
if (ret <= 0) {
|
|
rt_thread_mdelay(1);
|
|
continue;
|
|
}
|
|
|
|
while (ret > 0) {
|
|
rndis_data_packet_t *pmsg = (rndis_data_packet_t *)(device->rx_buf_ptr + pmg_offset);
|
|
if (pmg_offset & 0x3) {
|
|
/* Not word-aligned case */
|
|
//rt_kprintf("pmsg@%08x Not word-aligned case\n", pmsg);
|
|
|
|
rt_memcpy(&sRndisDataPkt, pmsg, sizeof(rndis_data_packet_t));
|
|
pmsg = &sRndisDataPkt;
|
|
}
|
|
|
|
if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG) {
|
|
/* allocate buffer */
|
|
struct pbuf *p = pbuf_alloc(PBUF_RAW, pmsg->DataLength, PBUF_POOL);
|
|
if (p != NULL) {
|
|
struct pbuf *q;
|
|
for (q = p; q != NULL; q = q->next) {
|
|
void *src = (void *)(device->rx_buf_ptr + pmg_offset + (2 * sizeof(uint32_t)) + pmsg->DataOffset + payload_offset);
|
|
|
|
rt_memcpy(q->payload,
|
|
src,
|
|
q->len);
|
|
|
|
payload_offset += q->len;
|
|
}
|
|
/* entry point to the LwIP stack */
|
|
/* notify to upper layer */
|
|
|
|
if (device->parent.netif->input(p, device->parent.netif) != ERR_OK) {
|
|
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: Input error\n"));
|
|
pbuf_free(p);
|
|
p = NULL;
|
|
}
|
|
}
|
|
} else {
|
|
rt_kprintf("pmsg->MessageType=%d\n", pmsg->MessageType);
|
|
break;
|
|
}
|
|
|
|
pmg_offset += pmsg->MessageLength;
|
|
ret -= pmsg->MessageLength;
|
|
}
|
|
}
|
|
}
|
|
|
|
void rt_rndis_dev_keepalive_timeout(void *pdata)
|
|
{
|
|
struct usbh_user_rndis *rndis_class = (struct usbh_user_rndis *)pdata;
|
|
|
|
while (1) {
|
|
rt_thread_mdelay(RT_TICK_PER_SECOND * RNDIS_DEV_KEEPALIVE_TIMEOUT / 1000);
|
|
|
|
rt_mutex_take(usbh_rndis_eth_device.rndis_mutex, RT_WAITING_FOREVER);
|
|
rt_rndis_keepalive_msg(rndis_class);
|
|
rt_mutex_release(usbh_rndis_eth_device.rndis_mutex);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This function will run rndis driver when usb disk is detected.
|
|
*
|
|
* @param rndis_class the usb interface instance.
|
|
*
|
|
* @return the error code, RT_EOK on successfully.
|
|
*/
|
|
rt_err_t rt_rndis_run(struct usbh_user_rndis *rndis_class)
|
|
{
|
|
rt_err_t ret = 0;
|
|
rt_uint32_t i = 0, j = 0;
|
|
|
|
/* check parameter */
|
|
RT_ASSERT(rndis_class != RT_NULL);
|
|
|
|
/*The host is configured to send and receive any of the RNDIS control messages for suitably
|
|
configuring or querying the device, to receive status indications from the device,
|
|
to reset the device, or to tear down the data and control channels*/
|
|
usbh_rndis_eth_device.rndis_state = RNDIS_INITIALIZED;
|
|
|
|
usbh_rndis_eth_device.keepalive_timer = rt_thread_create("keeplive",
|
|
(void (*)(void *parameter))rt_rndis_dev_keepalive_timeout,
|
|
rndis_class,
|
|
RNDIS_THREAD_STACK_SIZE,
|
|
5,
|
|
20);
|
|
|
|
if (usbh_rndis_eth_device.keepalive_timer == RT_NULL) {
|
|
ret = -RT_ENOMEM;
|
|
goto __exit;
|
|
}
|
|
|
|
rndis_class->user_data = (struct rt_device *)&usbh_rndis_eth_device;
|
|
|
|
usbh_rndis_eth_device.rndis_recv = rt_thread_create("rndis_recv",
|
|
(void (*)(void *parameter))rt_usbh_rndis_data_recv_entry,
|
|
rndis_class,
|
|
RNDIS_THREAD_STACK_SIZE,
|
|
5,
|
|
20);
|
|
|
|
if (usbh_rndis_eth_device.rndis_recv == RT_NULL) {
|
|
ret = -RT_ENOMEM;
|
|
goto __exit;
|
|
}
|
|
|
|
/*the LINK SPEED is 100Mbps*/
|
|
usbh_rndis_eth_device.rndis_speed = rndis_class->rndis_class->link_speed;
|
|
|
|
for (j = 0; j < MAX_ADDR_LEN; j++) {
|
|
usbh_rndis_eth_device.dev_addr[j] = rndis_class->rndis_class->mac[j];
|
|
}
|
|
|
|
__exit:
|
|
if (ret == RT_EOK) {
|
|
/*This state is entered after the host has received REMOTE_NDIS_SET_CMPLT
|
|
messages from the device in response to the REMOTE_NDIS_SET_MSG
|
|
that it had sent earlier to the device with all the OIDs required to configure the device for data transfer.
|
|
When the host is in this state, apart from the control messages,
|
|
it can exchange REMOTE_NDIS_PACKET_MSG messages for network data transfer with the device on the data channel*/
|
|
usbh_rndis_eth_device.rndis_state = RNDIS_DATA_INITIALIZED;
|
|
rt_thread_startup(usbh_rndis_eth_device.rndis_recv);
|
|
rt_thread_startup(usbh_rndis_eth_device.keepalive_timer);
|
|
|
|
RNDIS_DEV_PRINTF("rndis dev start!\n");
|
|
usbh_rndis_eth_device.rndis_class = rndis_class;
|
|
|
|
} else {
|
|
RNDIS_DEV_PRINTF("rndis dev faile!\n");
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void usbh_rndis_run(struct usbh_rndis *rndis_class)
|
|
{
|
|
g_user_rndis = usb_malloc(sizeof(struct usbh_user_rndis));
|
|
RT_ASSERT(g_user_rndis != RT_NULL);
|
|
g_user_rndis->rndis_class = rndis_class;
|
|
if (rt_rndis_run(g_user_rndis) == RT_EOK) {
|
|
/* Allocate ethernet resource. */
|
|
eth_device_init(&usbh_rndis_eth_device.parent, RNDIS_NET_DEV_NAME);
|
|
//eth_device_linkchange(&usbh_rndis_eth_device.parent, RT_FALSE);
|
|
eth_device_linkchange(&usbh_rndis_eth_device.parent, RT_TRUE);
|
|
}
|
|
}
|
|
|
|
rt_err_t rt_rndis_stop(struct usbh_user_rndis *rndis_class)
|
|
{
|
|
rt_rndis_eth_t info = RT_NULL;
|
|
|
|
info = (rt_rndis_eth_t)rndis_class->user_data;
|
|
|
|
if (info->rndis_recv) {
|
|
rt_thread_delete(info->rndis_recv);
|
|
info->rndis_recv = RT_NULL;
|
|
}
|
|
eth_device_linkchange(&usbh_rndis_eth_device.parent, RT_FALSE);
|
|
|
|
/* Destroy ethernet resource. */
|
|
eth_device_deinit(&usbh_rndis_eth_device.parent);
|
|
|
|
usbh_rndis_eth_device.rndis_class = RT_NULL;
|
|
|
|
/*disable the other thread etx call the rt_timer_start(rndis->keepalive_timer) cause the RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer)*/
|
|
if (info->keepalive_timer) {
|
|
rt_thread_delete(info->keepalive_timer);
|
|
info->keepalive_timer = RT_NULL;
|
|
}
|
|
|
|
info->rndis_state = RNDIS_BUS_UNINITIALIZED;
|
|
|
|
RNDIS_DEV_PRINTF("rndis dev stop!\n");
|
|
return RT_EOK;
|
|
}
|
|
|
|
void usbh_rndis_stop(struct usbh_rndis *rndis_class)
|
|
{
|
|
RT_ASSERT(g_user_rndis != RT_NULL);
|
|
rt_rndis_stop(g_user_rndis);
|
|
usb_free(g_user_rndis);
|
|
g_user_rndis = RT_NULL;
|
|
}
|
|
/**
|
|
* This function rndis eth device.
|
|
*
|
|
* @param intf the usb interface instance.
|
|
*
|
|
* @return the error code, RT_EOK on successfully.
|
|
*/
|
|
#ifdef RT_USING_LWIP
|
|
/* initialize the interface */
|
|
static rt_err_t rt_rndis_eth_init(rt_device_t dev)
|
|
{
|
|
return RT_EOK;
|
|
}
|
|
|
|
static rt_err_t rt_rndis_eth_open(rt_device_t dev, rt_uint16_t oflag)
|
|
{
|
|
return RT_EOK;
|
|
}
|
|
|
|
static rt_err_t rt_rndis_eth_close(rt_device_t dev)
|
|
{
|
|
return RT_EOK;
|
|
}
|
|
|
|
static rt_size_t rt_rndis_eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
|
|
{
|
|
rt_set_errno(-RT_ENOSYS);
|
|
return 0;
|
|
}
|
|
|
|
static rt_size_t rt_rndis_eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
|
|
{
|
|
rt_set_errno(-RT_ENOSYS);
|
|
return 0;
|
|
}
|
|
static rt_err_t rt_rndis_eth_control(rt_device_t dev, int cmd, void *args)
|
|
{
|
|
rt_rndis_eth_t rndis_eth_dev = (rt_rndis_eth_t)dev;
|
|
switch (cmd) {
|
|
case NIOCTL_GADDR:
|
|
/* get mac address */
|
|
if (args) {
|
|
rt_memcpy(args, rndis_eth_dev->dev_addr, MAX_ADDR_LEN);
|
|
} else {
|
|
return -RT_ERROR;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
/* ethernet device interface */
|
|
|
|
/* transmit packet. */
|
|
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);
|
|
|
|
rt_err_t rt_rndis_eth_tx(rt_device_t dev, struct pbuf *p)
|
|
{
|
|
struct pbuf *q;
|
|
rt_uint8_t *buffer = RT_NULL;
|
|
rt_err_t result = RT_EOK;
|
|
rt_rndis_eth_t device = (rt_rndis_eth_t)dev;
|
|
rndis_packet_msg_t msg = RT_NULL;
|
|
int recount = 5;
|
|
int ret;
|
|
uint8_t data[4];
|
|
uint32_t info_len = 0;
|
|
|
|
if (!device->parent.link_status) {
|
|
while (RT_TRUE) {
|
|
if (device->rndis_class == RT_NULL) {
|
|
rt_thread_delay(1000);
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
RNDIS_DEV_PRINTF("linkdown, drop pkg\r\n");
|
|
while (recount--) {
|
|
ret = usbh_rndis_query_msg_transfer(device->rndis_class->rndis_class, OID_GEN_MEDIA_CONNECT_STATUS, sizeof(data), data, &info_len);
|
|
if (ret < 0) {
|
|
return -EBUSY;
|
|
}
|
|
if (NDIS_MEDIA_STATE_CONNECTED == data[0]) {
|
|
device->rndis_class->rndis_class->link_status = true;
|
|
eth_device_linkchange(&usbh_rndis_eth_device.parent, RT_TRUE);
|
|
RNDIS_DEV_PRINTF("linkup, drop pkg\r\n");
|
|
break;
|
|
} else {
|
|
device->rndis_class->rndis_class->link_status = false;
|
|
eth_device_linkchange(&usbh_rndis_eth_device.parent, RT_FALSE);
|
|
}
|
|
rt_thread_delay(100);
|
|
}
|
|
return RT_EOK;
|
|
}
|
|
|
|
RT_ASSERT((p->tot_len + sizeof(struct rndis_packet_msg)) < sizeof(device->tx_buffer));
|
|
if (p->tot_len > sizeof(device->tx_buffer)) {
|
|
RNDIS_DEV_PRINTF("RNDIS MTU is:%d, but the send packet size is %d\r\n",
|
|
sizeof(device->tx_buffer), p->tot_len);
|
|
p->tot_len = sizeof(device->tx_buffer);
|
|
}
|
|
|
|
msg = (rndis_packet_msg_t)&device->tx_buffer;
|
|
msg->MessageType = REMOTE_NDIS_PACKET_MSG;
|
|
msg->DataOffset = sizeof(struct rndis_packet_msg) - 8;
|
|
msg->DataLength = p->tot_len;
|
|
msg->OOBDataLength = 0;
|
|
msg->OOBDataOffset = 0;
|
|
msg->NumOOBDataElements = 0;
|
|
msg->PerPacketInfoOffset = 0;
|
|
msg->PerPacketInfoLength = 0;
|
|
msg->VcHandle = 0;
|
|
msg->Reserved = 0;
|
|
msg->MessageLength = sizeof(struct rndis_packet_msg) + p->tot_len;
|
|
|
|
buffer = msg->data;
|
|
for (q = p; q != NULL; q = q->next) {
|
|
rt_memcpy(buffer, q->payload, q->len);
|
|
buffer += q->len;
|
|
}
|
|
|
|
/* send */
|
|
if ((msg->MessageLength & 0x3F) == 0) {
|
|
/* pad a dummy. */
|
|
msg->MessageLength += 1;
|
|
}
|
|
|
|
if (device->frame_debug == RT_TRUE) {
|
|
rt_kprintf("msg @ %08x\n", msg);
|
|
hex_data_print("rndis eth tx", (rt_uint8_t *)msg, msg->MessageLength);
|
|
}
|
|
result = rt_rndis_msg_data_send(device->rndis_class, (rt_uint8_t *)msg, msg->MessageLength);
|
|
device->send_packet_counter++;
|
|
|
|
return result;
|
|
}
|
|
|
|
#ifdef RT_USING_DEVICE_OPS
|
|
const static struct rt_device_ops rndis_device_ops = {
|
|
rt_rndis_eth_init,
|
|
rt_rndis_eth_open,
|
|
rt_rndis_eth_close,
|
|
rt_rndis_eth_read,
|
|
rt_rndis_eth_write,
|
|
rt_rndis_eth_control
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
__WEAK void
|
|
lowlevel_usb_init(void)
|
|
{
|
|
}
|
|
|
|
int usbh_rndis_eth_device_init(void)
|
|
{
|
|
/* Initialize all data member in usbh_rndis_eth_device */
|
|
rt_memset(&usbh_rndis_eth_device, 0, sizeof(struct rt_rndis_eth));
|
|
|
|
/* OUI 00-00-00, only for test. */
|
|
usbh_rndis_eth_device.dev_addr[0] = 0xFF;
|
|
usbh_rndis_eth_device.dev_addr[1] = 0xFF;
|
|
usbh_rndis_eth_device.dev_addr[2] = 0xFF;
|
|
/* generate random MAC. */
|
|
usbh_rndis_eth_device.dev_addr[3] = 0xFF;
|
|
usbh_rndis_eth_device.dev_addr[4] = 0xFF;
|
|
usbh_rndis_eth_device.dev_addr[5] = 0xFF;
|
|
|
|
usbh_rndis_eth_device.rndis_mutex = rt_mutex_create("rndis", RT_IPC_FLAG_PRIO);
|
|
|
|
if (usbh_rndis_eth_device.rndis_mutex == RT_NULL) {
|
|
RNDIS_DEV_PRINTF("Rndis mutex creat faile!\r\n");
|
|
}
|
|
|
|
#ifdef RT_USING_DEVICE_OPS
|
|
usbh_rndis_eth_device.parent.parent.ops = &rndis_device_ops;
|
|
#else
|
|
usbh_rndis_eth_device.parent.parent.init = rt_rndis_eth_init;
|
|
usbh_rndis_eth_device.parent.parent.open = rt_rndis_eth_open;
|
|
usbh_rndis_eth_device.parent.parent.close = rt_rndis_eth_close;
|
|
usbh_rndis_eth_device.parent.parent.read = rt_rndis_eth_read;
|
|
usbh_rndis_eth_device.parent.parent.write = rt_rndis_eth_write;
|
|
usbh_rndis_eth_device.parent.parent.control = rt_rndis_eth_control;
|
|
#endif
|
|
usbh_rndis_eth_device.parent.parent.user_data = RT_NULL;
|
|
|
|
usbh_rndis_eth_device.parent.eth_rx = RT_NULL;
|
|
usbh_rndis_eth_device.parent.eth_tx = rt_rndis_eth_tx;
|
|
|
|
/* register eth device */
|
|
usbh_rndis_eth_device.rx_buf_ptr = usbh_rndis_eth_device.rx_buffer;
|
|
usbh_rndis_eth_device.frame_debug = RT_FALSE;
|
|
|
|
usbh_rndis_eth_device.send_packet_counter = 0;
|
|
usbh_rndis_eth_device.recv_packet_counter = 0;
|
|
|
|
lowlevel_usb_init();
|
|
|
|
return 0;
|
|
}
|
|
INIT_DEVICE_EXPORT(usbh_rndis_eth_device_init);
|
|
|
|
/*********************************************************************************************************
|
|
** Function name eth_rndis_frame_debug()
|
|
** Descriptions: rndis frame print
|
|
** input parameters
|
|
** output parameters None
|
|
** Returned value: RT_EOK or RT_ERROR
|
|
*********************************************************************************************************/
|
|
static void eth_rndis_frame_debug(int argc, char **argv)
|
|
{
|
|
if (argc != 2) {
|
|
rt_kprintf("Please check the command you enter, it like this: rndis_debug on/off!\n");
|
|
} else {
|
|
if (rt_strcmp(argv[1], "on") == 0) {
|
|
usbh_rndis_eth_device.frame_debug = RT_TRUE;
|
|
} else {
|
|
usbh_rndis_eth_device.frame_debug = RT_FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef FINSH_USING_MSH
|
|
#include <finsh.h>
|
|
MSH_CMD_EXPORT_ALIAS(eth_rndis_frame_debug, rndis_debug, set eth rndis frame print);
|
|
#endif /* FINSH_USING_MSH */
|