Linux下使用电信3G CDMA上网卡
第一个任务是在小板子上驱动电信的3G上网卡,新事物,在PC上先得跑通。随卡带的驱动是不可能有linux版的,所以接下来就有两个办法,一个是google一下有没有这个卡的linux开源版驱动,太新,没有;另一个就是看看kernel是否本身可以支持。后来得到确认,修改kernel的usb-serial部分是可以驱动的。
这是个CDMA的卡,所以在drivers/usb/serial下搜一下有没有和cdma modem有关的东西,还真有,一个叫option.c的文件。实际上这就是usb cdma gsm modem的通用驱动,却用了这么一个大众化的名字,直接把这个卡的两个ID加到了这个文件里。重编译kernel,重启机器。再插卡,就出现了/dev/ttyUSB0-2三个modem。
接下来就简单了,wvdialconf自动配置,然后再wvdial拨号。
$ sudo wvdialconf
$ sudo vi /etc/wvdial.conf
$ sudo wvdial
sudo是必要的,因为要自动修改一些/etc下的配置文件,而且运行pppd也需要高权限。很顺利的就拨通了。wvdial和rp-pppoe都是pppd的前端程序。只是分工不同,wvdial负责通过modem拨号连接互联网,rp-pppoe负责通过网线拨号连接。核心其实都是pppd,只是pppd的配置忒复杂,才出现了这么很多以它为后段的前端。
那么接下来就是往小板子上弄了。先修改kernel重编译,很顺利(只添一行,不顺利才怪)。然后把卡插到板子上看看。没反应,嵌入式系统一般不会有设备自动添加这样的东西的。。所以只能手动添加设备文件。
$ mknod /dev/ttyUSB0 c 188 0
$ mknod /dev/ttyUSB1 c 188 1
$ mknod /dev/ttyUSB2 c 188 2
测一下这几个设备是否真的存在,很简单的命令。
$ echo ATZ >/dev/ttyUSB0
$ echo ATZ >/dev/ttyUSB1
$ echo ATZ >/dev/ttyUSB2
如果没有任何错误输出就对了,如果提示No such device,那就是kernel没搞对。
接下来就该移植那堆拨号软件了,首先是pppd(ppp-2.x.x.tar.gz),以前弄过,这个包的configure是个假configure脚本,只负责复制了一下Makefile。所以需要手工修改Makefile,不用编译所有模块,只需要编译pppd目录和chat目录即可。基本上是在Makefile里添加CC的定义就ok了。
顺利编出pppd后,开始移植wvdial,就是这个东西让我卡了壳——看到C++写的就头大。不仅仅如此,并不复杂的wvdial依赖于一个相当复杂的C++类库wvstreams。wvstreams是个automake的工程,但即使如此也是需要改一堆东西,屏蔽几十行代码或帮忙实现点空函数才能编译通过。这样弄过去估计也不太可用。事实证明,wvdial虽然可以运行,却对几个modem设备视而不见。
为了证明modem是ok的,我专门写了一个串口测试程序来测试modem。通过发送ATZ返回OK,ATI0返回一堆设备信息,ATDT#888返回CONNECT,可以确定设备完好,没有正常运行的是wvdial。放弃wvdial,改用ppp-2.x.x自带的拨号脚本,没有成功,在PC都没有成功,何况小板子上。
以前在搞pppoe的时候,pppd可以正常工作,应该可以说明pppd是ok的。那么关键就是怎么使用pppd来拨号的问题。自己感觉用脚本来做是个正途,参考了一些,都不好用。突然想到,既然wvdial可以跑,我抄它的pppd参数不就成了。wvdial是自己初始化modem,我用chat来初始化modem。以下就是我的拨号脚本:
#! /bin/sh
MODEM=$1
SPEED=$2
TELNUMBER=$3
USER=$4
PWD=$5
if [ -z $MODEM ];
then
MODEM=/dev/ttyUSB1
fi
if [ -z $SPEED ];
then
SPEED=115200
fi
if [ -z $TELNUMBER ];
then
TELNUMBER=#777
fi
if [ -z $USER ];
then
USER=CARD
fi
if [ -z $PWD ];
then
PWD=CARD
fi
CHATFILE=/etc/ppp/mychat
OPTFILE=/etc/ppp/options
PAPFILE=/etc/ppp/pap-secrets
#make chat script /etc/ppp/mychat
echo ABORT \"BUSY\" >$CHATFILE
echo ABORT \"NO CARRIER\" >>$CHATFILE
echo ABORT \"NO DIALTONE\" >>$CHATFILE
echo TIMEOUT 30 >>$CHATFILE
echo \"\" >>$CHATFILE
echo ATZ OK >>$CHATFILE
echo \"ATQ0 V1 E1 S0=0 \&C1 \&D2 +FCLASS=0\" OK >>$CHATFILE
echo \"ATDT$TELNUMBER\" CONNECT >>$CHATFILE
chmod +x $CHATFILE
#update options file
mv $OPTFILE $OPTFILE.bak
echo lock >$OPTFILE
echo modem >>$OPTFILE
echo crtscts >>$OPTFILE
echo defaultroute >>$OPTFILE
echo usehostname >>$OPTFILE
echo \-detach >>$OPTFILE
echo user $USER >>$OPTFILE
echo noipdefault >>$OPTFILE
#echo remotename ppp0 >>$OPTFILE
echo debug >>$OPTFILE
echo idle 0 >>$OPTFILE
echo connect \"chat -v -s -f $CHATFILE\" >>$OPTFILE
#echo demand >>$OPTFILE
echo usepeerdns >>$OPTFILE
#echo persist >>$OPTFILE
echo kdebug 1 >>$OPTFILE
echo $SPEED >>$OPTFILE
#update pap-secrets
mv $PAPFILE $PAPFILE.bak
cat $PAPFILE | grep -v "^${USER}" > $PAPFILE.new
echo "${USER} * ${PWD}" >> $PAPFILE.new
mv $PAPFILE.new $PAPFILE
#dialup
killall -9 pppd
killall -9 chat
mkdir -p /var/lock
mkdir -p /var/log
pppd $MODEM $SPEED
断开直接kill pppd就可以了,不过注意是kill -15,发送SIGTERM信号。
$ killall -15 pppd
目前仍然存在的问题是断开之后无法再次拨号,必须拔掉卡重插一下才行。