基于Jetson Xavier NX 移植移远EG25G 4G模块
先敲一下黑板,使劲敲
- 大家一定先试一下直接插上4G模块后,linux能否读出来,就是右上角的wifi设置那里面出不出现移动网络信息,如下图
- 如果出来的话直接添加新的网络(没有出来也可能是因为SIM卡插反了,缺角朝外,金属片向上试试)
- 一路next就可以,注意select your plan那里选internet
- 添加之后连接移动网络,密码随便输0000、1234啥的都可以,如果可以连上网,那后面也就不用看了,别问我怎么知道的…
如果你的设备型号和我不一致,也无法通过上面步骤连接上移动网络,那么可以结合我下面贴出的RMBR老哥的文章以及我这边的补充尝试一下。
写在前面
用了好久的CSDN, 这是我第一次写文章,想要作为自己这一次操作的记录,同时如果可以帮助到各位那就再好不过。同时第一次使用CSDN编辑器书写,操作不是十分熟悉,格式可能不够标准,请大家见谅。
笔者个人之前没有任何驱动移植相关经验,这次能够实现上述功能非常感谢各位CSDN的大佬们毫不吝啬地分享自己的操作步骤和经验,特别要感谢一位名字叫RMBR的大哥,百忙之中给了我很多帮助,这里再次说一声感谢,同时贴上我参考的他的文章地址给大家,大家可以作为参考。
移植EC20F 4G模块驱动基于Jetson-xavier
感谢毫不吝啬地分享知识的你们!
正文
实验室最近的项目需要用到Xavier Nx的4G功能,需要外接4G模块来实现,这里分享一下如何让Xavier通过4G模块实现拨号上网。
基本步骤大家建议大家先看一下我前面提到的文章,如果是相关从业人员应该照着他的步骤去做应该不会出现什么问题,我这里仅仅是希望从一个小白的视角详细记录一下操作的过程。
准备工作
硬件
- Jetson Xavier NX ;
- 移远EG25-G无线通信模块 ;
- 天线;
- Sim卡;
附一张全家福:
工具
-
Xavier官方kernel
-
交叉编译工具
http://releases.linaro.org/components/toolchain/binaries/7.3-2018.05/aarch64-linux-gnu/
-
EC20&EC25官方驱动
这个购买模块时商家会给你,或者到移远官网的设备界面下载 -
参考的RMBR大哥添加的额外依赖 : qmi_wwan_q.c
https://download.csdn.net/download/qq_39703165/15714727?spm=1001.2014.3001.5503 -
busybox源代码
https://busybox.net/downloads/?C=M;O=D
这个选择最新的压缩包下载就可以
使劲敲黑板
所有前面的这些工具源码啥的一定不要放到根目录下,直接在home目录下面操作就可以,不然可能因为权限出很多问题,别问我怎么知道的…
正式开始
修改内核源码文件 kernel-4.9/drivers/usb/serial/option.c
- 在 option_ids[] 中添加VID 和 PID USB_DEVICE(0x2c7c, 0x0125)
这里给出的是EG25的ID值,如设备不同请自行修改为相应的值
需要添加的代码部分我使用******标记
static const struct usb_device_id option_ids[] = {
******
{ USB_DEVICE(0x2c7c, 0x0125)},/*quectel EC20: add VID and PID*/
******
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) },
- 在 option_probe()中添加如下代码段:
注意是原本就有内容的那个option_probe()
需要添加的代码部分我使用******标记
static int option_probe(struct usb_serial *serial,
const struct usb_device_id *id)
{
struct usb_interface_descriptor *iface_desc =
&serial->interface->cur_altsetting->desc;
struct usb_device_descriptor *dev_desc = &serial->dev->descriptor;
unsigned long device_flags = id->driver_info;
/* Never bind to the CD-Rom emulation interface */
if (iface_desc->bInterfaceClass == 0x08)
return -ENODEV;
/*
* Don't bind reserved interfaces (like network ones) which often have
* the same class/subclass/protocol as the serial interfaces. Look at
* the Windows driver .INF files for reserved interface numbers.
*/
if (device_flags & RSVD(iface_desc->bInterfaceNumber))
return -ENODEV;
/*
* Don't bind network interface on Samsung GT-B3730, it is handled by
* a separate module.
*/
if (dev_desc->idVendor == cpu_to_le16(SAMSUNG_VENDOR_ID) &&
dev_desc->idProduct == cpu_to_le16(SAMSUNG_PRODUCT_GT_B3730) &&
iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
return -ENODEV;
******
#if 0
/*quectel EC20: use GobiNet or QMI WWAN*/
if(serial->dev->descriptor.idVendor == cpu_to_le16(0x2c7c) &&
serial->dev->descriptor.idProduct == cpu_to_le16(0x0125) &&
serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4)
return -ENODEV;
#endif
/*quectel modules's interface 4 can be used as USB network device*/
if(serial->dev->descriptor.idVendor == cpu_to_le16(0x2c7c)){
//some interfaces can be used as USB Network device (ecm, rndis, mbim)
if(serial->interface->cur_altsetting->desc.bInterfaceClass != 0xff){
return -ENODEV;
}
//interface 4 can be used as usb network device(qmi)
else if(serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4)
return -ENODEV;
}
/*quectel EC20: Enable USB Auto suspend*/
if(serial->dev->descriptor.idVendor == cpu_to_le16(0x2c7c)){
device_init_wakeup(&serial->dev->dev, 1);//enable usb remote wakeup
pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000);//auto suspend
usb_enable_autosuspend(serial->dev);
}
******
/* Store the device flags so we can use them during attach. */
usb_set_serial_data(serial, (void *)device_flags);
return 0;
}
- 在option_1port_device中添加如下代码段:
需要添加的代码部分我使用******标记
static struct usb_serial_driver option_1port_device = {
.driver = {
.owner = THIS_MODULE,
.name = "option1",
},
.description = "GSM modem (1-port)",
.id_table = option_ids,
.num_ports = 1,
.probe = option_probe,
.open = usb_wwan_open,
.close = usb_wwan_close,
.dtr_rts = usb_wwan_dtr_rts,
.write = usb_wwan_write,
.write_room = usb_wwan_write_room,
.chars_in_buffer = usb_wwan_chars_in_buffer,
.tiocmget = usb_wwan_tiocmget,
.tiocmset = usb_wwan_tiocmset,
.ioctl = usb_wwan_ioctl,
.attach = option_attach,
.release = option_release,
.port_probe = usb_wwan_port_probe,
.port_remove = usb_wwan_port_remove,
.read_int_callback = option_instat_callback,
#ifdef CONFIG_PM
.suspend = usb_wwan_suspend,
.resume = usb_wwan_resume,
******
.reset_resume = usb_wwan_resume, /*quectel EC20: add reset resume*/
******
#endif
};
修改文件kernel-4.9/drivers/usb/serial/usb_wwan.c
- 在 usb_wwan_setup_urb中添加如下代码段:
需要添加的代码部分我使用******标记
static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
int endpoint,
int dir, void *ctx, char *buf, int len,
void (*callback) (struct urb *))
{
struct usb_serial *serial = port->serial;
struct urb *urb;
urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
if (!urb)
return NULL;
usb_fill_bulk_urb(urb, serial->dev,
usb_sndbulkpipe(serial->dev, endpoint) | dir,
buf, len, callback, ctx);
******
/*quectel EC20: add the zero packet mechanism*/
if(dir == USB_DIR_OUT){
struct usb_device_descriptor *desc = &serial->dev->descriptor;
if(desc->idVendor == cpu_to_le16(0x2c7c))
urb->transfer_flags |= URB_ZERO_PACKET;
}
******
return urb;
}
复制GobiNet文件夹下的文件到 kernel-4.9/drivers//net/usb目录下
GobiNet中除Readme外的所有文件均需放到/net/usb目录下,并且注意要将前面提到的qmi_wwan_q.c也放进去
修改kernel-4.9/drivers//net/usb目录下的Makefile文件
需要添加的代码部分我使用******标记
obj-$(CONFIG_USB_VL600) += lg-vl600.o
******
obj-$(CONFIG_USB_NET_QMI_WWAN) += qmi_wwan_q.o
******
obj-$(CONFIG_USB_NET_QMI_WWAN) += qmi_wwan.o
obj-$(CONFIG_USB_NET_CDC_MBIM) += cdc_mbim.o
obj-$(CONFIG_USB_NET_CH9200) += ch9200.o
******
obj-m += GobiNet.o
GobiNet-objs := GobiUSBNet.o QMIDevice.o QMI.o
******
修改 arch/arm64/configs/tegra_defconfig 文件
这部分不清楚是不是可以直接把下面的内容完全复制到文件最后,我的做法是用查找功能一个一个查找,不同的话修改,没有的话补上
CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_OPTION=m
CONFIG_USB_SERIAL_QUALCOMM=m
CONFIG_USB_SERIAL_WWAN=m
CONFIG_PPP=y
CONFIG_PPP_BSDCOMP=y
CONFIG_PPP_DEFLATE=y
CONFIG_PPP_FILTER=y
CONFIG_PPP_MPPE=y
CONFIG_PPPOLAC=y
CONFIG_PPPOPNS=y
CONFIG_PPP_ASYNC=y
CONFIG_PPP_SYNC_TTY=y
CONFIG_USB_USBNET=y
CONFIG_USB_NET_QMI_WWAN=m
————————————————
版权声明:本文为CSDN博主「RMBR」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/rendog/article/details/103825555
编译内核
- 在你的kernel-4.9目录下编译
cd /kernel-4.3/kernel/kernel-4.9
- 设置输出文件地址
TEGRA_KERNEL_OUT=~/kernelout43
- 设置交叉编译工具地址(地址改成你自己的目录地址)
export CROSS_COMPILE=~/tools/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
- 编译
make ARCH=arm64 O=$TEGRA_KERNEL_OUT tegra_defconfig
make ARCH=arm64 O=$TEGRA_KERNEL_OUT -j6
这里原文的作者说不使用sudo也可以,但我这里尝试后发现必须要使用sudo命令。
另外最后一行命令“-j6”是核心数,看你板子的情况,我这边是6核所以使用-j6,大家根据自己情况修改
使劲敲黑板
执行最后一步后会开始编译,编译时间视板子性能而定,一般需要30-60分钟,如果编译成功会在输出文件目录下出现.ko文件,编译好之后可以搜索一下,有的话编译过程就应该是成功了
后面的内容
后面的内容大家去看原作者写的就好,附上传送门:
写在最后
再次感谢CSDN上各位大佬的分享,希望我的内容对大家有帮助。