138 lines
4.4 KiB
C
138 lines
4.4 KiB
C
#include <rtthread.h>
|
||
#include <include/rttusb_host.h>
|
||
#include "rndis.h"
|
||
|
||
#ifdef RT_USBH_WIRELESS
|
||
|
||
static struct uclass_driver wireless_driver;
|
||
|
||
static rt_err_t rt_usbh_wireless_enable(void *arg)
|
||
{
|
||
struct uhintf **intf = arg;
|
||
uhcd_t hcd = NULL;
|
||
uep_desc_t ep_desc = NULL;
|
||
struct usb_rndis *rndis = NULL;
|
||
upipe_t pipe;
|
||
rt_uint8_t ep_index;
|
||
|
||
if (intf[0] == NULL) {
|
||
return -EIO;
|
||
}
|
||
|
||
hcd = intf[0]->device->hcd;
|
||
os_printf("subclass %d, protocal %d\r\n",
|
||
intf[0]->intf_desc->bInterfaceSubClass,
|
||
intf[0]->intf_desc->bInterfaceProtocol);
|
||
|
||
// 中云信安cat1模组在iad描述符和接口描述符中不一致,兼容多了一种判断
|
||
if ((intf[0]->intf_desc->bInterfaceSubClass == 1 && intf[0]->intf_desc->bInterfaceProtocol == 3) || \
|
||
(intf[0]->intf_desc->bInterfaceSubClass == 2 && intf[0]->intf_desc->bInterfaceProtocol == 255)) {
|
||
#ifdef STATIC_RNDIS_NETDEV
|
||
rndis = (struct usb_rndis *)dev_get(HG_LTE_RNDIS_DEVID);
|
||
#else
|
||
rndis = (struct usb_rndis *)os_zalloc(sizeof(struct usb_rndis));
|
||
#endif
|
||
if (rndis == NULL) {
|
||
os_printf("rndis alloc fail\r\n");
|
||
return -ENOMEM;
|
||
}
|
||
rndis->msg_buffer = (rt_uint8_t *)os_malloc(128 + USB_RX_BUFF_RESERVE_SIZE);
|
||
if (rndis->msg_buffer == NULL) {
|
||
os_printf("rndis msg buffer alloc fail\r\n");
|
||
os_free(rndis);
|
||
return -ENOMEM;
|
||
}
|
||
rndis->data_buffer = (rt_uint8_t *)os_malloc(2048 + USB_RX_BUFF_RESERVE_SIZE);
|
||
if (rndis->data_buffer == NULL) {
|
||
os_printf("rndis data buffer alloc fail\r\n");
|
||
os_free(rndis->msg_buffer);
|
||
os_free(rndis);
|
||
return -ENOMEM;
|
||
}
|
||
rndis->ts_buffer = (rt_uint8_t *)os_zalloc(2048 + USB_RX_BUFF_RESERVE_SIZE);
|
||
if(rndis->ts_buffer == NULL) {
|
||
os_printf("rndis ts_buf alloc fail\r\n");
|
||
os_free(rndis->msg_buffer);
|
||
os_free(rndis->data_buffer);
|
||
os_free(rndis);
|
||
return -ENOMEM;
|
||
}
|
||
rndis->ts_saveLength = 0;
|
||
rndis->device = intf[0]->device;
|
||
rndis->req_id = 1;
|
||
intf[0]->user_data = rndis;
|
||
|
||
for (ep_index = 0; ep_index < intf[0]->intf_desc->bNumEndpoints; ++ep_index) {
|
||
rt_usbh_get_endpoint_descriptor(intf[0]->intf_desc, ep_index, &ep_desc);
|
||
if (ep_desc == NULL) {
|
||
return RET_ERR;
|
||
}
|
||
|
||
if ((ep_desc->bmAttributes & USB_EP_ATTR_TYPE_MASK) != USB_EP_ATTR_INT)
|
||
continue;
|
||
|
||
if ((ep_desc->bEndpointAddress & USB_DIR_MASK) == USB_DIR_IN) {
|
||
if (rt_usb_hcd_alloc_pipe(intf[0]->device->hcd, &pipe, intf[0]->device, ep_desc) != RT_EOK) {
|
||
rt_kprintf("alloc pipe failed\n");
|
||
return -RT_ERROR;
|
||
}
|
||
rt_usb_instance_add_pipe(intf[0]->device, pipe);
|
||
rndis->pipe_int = pipe;
|
||
}
|
||
}
|
||
|
||
for (ep_index = 0; ep_index < intf[1]->intf_desc->bNumEndpoints; ++ep_index) {
|
||
rt_usbh_get_endpoint_descriptor(intf[1]->intf_desc, ep_index, &ep_desc);
|
||
if (ep_desc == NULL) {
|
||
return RET_ERR;
|
||
}
|
||
|
||
if ((ep_desc->bmAttributes & USB_EP_ATTR_TYPE_MASK) != USB_EP_ATTR_BULK)
|
||
continue;
|
||
|
||
if (rt_usb_hcd_alloc_pipe(intf[0]->device->hcd, &pipe, intf[0]->device, ep_desc) != RT_EOK) {
|
||
rt_kprintf("alloc pipe failed\n");
|
||
return -RT_ERROR;
|
||
}
|
||
rt_usb_instance_add_pipe(intf[0]->device, pipe);
|
||
if ((ep_desc->bEndpointAddress & USB_DIR_MASK) == USB_DIR_IN) {
|
||
rndis->pipe_in = pipe;
|
||
} else {
|
||
rndis->pipe_out = pipe;
|
||
}
|
||
}
|
||
|
||
rt_usbh_rndis_run(rndis);
|
||
}
|
||
|
||
return RET_OK;
|
||
}
|
||
|
||
static rt_err_t rt_usbh_wireless_disable(void *arg)
|
||
{
|
||
struct uhintf *intf = arg;
|
||
struct usb_rndis *rndis = NULL;
|
||
|
||
if (intf == NULL) {
|
||
return -EIO;
|
||
}
|
||
|
||
rndis = intf->user_data;
|
||
if (rndis) {
|
||
rt_usbh_rndis_stop(rndis);
|
||
}
|
||
|
||
return RET_OK;
|
||
}
|
||
|
||
ucd_t rt_usbh_class_driver_wireless(void)
|
||
{
|
||
wireless_driver.class_code = USB_CLASS_WIRELESS;
|
||
|
||
wireless_driver.enable = rt_usbh_wireless_enable;
|
||
wireless_driver.disable = rt_usbh_wireless_disable;
|
||
|
||
return &wireless_driver;
|
||
}
|
||
|
||
#endif |