第8章 USB-4G/LTE移植 -第4节 USB-4G移植(移远EC20开发-Gobi拨号)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013162035/article/details/81841002

开发环境
主机:ubuntu12.04
开发板内核版本:linux-2.6.35
【注】EC20支持PPP拨号,Gobi拨号和QMI拨号,笔者使用的是Gobi拨号,关于另外两种拨号请参考官方文档,后文的附件链接中已经给出了参考文档。

3.1 USB Serial驱动

当模块连接到USB串行驱动时,驱动程序将在目录/dev中创建设备文件,
ttyUSB0/ttyUSB1/ttyUSB2…
接下来就是讲解如何移植USB Serial。

3.1.1增加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

这里其实只需要{ USB_DEVICE(0x05C6, 0x9215) }, /* Quectel EC20 */ 这一项,其他是无关紧要的,可以不放进去。option_ids[]就是一usb serial的设备pid,vid表。
【注】还有另外一种方式查看PID和VID,将EC20和微控器连接,就可以进入系统查看USB设备。

3.1.2添加零包处理

根据USB协议的要求,客户需要添加处理零数据包的机制。
For Linux Kernel Version newer than 2.6.34:
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;
}

这里写图片描述
For Linux kernel version lower than 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;
}

3.1.3增加休眠后唤醒接口

当MCU进入暂停/休眠模式时,一些USB主机控制器/USB集线器将失去电源或重新设置,并且在MCU退出暂停/休眠模式后,它们不能恢复USB设备。请添加以下语句以启用重新设置恢复过程。
For Linux kernel version higher than 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
};

For Linux kernel version lower than 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,
};

这里写图片描述

3.1.4 Enlarge Bulk out URBs

For Linux kernel version lower than 2.6.29, bulk out URBs need to be enlarged to get faster uplink speed.
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

3.1.5使用 GobiNet or QMI WWAN

如果客户使用ucxx/ec2x/egxx/EP06/EM06/BG96/AG35,并要求GobiNet或QMI WWAN,请添加以下语句,以防止这些模块接口4被用作USB串行设备。
For Linux Kernel Version newer than 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;
}

这里写图片描述
For Linux kernel version lower than 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
……

3.1.6修改内核配置

第一步:进入内核,并进入内核配置环境
$make menuconfig
第二步:添加USB 串口 GSM 和 CDMA 驱动选项。

[*] Device Drivers →
    [*] USB Support →
        [*] USB Serial Converter support →
            [*] USB driver for GSM and CDMA modems

这里写图片描述

3.1.7编译

以上操作完成后就是编译内核源码了。
$ make uImage -j4
将内核烧写进入板子中,会看到以下信息表示有USB设备了。
这里写图片描述
可以在dev目录下查看设备。
这里写图片描述

3.2 GobiNet移植

3.2.1修改内核配置

第一步:进入内核,并进入内核配置环境

$make menuconfig

第二步:启用USB网络支持

[*] Device Drivers →
    [*]Network device support →
            [*]usb Network Adapters →
 

这里写图片描述
【注】笔者是直接编译进内核的,也可编译后成模块动态加载。

3.2.2添加驱动代码

当使用Gobinet驱动移远模块时,Gobinet将会创建一个网络设备(ethX)和一个QMI channel(qcqmiX),将驱动源码放到[KERNEL]/drivers/net/usb/ (or [KERNEL]/drivers/usb/net/ if the kernel version is lower than2.6.22).。如果是把Gobinet编译到内核中,可以忽略。GoniNet源码中的Makefile,直接将源码中的.c和.h文件拷贝到上述目录中。网络设备用于网络传输 QMI channel要用于QMI 的信息交互。然后添加以下声明到file [KERNEL]/drivers/net/usb/Makefile (or [KERNEL]/drivers/usb/net/Makefile if the kernel version is lower than 2.6.22)。

obj-y += GobiNet.o
GobiNet-objs := GobiUSBNet.o QMIDevice.o QMI.o

【注】源码在后文的附件中,请下载。

3.2.3编译

以上操作完成后就是编译内核源码了。
$ make uImage -j4

3.2.4测试

将编译后的Image在板子上跑起来可以看到启动信息有qcqmil。
这里写图片描述
另外在dev下多了一个qcqmil。
这里写图片描述
说明GobiNet驱动已经生效了。

3.3拨号上网

拨号程序仍然使用移远提供的quectel-CM,这是一个4g连接管理程序,这里没什么说的,直接下载源码交叉编译后得到可执行bin“quectel-CM”,把这个bin放到板卡上启动后上述USB和Gobi没有问题的情况下直接执行该bin就可以
【注】移动式[cmnet],电信是[ctnet]。

$ ./quectel-CM -s cmnet &

【注意】笔者使用的移动卡。
拨号成功会分配IP,接下来就是ping一下看是否可以联网。

$ping www.baidu.com

【注意】这里需要UDHCPC ,检测你的busybox是否有这个东西,如果不存在,你需要重新移植busybox,启用CONFIG_UDHCPC选项。还需要配置一个配置文件,注意检查。
可以在开发板中输入busybox中查看,笔者的文件系统有,所以就不需要配置了。

【附件】
点击进入

Gobinet/QMI-WWAN/ppp拨号区别

1.Gobinet拨号
GOBI 高通Gobi无线宽带芯片技术,只需一个模块即可支持多种移动宽带网络和众多移动运营商。高通公司称全新的芯片将基于Gobi 4G LTE无线基带、MDM9615和MDM9215。这种技术可以在FDD和TDD网络下进行LTE连接,同时支持HSPA+和EV-DO网络、2G/3G网络。这意味着用户可以在本地使用高速4G LTE网络,在其他地方使用3G网络。Gobi平台在MDM芯片组的基础上还提供了软件增强层,这样可以使用不同技术下的无线连接更简单。

2.QMI-WWAN协议拨号
QMI: Qualcom Message Interface
MSM: Mobile station mode
AP: Application Procesor

高通平台目前都是非对称多核心,最主要的是AP和Modem。
两个处理器怎么进行通信呢,我们把AP和Modem当作两个主机,问题就变得了很简单,TCP/IP协议不是一种非常成功的进程间跨主机通信方式。高通没有采用这种方式,但是借鉴了TCP/IP的框架设计。
Qualcomm MSM Interface,作用用于AP和BP侧的交互,通俗说法就是让设备终端TE(可以是手机,PDA,计算机)
对高通BP侧的AMSS系统进行操作,如调用函数,读取数据,设置其中的NV项等。
参考:http://blog.csdn.net/u012439416/article/category/7004974

3.ppp协议拨号:点对点协议
PPP(点到点协议)在拨号过程中用于MS和PC间数据交互、协商。在拨号流程的初期首先开启的就是PC和MS直接的PPP过程,在拨号成功后,还需要依靠PPP协议对IP包进行封装传输数据。
官网源码:https://ppp.samba.org

猜你喜欢

转载自blog.csdn.net/u013162035/article/details/81841002