UsbSerial
The USB interface can be a tty device. Qualcomm modules generally have the following ports
DM Port (for diagnose, firmware upgrading);
GPS Port (for nmea log output)
AT Port (For AT cmd test)
ppp Port (Also known as modem, can be used for AT cmd test too);
If there no any other ttyUSB device exists, you’ll see device nodes created: /dev/ttyUSB0, /dev/ttyUSB1, dev/ttyUSB2, /dev/ttyUSB3
Add PID and VID
Add Quectel VID and PID into ${KERNELDIR}/driver/usb/serial/option.c
static const struct usb_device_id option_ids[] = {
#if 1 //Added by Quectel
{ USB_DEVICE(0x2C7C, 0x0125) }, /* Quectel EC20 R2.0/EC20 R2.1/EC25/EG25-G/EM05 */
{ USB_DEVICE(0x2C7C, 0x0121) }, /* Quectel EC21/EG21-G */
{ USB_DEVICE(0x2C7C, 0x0191) }, /* Quectel EG91 */
{ USB_DEVICE(0x2C7C, 0x0195) }, /* Quectel EG95 */
{ USB_DEVICE(0x2C7C, 0x0306) }, /* Quectel EG06/EP06/EM06 */
{ USB_DEVICE(0x2C7C, 0x0512) }, /* Quectel EG12/EM12/EG18 */
{ USB_DEVICE(0x2C7C, 0x0296) }, /* Quectel BG96 */
{ USB_DEVICE(0x2C7C, 0x0700) }, /* Quectel BG95/BG77/BG600L-M3/BC69 */
{ USB_DEVICE(0x2C7C, 0x0435) }, /* Quectel AG35 */
{ USB_DEVICE(0x2C7C, 0x0415) }, /* Quectel AG15 */
{ USB_DEVICE(0x2C7C, 0x0452) }, /* Quectel AG520R */
{ USB_DEVICE(0x2C7C, 0x0455) }, /* Quectel AG550R */
{ USB_DEVICE(0x2C7C, 0x0620) }, /* Quectel EG20 */
{ USB_DEVICE(0x2C7C, 0x0800) }, /* Quectel RG500Q/RM500Q/RG510Q/RM510Q */
#endif
Add the Zero Packet Mechanism
As required by the USB protocol, the mechanism for processing zero packets needs to be added during bulk-out transmission by adding the following statements.
${KERNELDIR}/driver/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(0x2C7C))
urb->transfer_flags |= URB_ZERO_PACKET;
}
#endif
return urb;
}
PM
${KERNELDIR}/driver/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
};
Reserve Interface for Net
For RMNET/ECM/MBIM interface, USB interface 4 is for net interface , ${KERNELDIR}/driver/usb/serial/option.c
static int option_probe {
...
#if 1 //Added by Quectel
//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;
}
}
#endif
For RNDIS interface
rndis_host would match the interface 0 and 1, and the option would match interface 2 to 5.
Kernel Config
Those are needed:
CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_OPTION=y
Ubuntu PC
In the case that an Option driver in Ubuntu PC or kernel is compiled into a kernel module, CONFIG_USB_SERIAL_OPTION=m, Quectel provides the source code for a USB serial driver that can be compiled and installed directly on an Ubuntu PC. For example, quectel_linux_USB_serial_option_DRIVER_20200720.tgz, unzip can get the USB serial port driver from kernel 2.6 to the latest kernel version, on Ubuntu PC, “make” && “sudo make install” is successful. In the case of cross-compilation of embedded system, the Makefile needs to be modified, and the option.ko obtained by compilation is copied to /lib/modules/ XXX/directory of the target platform.
stty
Adjust the properties of the serial port
stty -F /dev/ttyUSB2
stty -F /dev/ttyUSB2 ignbrk
stty -F /dev/ttyUSB2 -brkint
stty -F /dev/ttyUSB2 -icrnl
stty -F /dev/ttyUSB2 -imaxbel
stty -F /dev/ttyUSB2 -opost
stty -F /dev/ttyUSB2 -onlcr
stty -F /dev/ttyUSB2 -isig
stty -F /dev/ttyUSB2 -icanon
stty -F /dev/ttyUSB2 -iexten
stty -F /dev/ttyUSB2 -echo
stty -F /dev/ttyUSB2 -echoe
stty -F /dev/ttyUSB2 -echok
stty -F /dev/ttyUSB2 -echoctl
stty -F /dev/ttyUSB2 -echoke
stty -F /dev/ttyUSB2