适配4G模块 EC20 使用ppp拨号上网

一、USB Serial Driver 安装

当设备连接4G模块后,查看 /dev 下是否有以下设备文件:

ttyUSB0/ttyUSB1/ttyUSB2…

如果没有,则需要按照下列步骤集成USB串行驱动程序(以下操作均需要在内核根目录下进行,因此在操作前要安装对应版本的内核源码):

1.1 添加 VID 和 PID

为了识别模块,客户应该添加模块VID和PID信息,如下所示:

File: [KERNEL]/drivers/usb/serial/option.c

static const struct usb_device_id option_ids[] = { 
#if 1 //Added by Quectel
 { USB_DEVICE(0x05C6, 0x9090) }, /* Quectel UC15 */ 
 { USB_DEVICE(0x05C6, 0x9003) }, /* Quectel UC20 */ 
 { USB_DEVICE(0x2C7C, 0x0125) }, /* Quectel EC25 */
 { USB_DEVICE(0x2C7C, 0x0121) }, /* Quectel EC21 */ 
 { USB_DEVICE(0x05C6, 0x9215) }, /* Quectel EC20 */ 
{ USB_DEVICE(0x2C7C, 0x0191) }, /* Quectel EG91 */ 
{ USB_DEVICE(0x2C7C, 0x0195) }, /* Quectel EG95 */
{ USB_DEVICE(0x2C7C, 0x0306) }, /* Quectel EG06/EP06/EM06 */
{ USB_DEVICE(0x2C7C, 0x0296) }, /* Quectel BG96 */
{ USB_DEVICE(0x2C7C, 0x0435) }, /* Quectel AG35 */
#endif

对于EC20模块,如果内核源文件中存在以下文件和语句,请删除它们,因为它们会与EC20的USB驱动程序冲突。

File: [KERNEL]/drivers/usb/serial/qcserial.c

{USB_DEVICE(0x05c6, 0x9215)}, /* Acer Gobi 2000 Modem device (VP413) */ 

File: [KERNEL]/drivers/net/usb/qmi_wwan.c

{QMI_GOBI_DEVICE(0x05c6, 0x9215)}, /* Acer Gobi 2000 Modem device (VP413) */
1.2 添加零分组机制

根据USB协议的要求,客户需要在大量传输过程中添加用于处理零数据包的机制。
对于高于2.6.34的Linux内核版本:

File: [KERNEL]/drivers/usb/serial/usb_wwan.c

static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint, int dir, void *ctx, char *buf, int len,void (*callback) (struct urb *)) 
	{ 
	……
	 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; 
	} 

对于Linux内核版本低于2.6.35:

File: [KERNEL]/drivers/usb/serial/option.c

/* Helper functions used by option_setup_urbs */ 
	static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint,
		int dir, void *ctx, char *buf, int len, 
		 void (*callback)(struct urb *)) 
	{ 
	……
	 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 添加重置恢复

一些USB主机控制器/USB集线器将在MCU进入暂停/睡眠模式时损失或重置,并且在MCU从暂停/睡眠模式下退出后,它们无法恢复USB设备。请添加以下语句以启用重置恢复过程。

对于Linux内核版本高于3.4:

File: [KERNEL]/drivers/usb/serial/option.c

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 
};

对于Linux内核版本低于3.5:

File: [KERNEL]/drivers/usb/serial/ usb-serial.c

/* Driver structure we register with the USB core */ 
	static struct usb_driver usb_serial_driver = { 
		 .name = "usbserial", 
		 .probe = usb_serial_probe, 
		 .disconnect = usb_serial_disconnect, 
		 .suspend = usb_serial_suspend, 
		 .resume = usb_serial_resume, 
	#if 1 //Added by Quectel
		.reset_resume = usb_serial_resume, 
	#endif
		 .no_dynamic_id = 1, 
		 .supports_autosuspend = 1, 
	};
1.4 放大散装网址

对于低于2.6.29的Linux内核版本,大量URB需要放大以获得更快的上行链路速度。

File: [KERNEL]/drivers/usb/serial/option.c

#define N_IN_URB 4 
#define N_OUT_URB 4 //Quectel 1
#define IN_BUFLEN 4096 
#define OUT_BUFLEN 4096 //Quectel 128
1.5 使用 GobiNet 或 QMI WWAN

如果要求使用Gobinet或QMI WWAN,请添加以下语句以防止这些模块的接口4作为USB串行设备。

对于Linux内核版本高于2.6.30:

File: [KERNEL]/drivers/usb/serial/option.c

static int option_probe(struct usb_serial *serial, const struct usb_device_id *id) { 
		struct usb_wwan_intf_private *data; 
		……
	#if 1 //Added by Quectel
	//Quectel UC20's interface 4 can be used as USB network device 
		if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
	serial->dev->descriptor.idProduct == cpu_to_le16(0x9003) 
			&& serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4) 
			return -ENODEV; 
	//Quectel EC20's interface 4 can be used as USB network device 
		if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && 
	serial->dev->descriptor.idProduct == cpu_to_le16(0x9215) 
		 	&& serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4) 
		 	return -ENODEV; 
	//Quectel EC25&EC21&EG91&EG95&EG06&EP06&EM06&BG96/AG35's interface 4 can be used as USB network device 
	 	if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C) 
			&& serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4) 
			return -ENODEV; 
	#endif
		 /* Store device id so we can use it during attach. */ 
		 usb_set_serial_data(serial, (void *)id); 
		 return 0; 
	} 

对于Linux内核版本低于2.6.31:

File: [KERNEL]/drivers/usb/serial/option.c

static int option_startup(struct usb_serial *serial) 
	{ 
	……
		dbg("%s", __func__); 
	#if 1 //Added by Quectel
	//Quectel UC20's interface 4 can be used as USB network device 
		if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && 
	serial->dev->descriptor.idProduct == cpu_to_le16(0x9003) 
		 	&& serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4) 
		 	return -ENODEV; 
	//Quectel EC20's interface 4 can be used as USB network device 
		if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && 
	serial->dev->descriptor.idProduct == cpu_to_le16(0x9215) 
			&& serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4) 
		 	return -ENODEV; 
	//Quectel EC25&EC21&EG91&EG95&EG06&EP06&EM06&BG96/AG35's interface 4 can be used as USB network device 
		if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C) 
		 	&& serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4) 
		 	return -ENODEV; 
	#endif 
	……
	}
1.6 修改内核配置

内核配置中有几个强制性选定项目,请按照以下步骤配置内核:

步骤1:进入到内核根目录。

cd < your kernel directory >

步骤2:设置环境变量和导入板的defconfig。以下是RaspeBerry Pi板的示例。

export ARCH=arm
export CROSS_COMPILE=arm-none-linux-gnueabi-
make bcmrpi_defconfig

对于X86架构的系统,我的默认的defconfig文件为x86_64_defconfig,只需要在内核根目录下 make x86_64_defconfig

步骤3:编译内核。

make menuconfig

步骤4:启用CONFIG_USB_SERIAL_OPTION

[*] Device Drivers →

      	[*] USB Support →  

               [*] USB Serial Converter support →

                      [*] USB driver for GSM and CDMA modems
1.7 作为内核模块构建并加载驱动程序

请按照以下步骤将驱动程序作为内核模块构建。

步骤1:进入到内核根目录。

cd < your kernel directory >

步骤2:构建驱动程序。

sudo make -C /lib/modules/`uname -r`/build M=`pwd`/drivers/usb/serial obj-m=option.o modules
sudo make -C /lib/modules/`uname -r`/build M=`pwd`/drivers/usb/serial obj-m=usb_wwan.o modules
sudo make -C /lib/modules/`uname -r`/build M=`pwd`/drivers/usb/serial obj-m=qcserial.o modules

步骤3:加载驱动程序并重新启动。

sudo cp drivers/usb/serial/option.ko /lib/modules/`uname -r`/kernel/drivers/usb/serial
sudo cp drivers/usb/serial/usb_wwan.ko /lib/modules/`uname -r`/kernel/drivers/usb/serial
sudo cp drivers/usb/serial/qcserial.ko /lib/modules/`uname -r`/kernel/drivers/usb/serial
sudo depmod
sudo reboot

二、配置内核以支持PPP

首先检测 /dev 下面是否有 ppp 设备,没有的话请按照以下步骤配置内核以支持PPP。

步骤1:进入到内核根目录。

cd < your kernel directory >

步骤2:设置环境变量和导入板的defconfig。下面显示了一个例子。

export ARCH=arm
export CROSS_COMPILE=arm-none-linux-gnueabi-
make bcmrpi_defconfig

对于X86架构的系统,我的默认的defconfig文件为x86_64_defconfig,只需要在内核根目录下 make x86_64_defconfig

步骤3:编译内核。

make menuconfig

步骤4:启用CONFIG_PPP_ASYNC CONFIG_PPP_SYNC_TTY CONFIG_PPP_DEFLATE

[*] Device Drivers → 

		[*] Network device support → 
		
				[*] PPP (point-to-point protocol) support

内核启动后在 /dev 下生成 ppp 设备节点

三、测试PPP拨号上网

下载ppp服务:https://ppp.samba.org/download.html

解压:tar -xzvf ppp-2.4.4.tar.gz
cd ppp-2.4.4
./configure
make && make install

实现ppp拨号上网:

查看是否有名为/etc/ppp/ip-up的ppp脚本文件,用于设置DNS(域名系统)。如果没有这样的文件,请使用 Quectel 提供的linux-ppp-scripts\ip-up
关于 linux-ppp-scripts_V1.2.zip 请自行到网上下载。

解压:unzip linux-ppp-scripts_V1.2.zip

linux-ppp-scripts 里面的 quectel-pppquectel-chat-connectquectel-chat-disconnect 三个脚本复制到 /etc/ppp/peers 目录下
根据不同的模块,客户可能需要进行一些更改。有关更多信息,请参阅 linux-ppp-scripts\readme

然后通过以下命令开始设置PPP呼叫:

pppd call quectel-ppp &

拨号过程如下所示(EC20的示例):

# pppd options in effect: 
debug # (from /etc/ppp/peers/quectel-ppp) 
nodetach # (from /etc/ppp/peers/quectel-ppp) 
dump # (from /etc/ppp/peers/quectel-ppp) 
noauth # (from /etc/ppp/peers/quectel-ppp) 
user test # (from /etc/ppp/peers/quectel-ppp) 
password ?????? # (from /etc/ppp/peers/quectel-ppp) 
remotename 3gppp # (from /etc/ppp/peers/quectel-ppp) 
/dev/ttyUSB3 # (from /etc/ppp/peers/quectel-ppp) 
115200 # (from /etc/ppp/peers/quectel-ppp) 
lock # (from /etc/ppp/peers/quectel-ppp) 
connect chat -s -v -f /etc/ppp/peers/quectel-chat-connect # (from 
/etc/ppp/peers/quectel-ppp) 
disconnect chat -s -v -f /etc/ppp/peers/quectel-chat-disconnect # (from 
/etc/ppp/peers/quectel-ppp) 
nocrtscts # (from /etc/ppp/peers/quectel-ppp) 
modem # (from /etc/ppp/peers/quectel-ppp)
hide-password # (from /etc/ppp/peers/quectel-ppp) 
novj # (from /etc/ppp/peers/quectel-ppp) 
novjccomp # (from /etc/ppp/peers/quectel-ppp) 
ipcp-accept-local # (from /etc/ppp/peers/quectel-ppp) 
ipcp-accept-remote # (from /etc/ppp/peers/quectel-ppp) 
ipparam 3gppp # (from /etc/ppp/peers/quectel-ppp) 
noipdefault # (from /etc/ppp/peers/quectel-ppp) 
ipcp-max-failure 10 # (from /etc/ppp/peers/quectel-ppp) 
defaultroute # (from /etc/ppp/peers/quectel-ppp) 
usepeerdns # (from /etc/ppp/peers/quectel-ppp) 
noccp # (from /etc/ppp/peers/quectel-ppp) 
abort on (BUSY) 
abort on (NO CARRIER) 
abort on (NO DIALTONE) 
abort on (ERROR) 
abort on (NO ANSWER) 
timeout set to 30 seconds 
send (AT^M) 
expect (OK) 
^M
OK
-- got it 
send (ATE0^M) 
expect (OK) 
^M
^M
OK
-- got it
send (ATI;+CSUB;+CSQ;+CPIN?;+COPS?;+CGREG?;&D2^M) 
expect (OK) 
^M
^M
Quectel^M 
EC20^M 
Revision: EC20CQAR02A03E2G_BETA0914^M 
^M
SubEdition: V01^M 
^M
+CSQ: 23,99^M 
^M
+CPIN: READY^M 
^M
+COPS: 0,0,"CHN-CT",7^M 
^M
+CGREG: 2,1,"FFFE","6916934",7^M 
^M
OK
-- got it 
send (AT+CGDCONT=1,"IP","3gnet",,0,0^M) 
expect (OK) 
^M
^M
OK
-- got it 
send (ATD*99#^M) 
expect (CONNECT) 
^M
^M
CONNECT 
-- got it 
Script chat -s -v -f /etc/ppp/peers/quectel-chat-connect finished (pid 3017), status = 0x0 
Serial connection established. 
using channel 3 
Using interface ppp0 
Connect: ppp0 <--> /dev/ttyUSB3 
sent [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0xf2b7d6ee> <pcomp> <accomp>] 
rcvd [LCP ConfReq id=0x4 <asyncmap 0x0> <auth chap MD5> <magic 0x45c0e381> <pcomp> 
<accomp>] 
sent [LCP ConfAck id=0x4 <asyncmap 0x0> <auth chap MD5> <magic 0x45c0e381> <pcomp> 
<accomp>] 
rcvd [LCP ConfAck id=0x1 <asyncmap 0x0> <magic 0xf2b7d6ee> <pcomp> <accomp>] 
rcvd [LCP DiscReq id=0x5 magic=0x45c0e381] 
rcvd [CHAP Challenge id=0x1 <f8d54e0fa294c100101805a512176ff1>, name = 
"UMTS_CHAP_SRVR"] 
sent [CHAP Response id=0x1 <e8ad86182138523599fb54a172da7154>, name = "test"] 
rcvd [CHAP Success id=0x1 ""] 
CHAP authentication succeeded 
CHAP authentication succeeded 
sent [IPCP ConfReq id=0x1 <addr 0.0.0.0> <ms-dns1 0.0.0.0> <ms-dns2 0.0.0.0>] 
rcvd [IPCP ConfReq id=0x4] 
sent [IPCP ConfNak id=0x4 <addr 0.0.0.0>] 
rcvd [IPCP ConfNak id=0x1 <addr 100.65.245.137> <ms-dns1 61.132.163.68> <ms-dns2 
202.102.213.68>] 
sent [IPCP ConfReq id=0x2 <addr 100.65.245.137> <ms-dns1 61.132.163.68> <ms-dns2 
202.102.213.68>] 
rcvd [IPCP ConfReq id=0x5] 
sent [IPCP ConfAck id=0x5] 
rcvd [IPCP ConfAck id=0x2 <addr 100.65.245.137> <ms-dns1 61.132.163.68> <ms-dns2 
202.102.213.68>] 
Could not determine remote IP address: defaulting to 10.64.64.64 
local IP address 100.65.245.137 
remote IP address 10.64.64.64 
primary DNS address 61.132.163.68 
secondary DNS address 202.102.213.68 
Script /etc/ppp/ip-up started (pid 3020) 
Script /etc/ppp/ip-up finished (pid 3020), status = 0x0 

现在PPP呼叫设置成功。通过以下方式查看:

ifconfig ppp0 
ppp0  Link encap:Point-to-Point Protocol 
 		inet addr:100.65.245.137 P-t-P:10.64.64.64 Mask:255.255.255.255 
 		UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1 
 		RX packets:15 errors:0 dropped:0 overruns:0 frame:0 
 		TX packets:19 errors:0 dropped:0 overruns:0 carrier:0 
 		collisions:0 txqueuelen:3 
 		RX bytes:1057 (1.0 KiB) TX bytes:1228 (1.1 KiB) 
cat /etc/resolv.conf 
nameserver 61.132.163.68 
nameserver 202.102.213.68 
route -n 
Kernel IP routing table 
Destination		Gateway		Genmask 		Flags	 Metric 	Ref 	Use 	Iface 
10.64.64.64 	0.0.0.0 	255.255.255.255 UH 		 0 			0 		0 		ppp0
0.0.0.0 		0.0.0.0 	0.0.0.0		 	U 		 0 			0 		0 		ppp0 
ping www.baidu.com 
PING www.a.shifen.com (115.239.211.112) 56(84) bytes of data. 
64 bytes from 115.239.211.112: icmp_seq=1 ttl=54 time=46.4 ms

关闭PPP呼叫:

pkill -f pppd

参考文献:

《Quectel_WCDMA&LTE_Linux_USB_Driver_User_Guide_V1.8.pdf》

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值