在hi3516平台上移植4G模块(合宙CAT1:air724UG)
1.前言
4G模块:合宙推出的Air724UG Cat1
Linux版本:linux4.9
硬件平台:hi3516dv300 (SDK版本:rp-hi3516dv300-sdk020-20201214.tgz)
hi3516dv300的SDK源码不做任何配置或修改再编译的话,开发板是不能正确识别4G模块的。为了能让开发板正确识别4G网卡以及能够上网,则有必要对源码进行配置和修改。
2.修改源代码SDK
a.添加设备VID和PID
->进入内核目录文件 [KERNEL]/drivers/usb/serial/option.c
->在结构体 static const struct usb_device_id option_ids[]中添加如下内容:
//+add by airm2m for Air72x
{ USB_DEVICE(0x1782, 0x4e00) },//CAT1
// { USB_DEVICE(0x1286, 0x4e3d) },//CAT4
//-add by airm2m for Air72x
结果如下:
static const struct usb_device_id option_ids[] = {
//+add by airm2m for Air72x
{ USB_DEVICE(0x1782, 0x4e00) },//CAT1
// { USB_DEVICE(0x1286, 0x4e3d) },//CAT4
//-add by airm2m for Air72x
{ 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) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD) },
/*******省略大部分************/
{ USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_WMD200, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_6802, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_WMD300, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x421d, 0xff, 0xff, 0xff) }, /* HP lt2523 (Novatel E371) */
{ } /* Terminating entry */
};
->在函数 option_probe中添加如下内容
//+add by airm2m for Air72x
//CAT1
if (dev_desc->idVendor == cpu_to_le16(0x1782) && dev_desc->idProduct == cpu_to_le16(0x4e00) && iface_desc->bInterfaceNumber <= 1)
{
return -ENODEV;
}
//CAT4
if (dev_desc->idVendor == cpu_to_le16(0x1286) && dev_desc->idProduct == cpu_to_le16(0x4e3d) && iface_desc->bInterfaceNumber <= 1)
{
return -ENODEV;
}
//-add by airm2m for Air72x
结果如下:
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;
const struct option_blacklist_info *blacklist;
/* 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.
*/
blacklist = (void *)id->driver_info;
if (blacklist && test_bit(iface_desc->bInterfaceNumber,
&blacklist->reserved))
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;
//+add by airm2m for Air72x
//CAT1
if (dev_desc->idVendor == cpu_to_le16(0x1782) && dev_desc->idProduct == cpu_to_le16(0x4e00) && iface_desc->bInterfaceNumber <= 1)
{
return -ENODEV;
}
//CAT4
if (dev_desc->idVendor == cpu_to_le16(0x1286) && dev_desc->idProduct == cpu_to_le16(0x4e3d) && iface_desc->bInterfaceNumber <= 1)
{
return -ENODEV;
}
//-add by airm2m for Air72x
/* Store the blacklist info so we can use it during attach. */
usb_set_serial_data(serial, (void *)blacklist);
return 0;
}
b.添加reset_resume
->进入内核目录文件 [KERNEL]/drivers/usb/serial/option.c
->在结构体中static struct usb_serial_driver option_1port_device添加如下内容:
//+add by airm2m for Air72x
.reset_resume = usb_wwan_resume,
//-add by airm2m for Air72x
结果如下:
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,
//+add by airm2m for Air72x
.reset_resume = usb_wwan_resume,
//-add by airm2m for Air72x
#endif
};
c.增加零包机制
->进入内核目录文件 [KERNEL]/drivers/usb/serial/usb_wwan.c中
->在函数 usb_wwan_setup_urb中添加如下内容
//+add by airm2m for Air72x
if(dir == USB_DIR_OUT){
struct usb_device_descriptor *desc = &serial->dev->descriptor;
//CAT1
if(desc->idVendor == cpu_to_le16(0x1782) && desc->idProduct == cpu_to_le16(0x4e00))
{
urb->transfer_flags |= URB_ZERO_PACKET;
}
//CAT4
// if(desc->idVendor == cpu_to_le16(0x1286) && desc->idProduct == cpu_to_le16(0x4e3d))
// {
// urb->transfer_flags |= URB_ZERO_PACKET;
// }
}
//-add by airm2m for Air72x
结果如下:
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);
//+add by airm2m for Air72x
if(dir == USB_DIR_OUT){
struct usb_device_descriptor *desc = &serial->dev->descriptor;
//CAT1
if(desc->idVendor == cpu_to_le16(0x1782) && desc->idProduct == cpu_to_le16(0x4e00))
{
urb->transfer_flags |= URB_ZERO_PACKET;
}
//CAT4
// if(desc->idVendor == cpu_to_le16(0x1286) && desc->idProduct == cpu_to_le16(0x4e3d))
// {
// urb->transfer_flags |= URB_ZERO_PACKET;
// }
}
//-add by airm2m for Air72x
return urb;
}
3.修改内核选项
make ARCH=arm CROSS_COMPILE=arm-himix200-linux- menuconfig
Enable CONFIG_USB_SERIAL_OPTION
[]Device Drivers →
[] USB Support →
[] USB Serial Converter support →
[] USB driver for GSM and CDMA modems
[] Device Drivers →
[] Network device support →
[*] PPP (point-to-point protocol) support
make 之后
make ARCH=arm CROSS_COMPILE=arm-himix200-linux- uImage -j32
结果如下:
4.加载驱动文件
将以下内核驱动文件拷贝到根文件系统中
[kernel]/drivers/net/usb/usbnet.ko
[kernel]/drivers/net/usb/cdc_ether.ko
[kernel]/drivers/net/usb/rndis_host.ko
加载到内核
insmod usbnet.ko
insmod cdc_ether.ko
insmod rndis_host.ko
结果如下:
5.查看是否出现新的模块网卡ethx
ifconfig -a
结果如下:
6.启动网卡模块网卡ethx
ifconfig eth1 up
7.添加模块网卡的默认网关
Ifconfig -a出现了新的模块网卡之后,这个时候模块网卡无法ping通外网,必须把本地网卡网线拔掉才能使用模块网卡ping通外网
解決方法:需要设置一次ethx的默认网关
1.查看系统当前路由表:
ip route show
#或者
route
2.设置一次ethx的默认网关:
route add default gw xxx.xxx.xxx.xxx ethx
例子:
route add default gw 192.168.5.1 eth1
结果如下:
问题
a.linux下多个usb设备不固定名称
输入命令:
ls /sys/class/tty/ttyUSB* -l // 查看usb设备信息
其中的1-1:1.2/1-1:1.3/1-1:1.4为固定的串口编号。
或者输入命令
udevadm info --attribute-walk --name=/dev/ttyUSB0
udevadm info --attribute-walk --name=/dev/ttyUSB1
udevadm info --attribute-walk --name=/dev/ttyUSB2
udevadm info --attribute-walk --name=/dev/ttyUSB0 |grep KERNELS #通过对比信息中的不同,可以提取出区别与各个串口的KERNELS值,
udevadm info --attribute-walk --name=/dev/ttyUSB1 |grep KERNELS #通过对比信息中的不同,可以提取出区别与各个串口的KERNELS值,
udevadm info --attribute-walk --name=/dev/ttyUSB2 |grep KERNELS #通过对比信息中的不同,可以提取出区别与各个串口的KERNELS值,
添加在/etc/udev/rules.d/xxxxx.rules 文件
创建一个10-local.rules 文件(root权限下建立,命名可以自定义),并添加以下内容:
KERNELS=="1-1:1.4", KERNEL=="ttyUSB*", MODE:="0777", SYMLINK+="4G_uart"
#KERNELS是工控机usb插口编号、
#KERNEL是内核设备名称
#OWNER, GROUP, MODE是设备设定权限
#SYMLINK+是为 /dev/下的设备文件产生符号链接。由于 udev 只能为某个设备产生一个设备文件,所以为了不覆盖系统默认的 udev 规则所产生的文件,推荐使用符号链接。
保存退出。重新插拔设备(或重启)就会在/dev目录下生成固定的设备名(本实例为:4G_uart)。
也可以重启服务:
#分别在终端输入以下命令,要保持一定的时间间隔:
sudo service udev reload
sudo service udev restart
备注:
1.固定好之后usb设备插入的usb端口不能再改变。
2.操作中如果提示权限问题,用root用户操作即可。
3.若ttyUSB设备过多找不到自己要固定的串口设备,可以对要固定的设备进行拔插,通过比较插拔前后ls /sys/class/tty/ttyUSB* -l命令输出结果来找到所需要固定的串口号。
4.此方法也适用其他usb设备的固定,例如usb摄像头。。