This chapter mainly introduces the use of LTE modules and driver transplantation, pppd dial-up software transplantation, LTE modules mainly use ZTE ME3630 , Wade S600 module, Longshang U9300C module, MeiG SLM730 , Quectel EC20 , Neoway N720 ; the basic AT commands of each module The same, only a few specific commands are different ( 4G signal query command, soft reset command).
1. Pppd porting
This chapter uses the ppp-2.4.4 version, and the development package is ppp-2.4.4.tar.gz ;
Need to modify the content:
1.1. Modify ppp-2.4.4\pppd\ipcp.c
The main reason for modifying this file is that when the dial-up software obtains the network parameter DNS , the tool will not be automatically set to the embedded system, and we need to operate it ourselves.
Add in the ipcp_up function :
char cmd1[100] = {0x00};
char cmd2[100] = {0x00};
-------
notice("local IP address %I", go->ouraddr);
notice("remote IP address %I", ho->hisaddr);
//写入配置脚本
if (go->dnsaddr[0])
{
notice("primary DNS address %I", go->dnsaddr[0]);
sprintf(cmd1, "echo nameserver %s > /mnt/mtd/resolv_wirless.conf",
ip_ntoa(go->dnsaddr[0]));
system(cmd1);
}
if (go->dnsaddr[1])
{
notice("secondary DNS address %I", go->dnsaddr[1]);
sprintf(cmd2, "echo nameserver %s >> /mnt/mtd/resolv_wirless.conf",
ip_ntoa(go->dnsaddr[1]));
system(cmd2);
}
//清除默认网关
cifdefaultroute(0,0,0);
//设置新的网关
SetGateway(ifname,ip_ntoa(ho->hisaddr));
The main reason for setting the gateway is that a wired / wireless automatic switching function is designed in this chapter. In the wired environment, the dial-up software exits (occasionally exits the dial-up connection due to poor signal), and when it needs to switch to wireless, it needs to be cleared . Default gateway, reset the wireless gateway.
Set the gateway function
static bool
SetGateway(char* _szInterface, char* _szGateway)
{
int s32Ret;
int s32Socketfd = socket(AF_INET, SOCK_DGRAM, 0);
if(s32Socketfd < 0)
{
printf("socket failed by %d", errno);
return -1;
}
struct rtentry rt;
memset(&rt, 0, sizeof(struct rtentry));
memset(&rt.rt_dst, 0, sizeof(rt.rt_dst));
rt.rt_dst.sa_family = AF_INET;
((struct sockaddr_in *)(&rt.rt_dst))->sin_addr.s_addr = inet_addr("0.0.0.0");
memset(&rt.rt_gateway, 0, sizeof(rt.rt_gateway));
rt.rt_gateway.sa_family = AF_INET;
((struct sockaddr_in *)(&rt.rt_gateway))->sin_addr.s_addr = inet_addr(_szGateway);
memset(&rt.rt_genmask, 0, sizeof(rt.rt_genmask));
rt.rt_genmask.sa_family = AF_INET;
((struct sockaddr_in *)(&rt.rt_genmask))->sin_addr.s_addr = 0L;
rt.rt_dev = _szInterface;
rt.rt_flags = RTF_GATEWAY;
s32Ret = ioctl(s32Socketfd, SIOCADDRT, &rt);
if(s32Ret < 0)
{
printf("ioctl SIOCADDRT failed by %d", errno);
close(s32Socketfd);
return -1;
}
close(s32Socketfd);
return 0;
}
The above function is to write the dns obtained by dialing into the system file cache, and the application needs to write the cache into the system's dns file ( linux system: /etc/resolv.conf , Android system: it needs to be set through the dnsproxy2 tool Tools will be introduced in another chapter );
1.2. Determine whether the dial-up to obtain DNS is correct
Because when the dial-up software performs dial-up, when the signal is very poor, the DNS obtained from the base station will be wrong, so it must be filtered when obtaining DNS .
Modify the main.c function:
add function
void checkdns __V((char *fmt, ...))
{
va_list pvar;
#if defined(__STDC__)
va_start(pvar, fmt);
#else
char *fmt;
va_start(pvar);
fmt = va_arg(pvar, char *);
#endif
int n;
char buf[1024];
n = vslprintf(buf, sizeof(buf), fmt, pvar);
va_end(pvar);
//IPCP ConfAck id=0x2 <addr 10.138.113.2> <ms-dns1 210.21.4.130> <ms-dns3 221.5.88.88>
/*
* 该段函数是为了防止拨号后获取到错误的DNS后还继续使用该
* 该参数,解决方案是当获取到配置应答指令后判断是否获取
* 到IP地址和对于的DNS,如果没获取到DNS则推出该拨号程序。
*/
char *pu8ConfAck;
char *pu8addr;
char *pu8msdns;
pu8ConfAck = strstr((char*) buf,"ConfAck");
if(pu8ConfAck != NULL)
if(strncmp(pu8ConfAck,"ConfAck",strlen("ConfAck")) == 0)
{
printf("---ConfAck[%s]\n",pu8ConfAck);
pu8addr = strstr((char*) pu8ConfAck,"addr");
if(pu8addr != NULL)
if(strncmp(pu8addr,"addr",strlen("addr")) == 0)
{
printf("---addr[%s]\n",pu8addr);
pu8msdns = strstr((char*) pu8addr,"ms-dns");
if(pu8msdns == NULL)
exit(1);
printf("---msdns[%s]\n",pu8msdns);
}
}
}
static void
get_input()
{
-----------------
dump_packet("rcvd", p, len);
//-------edw------------------------//
checkdns( "%P", p, len);
//------end-------------------------//
At this point, the basic modification of the basic dial-up software is completed.
Note : For android system porting, the Android sdk comes with the pppd tool ( under the external\ppp directory), the modification content is basically the same as the above, only the difference is in setting dns , and the Android system uses the command " setprop net.dnsx " to set DNS .
1.3. Compiler
Generate makefile ;
compile make CC=arm-hisiv100nptl-linux-gcc
Get pppd chat
1.4. Operator connection point
Unicom node wcdma
mobile node cnmet
telecom node evdo
content:
debug
nodetach
/dev/ttyUSB2
115200
usepeerdns
noauth
noipdefault
novj
novjccomp
noccp
defaultroute
ipcp-accept-local
ipcp-accept-remote
connect '/system/bin/chat -s -v -f /etc/ppp/peers/chat-wcdma-connect'
disconnect '/system/bin/chat -s -v -f/etc/ppp/peers/chat-disconnect'
The contents of the three node files are similar, only the connection point is different: chat-wcdma-connect .
Unicom connection point mode chat-wcdma-connect
content:
ABORT 'NO CARRIER'
ABORT 'ERROR'
ABORT 'NO DIALTONE'
ABORT 'BUSY'
ABORT 'NO ANSWER'
'' AT
OK ATZ
OK AT+CGDCONT=1,\"IP\",\"3gnet\",,0,0
OK AT+CFUN=1
OK ATDT*99#
CONNECT ''
Mobile connection point mode chat-cnmet-connect
ABORT 'NO CARRIER'
ABORT 'ERROR'
ABORT 'NO DIALTONE'
ABORT 'BUSY'
ABORT 'NO ANSWER'
'' AT
OK ATZ
OK AT+CGDCONT=1,\"IP\",\"cmnet\",,0,0
OK AT+CFUN=1
OK ATDT*98*1#
CONNECT ''
Telecom connection point mode chat-evdo-connect
ABORT 'NO CARRIER'
ABORT 'ERROR'
ABORT 'NO DIALTONE'
ABORT 'BUSY'
ABORT 'NO ANSWER'
'' AT
OK ATZ
OK AT+CGDCONT=1,\"IP\",\"ctlte\",,0,0
OK AT+CFUN=1
OK ATDT*99#
CONNECT ''
1.5. Start dialing
Unicom operator: pppd call wcdma&
Mobile operator: pppd call cnmet&
Telecom operator: pppd call evdo&
2. Driver transplantation
http://blog.csdn.net/skdkjzz/article/details/22206949
stty -F /dev/ttyUSB0 raw speed 9600 min 0 time 10
Use Longshang 4G module, modify the driver:
1. Add the USB serial driver and USB network card driver to the kernel . You can choose to program them directly into the kernel, or compile them into modules to be loaded when the kernel starts. In short, make sure that after the Linux kernel is started, these two drivers are running on in the kernel.
Usually, configuring the kernel is through the command make menuconfig , after executing the command:
l Add USB serial port driver:
device drivers-->
usb support-->
usb serial converter support-->
USB driver for GSM and CDMA modems
lAdd USB NIC driver
devices drivers-->
Network device support-->
usb Network Adapters-->
Mulil-purpose USB Networking Framework
* Note: If your kernel structure is inconsistent with the above, you may need to choose under other paths. In short, just make sure that option.c and its related parts ( USB serial port driver), cdc_ether.c and its related parts in the source file ( USB network card driver) just participate in the compilation
2. Add PPP components to the kernel
Usually, configuring the kernel is through the command make menuconfig , after executing the command:
devices drivers-->
Network device support-->
ppp support-->
ppp filtering
ppp support for async serial ports
ppp support for sync tty ports
ppp deflate compression
ppp BSD-compress compression
3. Add ZTE module-related information in the kernel driver source file : The USB network card driver can automatically recognize the ZTE module, so there is no need to add anything to the corresponding cdc_ether.c file. However, the USB serial port driver cannot be automatically identified, and the device information of the ZTE module must be added to the source file option.c .
File path: /kernel/drivers/usb/serial/option.c
l Add the VID and PID information of the USB port , see the blue part below. Here 0x0199 is the PID of the ME3860 module and ME3760_V2 module , and 0x1476 is the PID of the ME3620 module . If you are using other modules, just replace the PID value with the corresponding value.
static const struct usb_device_id option_ids[] = {
+{ USB_DEVICE(0x19d2, 0x1476) }, //add me3630
+{ USB_DEVICE(0x19d2, 0x0016) }, //add me3630
+{ USB_DEVICE(0x1c9e, 0x9b05) }, //add 8300
+{ USB_DEVICE(0x1c9e, 0x9b3c) }, //add 9300
+{ USB_DEVICE(0x05C6, 0x9025) }, //add S600
+{ USB_DEVICE(0x05C6, 0xf601) }, //add slm730
+{ USB_DEVICE(0x2c7c, 0x0125) }, //add yiyuan
+{ USB_DEVICE(0x05C6, 0x9008) }, //add n720……
}
The above ID can be entered into the system, through the command " lsusb ", to view the module ID .
lAdd blacklist information, the module information added above is only the VID and PID of the device , without any additional port information, which will cause the network card of the device to be loaded as a USB serial port. The following is a similar blacklist In the list method, in the option_probe function, add the port corresponding to the network card to the blacklist to prevent the USB network card from being loaded as a USB serial port.
For ME3860 and ME3760_V2 , the corresponding ports of the network card are 0 and 1 , and for the ME3620 , the corresponding ports of the network card are 3 and 4 . Please add the following code to the option_probe function
printk("idVendor=%x, idProduct=%x, bInterfaceNumber =%d\r\n",
serial->dev->descriptor.idVendor,
serial->dev->descriptor.idProduct,
serial->interface->cur_altsetting->desc. bInterfaceNumber);
if (serial->dev->descriptor.idVendor == 0x19d2 &&
serial->dev->descriptor.idProduct == 0x1476 &&
serial->interface->cur_altsetting->desc. bInterfaceNumber == 3)
return -ENODEV;
if (serial->dev->descriptor.idVendor == 0x19d2 &&
serial->dev->descriptor.idProduct == 0x1476 &&
serial->interface->cur_altsetting->desc. bInterfaceNumber == 4)
return -ENODEV;
if (serial->dev->descriptor.idVendor == 0x19d2 &&
serial->dev->descriptor.idProduct == 0x0199 &&
serial->interface->cur_altsetting->desc. bInterfaceNumber == 0)
return -ENODEV;
if (serial->dev->descriptor.idVendor == 0x19d2 &&
serial->dev->descriptor.idProduct == 0x0199 &&
serial->interface->cur_altsetting->desc. bInterfaceNumber == 1)
return -ENODEV;
if (serial->dev->descriptor.idVendor == 0x1c9e&& //龙尚
serial->dev->descriptor.idProduct == 0x9b05&&
serial->interface->cur_altsetting->desc. bInterfaceNumber == 3)
return -ENODEV;
* Note: The printk on the first line is printed for the convenience of debugging. Although it has no actual effect, it is best to bring it. The following if statements respectively determine the port numbers that need to be added to the blacklist. If you are using modules other than ME3860 , ME3760_V2 and ME3620 , the judgment conditions in the above if statements should be modified accordingly.
If you need to load other modules after loading the driver, you can load them with the command:
echo "19d2 1476" >/sys/bus/usb-serial/drivers/option1/new_id
Note: The kernel patch will be obtained in the HiSilicon 3518C 4G module porting file;