配置文件
//kernel-4.9/arch/arm64/configs/xxx_android_defconfig
USB_SERIAL=y
CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_OPTION=y
//kernel-4.9/drivers/usb/serial/Kconfig
config USB_SERIAL_OPTION
tristate "USB driver for GSM and CDMA modems"
select USB_SERIAL_WWAN
help
Say Y here if you have a GSM or CDMA modem that's connected to USB.
This driver also supports several PCMCIA cards which have a
built-in OHCI-USB adapter and an internally-connected GSM modem.
The USB bus on these cards is not accessible externally.
Supported devices include (some of?) those made by:
Option, Huawei, Audiovox, Novatel Wireless, or Anydata.
To compile this driver as a module, choose M here: the
module will be called option.
If this driver doesn't recognize your device,
it might be accessible via the FTDI_SIO driver.
配置的usb转串口,是给4G类似模组使用的,通信模块一般使用AT指令方式,这里就是用USB虚拟串口。
流程
一般使用的文件是 kernel-4.9/drivers/net/usb/下的文件,ncm,ecm,ether这些
//kernel-4.9/include/linux/usb/usbnet.h
#define FLAG_POINTTOPOINT 0x1000 /* possibly use "usb%d" names */
//kernel-4.9/drivers/net/usb/cdc_ether.c
static const struct driver_info cdc_info = {
.description = "CDC Ethernet Device",
.flags = FLAG_ETHER | FLAG_POINTTOPOINT,//设置类型
.bind = usbnet_cdc_bind,
.unbind = usbnet_cdc_unbind,
.status = usbnet_cdc_status,
.set_rx_mode = usbnet_cdc_update_filter,
.manage_power = usbnet_manage_power,
};
{
....//这里是usb idVendor 和 idProduct
}
MODULE_DEVICE_TABLE(usb, products);
static struct usb_driver cdc_driver = {
.name = "cdc_ether",
.id_table = products,
.probe = usbnet_probe,//使用同一个函数
.disconnect = usbnet_disconnect,
.suspend = usbnet_suspend,
.resume = usbnet_resume,
.reset_resume = usbnet_resume,
.supports_autosuspend = 1,
.disable_hub_initiated_lpm = 1,
};
//kernel-4.9/drivers/net/usb/usbnet.c
int
usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
{
...
dev->net = net;
strcpy (net->name, "usb%d");//这里就是usb0
memcpy (net->dev_addr, node_id, sizeof node_id);
...
// heuristic: "usb%d" for links we know are two-host,
// else "eth%d" when there's reasonable doubt. userspace
// can rename the link if it knows better.
if ((dev->driver_info->flags & FLAG_ETHER) != 0 &&
((dev->driver_info->flags & FLAG_POINTTOPOINT) == 0 ||
(net->dev_addr [0] & 0x02) == 0))
strcpy (net->name, "eth%d");
/* WLAN devices should always be named "wlan%d" */
if ((dev->driver_info->flags & FLAG_WLAN) != 0)
strcpy(net->name, "wlan%d");
/* WWAN devices should always be named "wwan%d" */
if ((dev->driver_info->flags & FLAG_WWAN) != 0)
strcpy(net->name, "wwan%d");
/* devices that cannot do ARP */
if ((dev->driver_info->flags & FLAG_NOARP) != 0)
net->flags |= IFF_NOARP;
...
}
这里先将 usb 的 idVendor 和 idProduct 加到 id_table 表里,然后调用 usbnet_probe ,在函数 usbnet_probe 中靠flags 区分注册的名字,这里如果想自定义名字,可以自己在 usbnet.h 中定义个 FLAG 加入到 FLAG 值中,usbnet_probe 中区分 FLAG 修改名字。
//kernel-4.9/include/linux/usb/usbnet.h
#define FLAG_MY_USB 0x1002 /* possibly use "my_usb%d" names */
//kernel-4.9/drivers/net/usb/rndis_host.c
static const struct driver_info rndis_info = {
.description = "RNDIS device",
// .flags = FLAG_ETHER | FLAG_POINTTOPOINT | FLAG_FRAMING_RN | FLAG_NO_SETINT,
.flags = FLAG_ETHER | FLAG_MY_USB | FLAG_FRAMING_RN | FLAG_NO_SETINT,
.bind = rndis_bind,
.unbind = rndis_unbind,
.status = rndis_status,
.rx_fixup = rndis_rx_fixup,
.tx_fixup = rndis_tx_fixup,
};
//kernel-4.9/drivers/net/usb/usbnet.c
int
usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
{
...
if ((dev->driver_info->flags & FLAG_ETHER) != 0 &&
(dev->driver_info->flags & FLAG_MY_USB) != 0)
strcpy (net->name, "my_usb%d");
...
}