参考了不少教程,也做了不少尝试,最后记录下整个过程以便自己和坛友们参考
我所用的4G模块是Quectel EC20 R2.0,对于这个型号以下的操作前半部分修改USB Serial驱动应该是不需要的,但是我也都修改了并且记录下来,对于其他品牌型号的模块应该是原理相通的
0531_6.jpg (180.92 KB, 下载次数: 0)
2020-5-31 11:04 上传
修改内核增加USB Serial驱动支持
1.增加PID&VID,教程中所用内核4.4.79尚没有支持,我用的4.19.122已经支持,而且两者之间的定义方式稍有不同
教程里需要添加的代码为
build_dir/target-mips_24kc_musl/linux-ar71xx_generic/linux-4.4.79/drivers/usb/serial/option.c
【注】只添加#if 1 到 #endif的内容
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_id option_ids[]里添加了移远各型号的PID和VID
而新内核的此结构体是通过在前面define然后后面通过VENDOR_ID和PRODUCT来定义
#define QUECTEL_VENDOR_ID 0x2c7c
/* These Quectel products use Quectel's vendor ID */
#define QUECTEL_PRODUCT_EC21 0x0121
#define QUECTEL_PRODUCT_EC25 0x0125
#define QUECTEL_PRODUCT_BG96 0x0296
#define QUECTEL_PRODUCT_EP06 0x0306
#define QUECTEL_PRODUCT_EM12 0x0512
#define QUECTEL_PRODUCT_RM500Q 0x0800
后面则是
{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25), .driver_info = RSVD(4) },
总之就是此处不需要额外修改了
2.添加零包处理
文件位于build_dir/target-mips_24kc_musl/linux-ar71xx_generic/linux-4.4.79/drivers/usb/serial/usb_wwan.c
添加在函数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 usb_wwan_intf_private *intfdata = usb_get_serial_data(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);
if (intfdata->use_zlp && dir == USB_DIR_OUT)
urb->transfer_flags |= URB_ZERO_PACKET;
#if 1 //Added by Quectelfor 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->idV