|
|
@@ -8,12 +8,13 @@
|
|
|
#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 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 USB_ETH_MTU (1500 + 14)
|
|
|
+#define RNDIS_THREAD_STACK_SIZE (4096)
|
|
|
|
|
|
#define RNDIS_NET_DEV_NAME "u0"
|
|
|
#define MAX_ADDR_LEN 6
|
|
|
@@ -27,8 +28,7 @@ struct usbh_user_rndis {
|
|
|
void *user_data;
|
|
|
};
|
|
|
|
|
|
-struct rndis_packet_msg
|
|
|
-{
|
|
|
+struct rndis_packet_msg {
|
|
|
rt_uint32_t MessageType;
|
|
|
rt_uint32_t MessageLength;
|
|
|
rt_uint32_t DataOffset;
|
|
|
@@ -65,12 +65,12 @@ struct rt_rndis_eth {
|
|
|
|
|
|
rt_uint32_t rndis_state;
|
|
|
rt_thread_t rndis_recv;
|
|
|
- rt_timer_t keepalive_timer;
|
|
|
+ rt_thread_t keepalive_timer;
|
|
|
};
|
|
|
typedef struct rt_rndis_eth *rt_rndis_eth_t;
|
|
|
|
|
|
-struct usbh_user_rndis *g_user_rndis;
|
|
|
-USB_NOCACHE_RAM_SECTION struct rt_rndis_eth usbh_rndis_eth_device;
|
|
|
+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)
|
|
|
{
|
|
|
@@ -139,7 +139,7 @@ static rt_err_t rt_rndis_msg_data_send(struct usbh_user_rndis *rndis_class, rt_u
|
|
|
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 fial\r\n");
|
|
|
+ rt_kprintf("rndis msg send fail(%d %d)\r\n", ret, nbytes);
|
|
|
}
|
|
|
return ret;
|
|
|
}
|
|
|
@@ -187,55 +187,62 @@ static rt_err_t rt_rndis_keepalive_msg(struct usbh_user_rndis *rndis_class)
|
|
|
*/
|
|
|
void rt_usbh_rndis_data_recv_entry(void *pdata)
|
|
|
{
|
|
|
- int ret = 0;
|
|
|
struct usbh_user_rndis *rndis_class = (struct usbh_user_rndis *)pdata;
|
|
|
- rt_rndis_eth_t device = RT_NULL;
|
|
|
- device = (rt_rndis_eth_t)rndis_class->user_data;
|
|
|
- err_t err;
|
|
|
- struct pbuf *p;
|
|
|
- rndis_data_packet_t *pmsg;
|
|
|
- int pmg_offset;
|
|
|
- int payload_offset;
|
|
|
-
|
|
|
- if ((pdata == RT_NULL) || (rndis_class == RT_NULL) ||
|
|
|
- (device == RT_NULL)) {
|
|
|
- return;
|
|
|
- }
|
|
|
+ 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;
|
|
|
+ //device->rx_buf_ptr = device->rx_buffer;
|
|
|
|
|
|
while (1) {
|
|
|
- pmg_offset = 0;
|
|
|
- payload_offset = 0;
|
|
|
+ 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, RT_WAITING_FOREVER);
|
|
|
if (ret <= 0) {
|
|
|
rt_thread_mdelay(1);
|
|
|
continue;
|
|
|
}
|
|
|
+
|
|
|
while (ret > 0) {
|
|
|
- pmsg = (rndis_data_packet_t *)(device->rx_buf_ptr + pmg_offset);
|
|
|
+ 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 */
|
|
|
- p = pbuf_alloc(PBUF_RAW, pmsg->DataLength, PBUF_POOL);
|
|
|
+ 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) {
|
|
|
- /* 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);
|
|
|
+ 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 )
|
|
|
- {
|
|
|
+
|
|
|
+ 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;
|
|
|
}
|
|
|
- pmg_offset += pmsg->MessageLength;
|
|
|
- ret -= pmsg->MessageLength;
|
|
|
}
|
|
|
+ } else {
|
|
|
+ rt_kprintf("pmsg->MessageType=%d\n", pmsg->MessageType);
|
|
|
+ break;
|
|
|
}
|
|
|
+
|
|
|
+ pmg_offset += pmsg->MessageLength;
|
|
|
+ ret -= pmsg->MessageLength;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -243,15 +250,14 @@ void rt_usbh_rndis_data_recv_entry(void *pdata)
|
|
|
void rt_rndis_dev_keepalive_timeout(void *pdata)
|
|
|
{
|
|
|
struct usbh_user_rndis *rndis_class = (struct usbh_user_rndis *)pdata;
|
|
|
- static rt_uint32_t keepalive_error = 0;
|
|
|
|
|
|
- if (rndis_class == RT_NULL) {
|
|
|
- return;
|
|
|
- }
|
|
|
+ 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);
|
|
|
+ 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);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -274,22 +280,24 @@ rt_err_t rt_rndis_run(struct usbh_user_rndis *rndis_class)
|
|
|
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_timer_create("keeplive", rt_rndis_dev_keepalive_timeout,
|
|
|
- rndis_class,
|
|
|
- RT_TICK_PER_SECOND * RNDIS_DEV_KEEPALIVE_TIMEOUT / 1000,
|
|
|
- RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER);
|
|
|
+ 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;
|
|
|
}
|
|
|
- rt_timer_start(usbh_rndis_eth_device.keepalive_timer);
|
|
|
+
|
|
|
rndis_class->user_data = (struct rt_device *)&usbh_rndis_eth_device;
|
|
|
|
|
|
- usbh_rndis_eth_device.rndis_recv = rt_thread_create("rndis",
|
|
|
+ usbh_rndis_eth_device.rndis_recv = rt_thread_create("rndis_recv",
|
|
|
(void (*)(void *parameter))rt_usbh_rndis_data_recv_entry,
|
|
|
rndis_class,
|
|
|
- 1024 + 512,
|
|
|
+ RNDIS_THREAD_STACK_SIZE,
|
|
|
5,
|
|
|
20);
|
|
|
|
|
|
@@ -301,8 +309,6 @@ rt_err_t rt_rndis_run(struct usbh_user_rndis *rndis_class)
|
|
|
/*the LINK SPEED is 100Mbps*/
|
|
|
usbh_rndis_eth_device.rndis_speed = rndis_class->rndis_class->link_speed;
|
|
|
|
|
|
- eth_device_linkchange(&usbh_rndis_eth_device.parent, rndis_class->rndis_class->link_status);
|
|
|
-
|
|
|
for (j = 0; j < MAX_ADDR_LEN; j++) {
|
|
|
usbh_rndis_eth_device.dev_addr[j] = rndis_class->rndis_class->mac[j];
|
|
|
}
|
|
|
@@ -316,6 +322,8 @@ __exit:
|
|
|
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;
|
|
|
|
|
|
@@ -332,8 +340,10 @@ void usbh_rndis_run(struct usbh_rndis *rndis_class)
|
|
|
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_FALSE);
|
|
|
+ eth_device_linkchange(&usbh_rndis_eth_device.parent, RT_TRUE);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -348,16 +358,17 @@ rt_err_t rt_rndis_stop(struct usbh_user_rndis *rndis_class)
|
|
|
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)*/
|
|
|
- rt_mutex_take(usbh_rndis_eth_device.rndis_mutex, RT_WAITING_FOREVER);
|
|
|
if (info->keepalive_timer) {
|
|
|
- rt_timer_stop(info->keepalive_timer);
|
|
|
- rt_timer_delete(info->keepalive_timer);
|
|
|
+ rt_thread_delete(info->keepalive_timer);
|
|
|
info->keepalive_timer = RT_NULL;
|
|
|
}
|
|
|
- rt_mutex_release(usbh_rndis_eth_device.rndis_mutex);
|
|
|
|
|
|
info->rndis_state = RNDIS_BUS_UNINITIALIZED;
|
|
|
|
|
|
@@ -370,6 +381,7 @@ 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.
|
|
|
@@ -428,7 +440,6 @@ static rt_err_t rt_rndis_eth_control(rt_device_t dev, int cmd, void *args)
|
|
|
|
|
|
/* ethernet device interface */
|
|
|
|
|
|
-
|
|
|
/* transmit packet. */
|
|
|
extern int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class,
|
|
|
uint32_t oid, uint32_t query_len,
|
|
|
@@ -455,7 +466,7 @@ rt_err_t rt_rndis_eth_tx(rt_device_t dev, struct pbuf *p)
|
|
|
break;
|
|
|
}
|
|
|
RNDIS_DEV_PRINTF("linkdown, drop pkg\r\n");
|
|
|
- while(recount--) {
|
|
|
+ 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;
|
|
|
@@ -507,6 +518,7 @@ rt_err_t rt_rndis_eth_tx(rt_device_t dev, struct pbuf *p)
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
@@ -527,13 +539,16 @@ const static struct rt_device_ops rndis_device_ops = {
|
|
|
#endif
|
|
|
#endif
|
|
|
|
|
|
-__WEAK void lowlevel_usb_init(void)
|
|
|
+__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;
|
|
|
@@ -573,9 +588,9 @@ int usbh_rndis_eth_device_init(void)
|
|
|
|
|
|
lowlevel_usb_init();
|
|
|
|
|
|
- return RT_EOK;
|
|
|
+ return 0;
|
|
|
}
|
|
|
-INIT_APP_EXPORT(usbh_rndis_eth_device_init);
|
|
|
+INIT_DEVICE_EXPORT(usbh_rndis_eth_device_init);
|
|
|
|
|
|
/*********************************************************************************************************
|
|
|
** Function name eth_rndis_frame_debug()
|