USB NCM usbnet 枚举流程代码分析
一、cdc_ncm.c
在linux 驱动中,CDC NCM的驱动位于: kerneldrivers
etusbcdc_ncm.c
static struct usb_driver cdc_ncm_driver = {
.name = "cdc_ncm",
.id_table = cdc_devs,
.probe = usbnet_probe,
.disconnect = usbnet_disconnect,
.suspend = usbnet_suspend,
.resume = usbnet_resume,
.reset_resume = usbnet_resume,
.supports_autosuspend = 1,
.disable_hub_initiated_lpm = 1,
};
module_usb_driver(cdc_ncm_driver);
在结构体cdc_ncm_driver
中,比较重要的是id_table
,probe
这两个,
在id_table
中定义了所有符合cdc_ncm
设备的 idVendor
号,当linux
枚举时检测到USB设备的idVendor
在这个id_table
中时,就会调用usbnet_probe
进行起网操作。
1.1 struct usb_device_id结构体
在分析cdc_ncm
的id_table
之前,我们先来看下usb_device_id
结构体是如何定义的:
struct usb_device_id {
/* which fields to match against? */
__u16 match_flags; //说明使用哪种匹配方式
/* Used for product specific matches; range is inclusive */
__u16 idVendor; //供应商ID
__u16 idProduct; //产品ID
__u16 bcdDevice_lo;
__u16 bcdDevice_hi;
/* Used for device class matches */
__u8 bDeviceClass; //设备类型
__u8 bDeviceSubClass; //设备子类型
__u8 bDeviceProtocol; //协议
/* Used for interface class matches */
__u8 bInterfaceClass; //接口类
__u8 bInterfaceSubClass; //接口子类
__u8 bInterfaceProtocol; //接口协议
/* Used for vendor-specific interface matches */
__u8 bInterfaceNumber;
/* not matched against */
kernel_ulong_t driver_info
__attribute__((aligned(sizeof(kernel_ulong_t)))); // NCM 驱动结构体,其中包含了收发包的函数等
};
结合结构体定义,我们来看下cdc_ncm
的id_table
:
static const struct usb_device_id cdc_devs[] = {
// 爱立信 F5521gw USB网卡
/* Ericsson MBM devices like F5521gw */
{ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | USB_DEVICE_ID_MATCH_VENDOR,
//匹配方式:CLASS(设备类)、SUBCLASS(子类)、PROTOCOL(设备协议)
.idVendor = 0x0bdb, //供应商ID: 0x0bdb
.bInterfaceClass = USB_CLASS_COMM, //设备类型: 网卡类
.bInterfaceSubClass = USB_CDC_SUBCLASS_NCM, //设备子类型:NCM
.bInterfaceProtocol = USB_CDC_PROTO_NONE, //设备协议: 无
.driver_info = (unsigned long) &wwan_info, // NCM 驱动结构体,其中包含了收发包的函数等
},
/* DW5812 LTE Verizon Mobile Broadband Card Unlike DW5550 this device requires FLAG_NOARP */
{ USB_DEVICE_AND_INTERFACE_INFO(0x413c, 0x81bb,
USB_CLASS_COMM,
USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
.driver_info = (unsigned long)&wwan_noarp_info,
},
/* DW5813 LTE AT&T Mobile Broadband Card Unlike DW5550 this device requires FLAG_NOARP */
{ USB_DEVICE_AND_INTERFACE_INFO(0x413c, 0x81bc,
USB_CLASS_COMM,
USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
.driver_info = (unsigned long)&wwan_noarp_info,
},
/* Dell branded MBM devices like DW5550 */
{ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x413c,
.bInterfaceClass = USB_CLASS_COMM,
.bInterfaceSubClass = USB_CDC_SUBCLASS_NCM,
.bInterfaceProtocol = USB_CDC_PROTO_NONE,
.driver_info = (unsigned long) &wwan_info,
},
/* Toshiba branded MBM devices */
{ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x0930,
.bInterfaceClass = USB_CLASS_COMM,
.bInterfaceSubClass = USB_CDC_SUBCLASS_NCM,
.bInterfaceProtocol = USB_CDC_PROTO_NONE,
.driver_info = (unsigned long) &wwan_info,
},
/* tag Huawei devices as wwan */
{ USB_VENDOR_AND_INTERFACE_INFO(0x12d1,
USB_CLASS_COMM,
USB_CDC_SUBCLASS_NCM,
USB_CDC_PROTO_NONE),
.driver_info = (unsigned long)&wwan_info,
},
/* Infineon(now Intel) HSPA Modem platform */
{ USB_DEVICE_AND_INTERFACE_INFO(0x1519, 0x0443,
USB_CLASS_COMM,
USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
.driver_info = (unsigned long)&wwan_noarp_info,
},
/* Generic CDC-NCM devices */
{ USB_INTERFACE_INFO(USB_CLASS_COMM,
USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
.driver_info = (unsigned long)&cdc_ncm_info,
}
};
MODULE_DEVICE_TABLE(usb, cdc_devs);
1.1.1 match_flags 设备类型
所有的match_flags
定义在mod_devicetable.h
中:
/* Some useful macros to use to create struct usb_device_id */
1.1.2 bInterfaceClass 接口类
/* Device and/or Interface Class codes
* as found in bDeviceClass or bInterfaceClass
* and defined by www.usb.org documents */
/* for DeviceClass */
//声音设备
//调制解调器,网卡,ISDN连接
//HID设备,如鼠标,键盘
//物理设备
//静止图像捕捉设备
//打印机
//批量存储设备
//USB HUBS
/* chip+ smart card */ //智能卡
/* content security */
//视频设备,如网络摄像头
//网络控制设备
//杂项设备
//厂商自定义的设备
wait…
本文摘自 :https://blog.51cto.com/c