周立功IoT7000li编译移远EC20驱动记录
1.USB 串口驱动修改
1.1 增加VID和PID
为了使内核识别模块,需要增加模块的 VID 和 PID 信息,如程序清单 1.1 所示。
程序清单 1.1 增加 PID 和 VID
file:drivers/usb/serial/option.c
#define VIATELECOM_VENDOR_ID 0x15eb #define VIATELECOM_PRODUCT_CDS7 0x0001
#define QUECTEL_VENNDOR_EC20 0x2c7c /* 这里的 ID 与移远给的资料不一致 */
#define QUECTEL_PRODUCT_EC20 0x0125 /* EC20 模块的 ID 就是 0x2c7c,0x0125*/
……
static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(QUECTEL_VENNDOR_EC20,QUECTEL_PRODUCT_EC20) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) },
......
#ifdef CONFIG_PM
.suspend = usb_wwan_suspend,
.resume = usb_wwan_resume,
#if 1
.reset_resume = usb_wwan_resume,
#endif
#endif
1.2 增加零件包处理
根据 USB 协议要求,需要在大容量输出传输过程中添加处理零包的机制,如程序清单 1.2 所示。
程序清单 1.2 添加零包处理
file: drivers/usb/serial/usb_wwan.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(0x05C6) && desc->idProduct == cpu_to_le16(0x9090))
urb->transfer_flags |= URB_ZERO_PACKET;
if (desc->idVendor == cpu_to_le16(0x05C6) && desc->idProduct == cpu_to_le16(0x9003))
urb->transfer_flags |= URB_ZERO_PACKET;
if (desc->idVendor == cpu_to_le16(0x05C6) && desc->idProduct == cpu_to_le16(0x9215))
urb->transfer_flags |= URB_ZERO_PACKET;
if (desc->idVendor == cpu_to_le16(0x2C7C))
urb->transfer_flags |= URB_ZERO_PACKET;
}
#endif
return urb;
}
1.3 接口定义及处理
使用移远模块包括以下几个程序接口,表 1.1 描述了 EC20 模块在 Linux 系统中的接口信息。
表 1.1 EC20 接口信息
需要将 InterfaceNumber 大于等于 4 的接口分离出来,避免 USB 串口驱动注册,修改如程序清单 1.3 所示。
程序清单 1.3 屏蔽 InterfaceNumber
file: drivers/usb/serial/option.c
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;
/* Never bind to the CD-Rom emulation interface */
if (iface_desc->bInterfaceClass == 0x08)
return -ENODEV;
/*
* Don't bind reserved interfaces (like network ones) which often have
* the same class/subclass/protocol as the serial interfaces. Look at
* the Windows driver .INF files for reserved interface numbers.
*/
blacklist = (void *)id->driver_info;
if (blacklist && test_bit(iface_desc->bInterfaceNumber,
&blacklist->reserved))
return -ENODEV;
/*
* Don't bind network interface on Samsung GT-B3730, it is handled by
* a separate module.
*/
if (dev_desc->idVendor == cpu_to_le16(SAMSUNG_VENDOR_ID) &&
dev_desc->idProduct == cpu_to_le16(SAMSUNG_PRODUCT_GT_B3730) &&
iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
return -ENODEV;
/* modify start */
#if 1
if (serial->dev->descriptor.idVendor == cpu_to_le16(QUECTEL_VENNDOR_EC20) &&
serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4) {
printk("find the interface for EC20 NDIS\n");
return -ENODEV;
}
#endif
/* modify end*/
/* Store the blacklist info so we can use it during attach. */
usb_set_serial_data(serial, (void *)blacklist);
return 0;
}
1.4 删除 qcserial 驱动的 EC20 支持
删除 qcserial 驱动的 EC20 支持,如程序清单 1.4 和程序清单 1.5 所示。
程序清单 1.4 删除 qmi 的 EC20 支持
file: drivers/net/usb/qmi_wwan.c
static const struct usb_device_id products[] = {
{QMI_GOBI_DEVICE(0x05c6, 0x9225)}, /* Sony Gobi 2000 Modem device (N0279, VU730) */
{QMI_GOBI_DEVICE(0x05c6, 0x9245)}, /* Samsung Gobi 2000 Modem device (VL176) */
{QMI_GOBI_DEVICE(0x03f0, 0x251d)}, /* HP Gobi 2000 Modem device (VP412) */
/*{QMI_GOBI_DEVICE(0x05c6, 0x9215)},*/ /* Acer Gobi 2000 Modem device (VP413) */
{QMI_GOBI_DEVICE(0x05c6, 0x9265)}, /* Asus Gobi 2000 Modem device (VR305) */
{QMI_GOBI_DEVICE(0x05c6, 0x9235)}, /* Top Global Gobi 2000 Modem device (VR306) */
程序清单 1.5 删除 qcserial 的 EC20 支持
file: drivers/usb/serial/qcserial.c
const struct usb_device_id id_table[] = {
{USB_DEVICE(0x03f0, 0x241d)}, /* HP Gobi 2000 QDL device (VP412) */
{USB_DEVICE(0x03f0, 0x251d)}, /* HP Gobi 2000 Modem device (VP412) */
{USB_DEVICE(0x05c6, 0x9214)}, /* Acer Gobi 2000 QDL device (VP413) */
/*{USB_DEVICE(0x05c6, 0x9215)},*/ /* Acer Gobi 2000 Modem device (VP413) */
{USB_DEVICE(0x05c6, 0x9264)}, /* Asus Gobi 2000 QDL device (VR305) */
{USB_DEVICE(0x05c6, 0x9265)}, /* Asus Gobi 2000 Modem device (VR305) */
{USB_DEVICE(0x05c6, 0x9234)}, /* Top Global Gobi 2000 QDL device (VR306) */
修改完整的的包,下载
1.3.5 内核配置选项
在 make menuconfig 界面作如下所示的配置:
配置完之后编译内核烧写到目标板。烧录内核后,查看是否能正常识别模块、有无 USB接口生成、AT 指令是否正常等。如程序清单 1.6 所示。
程序清单 1.6 查看模块状态
[root@M6G2C ~]# lsusb Bus 001 Device 001: ID 1d6b:0002 Bus 002 Device 001: ID 1d6b:0002 Bus 001 Device 002: ID 2c7c:0125 [root@M6G2C ~]#ls /dev/ttyUSB* /dev/ttyUSB0 /dev/ttyUSB1 /dev/ttyUSB2 /dev/ttyUSB3 [root@ M6G2C ~]# microcom -s 9600 /dev/ttyUSB2 ate OK at+csq +CSQ: 15,99
1.6 PPP 拨号
将原厂提供的 05 Driver/Linux/USB/Quectel_WCDMA<E_Linux_USB_R01A01/linux-ppp-scripts_V1.2/linux-ppp-scripts 目录下的 quectel-chat-connect、uectel-chat-disconnect、quectel-ppp 拷贝到板子/etc/ppp/peers 目录下。拷贝 pppd 和 chat 命令到板子/usr/bin 目录
下。
quectel-ppp 里修改串口设备名,pppd 拨号使用的 username、password 在quectel-char-connect 里修改 APN。APN、username、passward 需要从网络提供商获取。APN修改如程序清单 1.7 所示。串口设备名、username、password 修改如程序清单 1.8 所示。
程序清单 1.7 APN 修改
# /etc/ppp/peers/quectel-chat-connect ABORT "BUSY" ABORT "NO CARRIER" ABORT "NO DIALTONE" ABORT "ERROR" ABORT "NO ANSWER" TIMEOUT 30 "" AT OK ATE0 OK ATI;+CSUB;+CSQ;+CPIN?;+COPS?;+CGREG?;&D2 # Insert the APN provided by your network operator, default apn is 3gnet OK AT+CGDCONT=1,"IP","cmnet",,0,0 OK ATD*99# CONNECT
程序清单 1.8 使用的拨号串口修改
# /etc/ppp/peers/quectel-pppd # Usage:root>pppd call quectel-pppd #Modem path, like /dev/ttyUSB3,/dev/ttyACM0, depend on your module, default path is /dev/ttyUSB3 /dev/ttyUSB3 115200 #Insert the username and password for authentication, default user and password are test user "test" password "test" ……
运行 pppd 命令进行拨号,正常现象如下所示。
[root@ M6G2C ~]# pppd call quectel-ppp & …… local IP address 10.37.158.154 remote IP address 10.64.64.64 primaryDNS address 211.136.17.107 secondary DNS address 211.136.20.203 [root@ M6G2C ~]# ifconfig ppp0 ppp0 Link encap:Point-to-Point Protocol inet addr:10.37.158.154 P-t-P:10.64.64.64 Mask:255.255.255.255 UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1 RX packets:4 errors:0 dropped:0 overruns:0 frame:0 TX packets:5 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:3 RX bytes:52 (52.0 B) TX bytes:183 (183.0 B) [root@ M6G2C ~]#echo "nameserver 8.8.8.8" > /etc/resolv.conf [root@ M6G2C ~]# ping www.baidu.com PING baidu.com (123.125.114.144): 56 data bytes 64 bytes from 123.125.114.144: seq=0 ttl=53 time=102.081 ms 64 bytes from 123.125.114.144: seq=1 ttl=53 time=113.556 ms 64 bytes from 123.125.114.144: seq=2 ttl=53 time=84.534 ms