驱动移植
4G模块加载 USB 转串口驱动option后会在/dev/下创建ttyUSB0、ttyUSB1 和 ttyUSB2 等设备文件。如果没有出现,需要在drivers/usb/serial/option.c里添加VID(Vendor ID)与PID(Product ID)
USB 转串口驱动修改
通过lsusb可得到
Bus 001 Device 002: ID 1a86:8091
Bus 001 Device 001: ID 1d6b:0002
Bus 002 Device 001: ID 1d6b:0002
Bus 003 Device 001: ID 1d6b:0002
Bus 001 Device 004: ID 2c7c:0904
在drivers/usb/serial/option.c里添加
static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(0x2C7C, 0x6002) }, /* Quectel EC800M */
{ USB_DEVICE(0x2C7C, 0x0904) }, /* Quectel EC800G */
{ USB_DEVICE(0x05C6, 0x9215) }, /* Quectel EC20 */
..
}
static int option_probe(struct usb_serial *serial,
const struct usb_device_id *id)
{
struct usb_interface_descriptor *iface_desc =
&serial->interface->cur_altsetting->desc;
struct usb_device_descriptor *dev_desc = &serial->dev->descriptor;
const struct option_blacklist_info *blacklist;
#if 1 //Added byQuectel
if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C)) {
__u16 idProduct = le16_to_cpu(serial->dev->descriptor.idProduct);
struct usb_interface_descriptor *intf = &serial->interface->cur_altsetting->desc;
if (intf->bInterfaceClass != 0xFF || intf->bInterfaceSubClass == 0x42) {
//ECM, RNDIS, NCM, MBIM, ACM, UAC, ADB
return -ENODEV;
}
if ((idProduct&0xF000) == 0x0000) {
//MDM interface 4 is QMI
if (intf->bInterfaceNumber == 4 && intf->bNumEndpoints == 3
&& intf->bInterfaceSubClass == 0xFF && intf->bInterfaceProtocol == 0xFF)
return -ENODEV;
}
}
#endif
.......
}
添加零包机制
根据 USB 协议的要求,通过添加如下语句在 bulk-out 传输过程中添加处理零包的机制: 高于 2.6.34 的 Linux 内核版本,需在[KERNEL]/drivers/usb/serial/usb_wwan.c 文件中添加以下语句。低于 2.6.35 的 Linux 内核版本,需在[KERNEL]/drivers/usb/serial/option.c 文件中添加。
static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
int endpoint,
int dir, void *ctx, char *buf, int len,
void (*callback) (struct urb *))
{
struct usb_serial *serial = port->serial;
struct urb *urb;
urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
if (!urb)
return NULL;
usb_fill_bulk_urb(urb, serial->dev,
usb_sndbulkpipe(serial->dev, endpoint) | dir,
buf, len, callback, ctx);
#if 1 //Added by Quectel for Zero Packet
if (dir == USB_DIR_OUT) {
struct usb_device_descriptor *desc = &serial->dev->descriptor;
if (desc->idVendor == cpu_to_le16(0x2C7C))
urb->transfer_flags |= URB_ZERO_PACKET;
}
#endif
return urb;
}
添加 Reset-resume 机制
static struct usb_serial_driver option_1port_device = {
……
#ifdef CONFIG_PM
.suspend = usb_wwan_suspend,
.resume = usb_wwan_resume,
#if 1 //Added by Quectel
.reset_resume = usb_wwan_resume,
#endif
#endif
};
确保内核开启CONFIG_USB_SERIAL = y
常用命令
udhcpc
udhcpc是Busybox的非常小的DHCP的客户端,所谓的DHCP(Dynamic Host Configuration Protocol)是一个局域网的网络协议,使用UDP协议进行工作。1:用于给内部网或网络服务供应商自动分配 IP 地址;2:用户用于内部网管理员作为对所有计算机作中央管理的手段
- -i 指定网卡
- -s 指定发生dhcp事件时运行的脚本
租约
DHCP Server 临时把一个 IP 地址以及相关网络参数 “租” 给客户端使用一段时间。ubs0 使用dhcpc申请地址的时候,4G模块内部的DHCP Server 可能会返回如下内容:
IP: 10.49.93.93
Netmask: 255.255.255.0
Gateway: 10.49.93.1
DNS: 8.8.8.8
Lease: 3600 秒
这个Lease就租约时间,相当于"10.49.93.93 这个 IP 给你用 3600 秒。" 租约到期之前,udhcpc会负责续约,调用脚本
#!/bin/sh
# generated by nvr_test (WanFailover): usb0 lease recorder
case "$1" in
deconfig)
ifconfig usb0 0.0.0.0
rm -f /tmp/usb0.lease
;;
bound|renew)
NETMASK=""
[ -n "$subnet" ] && NETMASK="netmask $subnet"
ifconfig usb0 $ip $NETMASK
{
echo "router $router"
echo "dns $dns"
} > /tmp/usb0.lease.tmp
mv /tmp/usb0.lease.tmp /tmp/usb0.lease
;;
esac
exit 0
- bound:第一次成功拿到租约
- renew:已有租约续租成功
- deconfig:租约失效,需要把地址撤掉