基于嵌入式Linux的3G技术的应用和研究

时间:2022-10-07 02:45:39

基于嵌入式Linux的3G技术的应用和研究

摘要:该文介绍了在嵌入式linux的平台下,如何通过3g USB Dongle来进行网络连接。介绍了目前主流3G USB Dongle的工作模式,分析了linux 的USB热插拔在用户空间的处理流程,并引入一个轻量级的热插拔事件处理框架,最后介绍3G USB Dongle通过PPP套件的拨号处理流程。

关键词:嵌入式;linux;3G ;USB

中图分类号:TP393文献标识码:A文章编号:1009-3044(2010)20-5655-03

第三代移动通信技术(3rd-generation,3G),是指支持高速数据传输的蜂窝移动通讯技术。3G服务能够同时传送声音(通话)及数据信息(电子邮件、即时通信等)。3G的代表特征是提供高速数据业务,速率一般在几百kbps以上。3G的标志性业务包括:无线宽带上网、手机电视以及视频通话等。目前在中国运营的共有三种制式的3G网络:中国移动TD-SCDMA网络,中国联通WCDMA网络,中国电信CDMA2000网络。Linux是目前嵌入操作系统的一个极有吸引力的选择。它支持广泛的计算机硬件,除了PC平台的x86系列cpu外,嵌入式平台常见的ARM 和MIPS核心的cpu都能得到很好的支持。Linux提供了完整内存保护,是一个多任务,多进程的操作系统。它不仅是免费的,其程序源码全部公开,任何人可以修改并在GPL下发行,这样开发人员可以对操作系统进行定制。其强大的语言编译器GCC等也可以很容易得到,不但成熟完善、而且使用方便。3G技术的引入使得其有了更大的用武之地。各个公司正在结合这两个技术开发很多新的应用为人们提供更好的服务,目前的应用主要有3G路由器,3G视频服务器,3G工业数据采集系统,3G无线网络视频监控,3G媒体广告等。3G连接可采用通用的USB无线上网模块(本文中也称作3G USB Dongle),只要嵌入式产品具有linux操作系统 和USB HOST接口就立即可以使用。

1 配置内核

在编译内核时进入“Device Drivers”选项,再进入“USB support”子菜单,把以下的条目选中编译进内核,或者把这些条目编译成模块形式。

[*] Support for Host-side USB

[*] USB device filesystem

[*] EHCI HCD (USB 2.0) support

[*] OHCI HCD support

[*] USB Mass Storage support

USB Serial Converter support-->

[*] USB driver for GSM and CDMA modems

再进入“SCSI device support”子菜单,把以下的条目选中编译进内核,或者把这些条目编译成模块形式。

[*] SCSI device support

[*] SCSI disk support

[*] Probe all LUNs on each SCSI device

现对这些选项介绍做些说明。目前有两种主控制器接口,Compaq的OHCI (Open HCI),Intel的UHCI (Universal HCI)和EHCI (Enhanced HCI)。OHCI/UHCI是针对USB 1.1的工业标准,而EHCI是针对USB 2.0的。启用EHCI和OHCI确保所有接口规范的USB设备都能够得到支持。启用USB device filesystem选项可以让我们在/porc/bus/usb中查看USB设备。USB driver for GSM and CDMA modems又名option,是USB 3G dongle的核心驱动,几乎现在市面上所有USB 3G dongle都通过这个驱动来支持,无论它是哪个网络制式,最终都是通过USB Serial的option驱动来和内核通信。USB Mass Storage 和SCSI device support是为了支持一些Dongle上自带的USB Mass-storage设备,Probe all LUNs on each SCSI device是为了支持Dongle上读卡器。

当你碰到一个内核并不支持的新设备后,只需要把该Dongle 3G接口的 Vendor ID 和Product ID 添加到linux-2.6.x/drivers/usb/serial/option.c 中的option_ids[]数组即可。以华为K3765举例,其3G 接口的Vendor ID 为0x12D1 ,Product ID为0x1465,

#define HUAWEI_VENDOR_ID0x12D1/* add to ID table */

static struct usb_device_id option_ids[] = {

……

{USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID,0x1465,0xff,0xff,0xff)},

……};

重新编译内核后,内核部分的配置工作就做完了,我们还需要通过下面的命令来创建设备文件给用户空间的拨号程序来访问。

mknod /dev/ttyUSB0 c 188 0

……

mknod /dev/ttyUSB3 c 188 3

最后在系统初始化的脚本中,我们还必须挂载usb虚拟文件系统:

mount -t usbfs usbfs /proc/bus/usb/

2 3G USB Dongle的工作模式研究

一些新的USB 3G Dongle 都板载了Windows 的驱动程序,因此不需要额外的CD来放驱动程序。当Dongle第一次插上的时候,它会被当做一个Flash 储存设备,然后windows的autorun机制会自动执行安装驱动程序。在驱动程序安装之后,每次插入Dongle时候,驱动会自动在内部切换模式,由储存模式变成USB Modem模式。然而这些驱动都只工作在windows下,厂商并没有提供linux下的驱动或者相关文档。幸运的是,一些热忱的hacker利用USB嗅探工具通过分析windows驱动的行为和动作,然后再linux下复制这些行为和动作来做切换动作。

usb_modeswitch是linux下面对USB设备的工作模式进行转换一种工具,它可以把3G USB Dongle从储存设备模式切换到modem模式。它只需要libusb的支持,把这个程序移植到嵌入式平台是个很容易的事。我们只需要提供一个配置文件来给usb_modeswitch。配置文件应该至少包含以下的一些参数:DefaultVendor和DefaultProduct是3G USB Dongle插入时没有做模式切换前的USB ID,这个ID 我们能够在/proc/bus/usb/devices中找到。程序需要这两个参数来做匹配。TargetVendor和TargetProduct是3G USB Dongle在成功切换到modem模式的USB ID.程序可以通过这两个参数来判断是否切换成功。最重要的参数是MessageContent,它是一个16进制的字符串,这个字符串会发送给3G USB Dongle,让其切换模式。

从上文usb_modeswitch的配置文件的介绍,我们差不多能够了解到usb_modeswitch的工作流程:先匹配储存模式的USB ID,如果匹配上,向设备发送MessageContent消息来切换模式,然后通过检测modem模式的USB ID来判断模式切换是否成功。usb_modeswitch已经自带目前市面上常见的3G USB Dongle的配置文件。如果碰到一个新设备,我们可以在windows下使用sniffusb程序来获取参数,安装驱动前,我们能获得DefaultVendor和DefaultProduct参数;安装驱动后,我们能获得TargetVendor和TargetProduct参数;sniffusb程序来监听所有的主机和USB设备之间的通讯信息,然后找出模式切换的MessageContent消息。

3 USB热插拔事件检测

上面讨论了usb_modeswitch的原理之后,现在来讨论usb_modeswitch使用的时机。usb_modeswitch应该在usb设备插入的时候,检测到Vendor ID 和Product ID后,用这两者作为命令行参数来调用usb_modeswitch。udev可以帮我们实现USB 热插拔并自动调用usb_modeswitch的功能,但是在一些内存和闪存紧缺的解决方案中,并没有提供udev工具。笔者在这里介绍一种轻量级的linux热插拔方案。

简单的linux内核的USB的热插拔通知可以通过调用/proc/sys/kernel/hotplug中注册的程序来实现,它通常是/sbin/hotplug。 当有USB设备插上时,内核的会把该设备的一些信息填入字符串数组,然后把这个字符串数组作为/sbin/hotplug进程的环境变量并开始执行这个进程。而sysfs的出现会报告更多的内核hotplug事件给/sbin/hotplug,只要实现了kobject模型的设备驱动都会产生该事件,/sbin/hotplug开始变得复杂,又由于/sbin/hotplug都是bash所写,因此变得没有效率。

内核在2.6.15之后,/proc/sys/kernel/hotplug会成空的,因为内核通知用户空间还用了netlink接口,而且最新的udev也采用了netlink接口去写,废弃了/sbin/hotplug。我们可以直接通过netlink监听设备事件,然后过滤出我们关心的3G USB Dongle 热插拔事件并作出相应的处理,下面是程序的初始化和主循环框架:

/* netlink socket的创建和绑定*/

int netlinkfd, fdmax;

fd_set fdset;

struct sockaddr_nl snl;

memset( &snl, 0, sizeof(struct sockaddr_nl) );

snl.nl_family = AF_NETLINK;

snl.nl_pid = getpid();

snl.nl_groups = 1;

netlinkfd = socket( PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT );

bind( netlinkfd, (struct sockaddr *) &snl, sizeof(struct sockaddr_nl) );

/* netlink 数据侦听检测*/

while (1){

tv.tv_sec = 0;

tv.tv_usec = 1000 * 50;

FD_ZERO ( &fdset );

FD_SET ( netlinkfd, &fdset );

retval = select( fdmax, &fdset, NULL, NULL, &tv );

if ( retval >0 ){

if ( FD_ISSET( netlinkfd, &fdset ) ){

recv( netlinkfd, buff, sizeof(buff)-1, 0 );

/* 处理netlink 数据 */}}}

通过上面的程序框架,我们能够获得所有的内核热插拔的事件通知,我们还需要做的就是把netlink传到用户空间的数据分析出来,然后过滤出我们需要的数据。前文提到过内核把该设备的一些信息填入字符串数组,然后把这个字符串数组作为的环境变量传递给/sbin/hotplug,内核还会把这个字符串数组通过netlink结果传给用户空间的程序,上面的recv函数收到的数据就是这个字符串数组,因而很容易被分析出来。同/sbin/hotplug的方案相比,netlink的方案不用反复创建新进程,效率提高的很多,一个单线程就可以收到所有的热插拔通知消息,除了去检查是否调用usb_modeswitch来切换3G USB Dongle的工作模式,我们还可以利用这个框架来做USB Mass Storage自动挂载等。

我们目前只需要注意的就是ADD事件,当一个USBADD 设备的通知收到后,我们结合上下文得到这个新添加设备的Vendor ID 和Product ID,如果他们正好匹配华为K3765储存接口的Vendor ID0x12D1 和Product ID 0x1465,那我们就直接调用usb_modeswitch来做工作模式切换:

usb_modeswitch -c /etc/usb/usb_modeswitch.d/12D1:1465

4 使用ppp套件拨号

虽然WCDMA,TD-SCDMA,CDMA2000,这三种网络制式并不兼容,但是它们的USB Dongle的linux 驱动接口都是一样的,用户空间的控制程序也只是配置上的不同。在这里我们还是以华为K3765来举例,它支持WCDMA的网络。通过对华为K3765拨号流程介绍,读者可以举一反三的了解到3G USB Dongle的拨号流程,并很容易从网络上找到TD-SCDMA,CDMA2000,USB Dongle的配置数据。

在前文中我们提到如何去创建设备驱动文件ttyUSB0,接下来我们将探讨如何使用ppp套件(只使用了chat和pppd)。虽然华为K3765提供了4个ttyUSB接口,但是我们只用使用第一个就可以了。chat命令用来和modem通过一系列AT命令集交互,当底层拨号连接成功后在通过pppd在ttyUSB0设备上进行数据收发。

ppp的配置文件如下(/etc/ppp/peer/wcdma):

nodetach

lock

/dev/ttyUSB0

modem

115200

user "card"

password "card"

crtscts

usepeerdns

noauth

noipdefault

novj

novjccomp

noccp

defaultroute

connect 'chat -s -v -f wcdma-connect'

disconnect 'chat -s -v -f wcdma-disconnect'

wcdma-connect脚本如下(/etc/ppp/ wcdma-connect):

TIMEOUT 5

ABORT 'NO CARRIER'

ABORT 'ERROR'

ABORT 'NO DIALTONE'

ABORT 'BUSY'

ABORT 'NO ANSWER'

'' \rAT

OK \rATZ

OK \rAT+CGDCONT=1,"IP","3gnet",,0,0

OK-AT-OK ATDT*99#

CONNECT \d\c

wcdma-disconnect脚本如下(/etc/ppp/wcdma-disconnect):

ABORT "BUSY"

ABORT "ERROR"

ABORT "NO DIALTONE"

'' "\K"

'' "+++ATH"

SAY "\ndisconnected\n"

最后我们只用通过下面的命令来进行拨号和连接:pppd call wcdma。

5 结束语

3G的出现使得移动的无线宽带成为可能,借助无线宽带连接,嵌入式的linux有了更大的应用空间。通过把这两种技术结合,不但可以改进现有的一些网络应用,比如我们可以把传统的有线视频监控改造成3G,不但省去了布线的麻烦,而且更容易部署。有了3G,嵌入式linux能开展无限的应用。

参考文献:

[1] 第三代行动通讯[EB/OL]./zh-hans/3G.

[2] Carla Schroder.Linux Networking Cookbook:中文版.[M].南京:东南大学出版社.2009.

[3] Jonathan Corbet.Linux设备驱动程序[M].3版.北京:中国电力出版社.2006.

[4] usb_modeswitch[EB/OL].www.draisberghof.de/usb_modeswitch/.

上一篇:浅谈企业信息系统的安全 下一篇:一种基于独立分量分析的数字水印算法