zl程序教程

您现在的位置是:首页 >  系统

当前栏目

嵌入式Linux,4G模组驱动,移远EC20、EC25使用随笔-内核kernel

Linux驱动内核嵌入式 随笔 Kernel 4G 模组
2023-09-14 09:09:34 时间

移远EC20、EC25内核驱动修改。内核版本为3.2.0。

一、设备信息。

Interface Information:

EC20
VID: 0x05c6 PID: 0x9215
USB Serial
ttyUSB0 -> DM
ttyUSB1 -> NMEA
ttyUSB2 -> AT
ttyUSB3 -> Modem
ttyUSB4 -> NDIS

EC25
VID: 0x2c7c PID: 0x0125

二、修改文件。

1、Add VID and PID。

文件:kernel/drivers/usb/serial/option.c。

static const struct usb_device_id option_ids[] = {
...
	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */
	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
#if 1 //Added by Quectel
	{ USB_DEVICE(0x05C6, 0x9090) }, /* Quectel UC15 */
	{ USB_DEVICE(0x05C6, 0x9003) }, /* Quectel UC20 */
	{ USB_DEVICE(0x2C7C, 0x0125) }, /* Quectel EC25/EC20 R2.0 */
	{ 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 */
#endif
	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6280) }, /* BP3-USB & BP3-EXT HSDPA */
	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) },
	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
...

文件:kernel/drivers/usb/serial/qcserial.c。

static const struct usb_device_id id_table[] = {
...
	{USB_DEVICE(0x03f0, 0x251d)},	/* HP Gobi 2000 Modem device (VP412) */
	{USB_DEVICE(0x05c6, 0x9214)},	/* Acer Gobi 2000 QDL device (VP413) */
	{USB_DEVICE(0x05c6, 0x9215)},	/* Acer Gobi 2000 Modem device (VP413) */
	{USB_DEVICE(0x05c6, 0x9264)},	/* Asus Gobi 2000 QDL device (VR305) */
...

文件:kernel/drivers/net/usb/qmi_wwan.c。(无此文件)

{QMI_GOBI_DEVICE(0x05c6, 0x9215)}, /* Acer Gobi 2000 Modem device (VP413) */

2、Add the Zero Packet Mechanism。

文件:kernel/drivers/usb/serial/usb_wwan.c。For Linux Kernel Version newer than 2.6.34:

/* Helper functions used by usb_wwan_setup_urbs */
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 *))
{
...
	/* Fill URB using supplied data. */
	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;
}
...

文件:kernel/drivers/usb/serial/option.c。For Linux Kernel Version older than 2.6.35:

/* 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、Add Reset Resume。

文件:kernel/drivers/usb/serial/option.c。For Linux Kernel Version newer than 3.4:

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
};

文件:kernel/drivers/usb/serial/ usb-serial.c。For Linux Kernel Version older than 3.5:

/* 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,
};

4、Enlarge Bulk out URBs。

文件:kernel/drivers/usb/serial/option.c。

原:
/* per port private data */

#define N_IN_URB 4
#define N_OUT_URB 4
#define IN_BUFLEN 4096
#define OUT_BUFLEN 4096

改:
/* per port private data */

#define N_IN_URB 4
#define N_OUT_URB 4 //Quectel 1
#define IN_BUFLEN 4096
#define OUT_BUFLEN 4096 //Quectel 128

5、Use GobiNet or QMI WWAN。(无此文件)

文件:kernel/drivers/usb/serial/option.c。For Linux Kernel Version newer than 2.6.30:

static int option_probe(struct usb_serial *serial,
			const struct usb_device_id *id)
{
...
#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&EC20 R2.0&EG91&EG95&EG06&EP06&EM06&BG96'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;
}
...

文件:kernel/drivers/usb/serial/option.c。For Linux Kernel Version older than 2.6.31:

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&EC20 R2.0&EG91&EG95&EG06&EP06&EM06&BG96'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
...

三、内核配置,Modify Kernel Configuration。

1、Enable CONFIG_USB_SERIAL_OPTION。

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

Configure USB Serial in Kernel:

2、Enable CONFIG_USB_USBNET。

[*] Device Drivers
    -->-*- Network device support
        -->USB Network Adapters
            <*> Multi-purpose USB Networking Framework

3、WWAN driver。

[*] Device Drivers
    -->-*- Network device support
        -->USB Network Adapters
            <*> USB-to-WWAN Driver for Sierra Wireless modems

4、Configure Kernel to Support PPP。

[*] Device Drivers
    -->[*] Network device support
        [*] PPP (point-to-point protocol) support