Recently started a new board, inside Gobinet and usbserial these are modular insmod inserted into the, although provided the source code but still do not understand what meaning, so the interest in this piece, because the company has and move far there is cooperation, It's coming. Their Linux source (itself is also open source) research, found in fact very simple, mainly refer to the hospital official document "Quectel_wcdma<e_linux_usb_driver_user_guide_v1.7.pdf" Next I will combine this document to everybody again.
=======================================================================
One, USB serial
If you are using the ec20********** and need to start the USB serial port, please detail this chapter or skip directly ....
1.1 adding vid and PID
Vid and PID are actually equivalent to the USB hardware identification ID system is also through them to find your EC20 device, modify the kernel file to add, methods as follows
Note: If other USB devices use these resources, delete the conflicting areas, such as in [KERNEL]/DRIVERS/USB/SERIAL/QCSERIAL.C neutralization [Kernel]/drivers/net/usb/qmi_ WWAN.C files have a duplicate description of (0X05C6, 0x9215) ID, the official document is deleted, I did not delete the test is OK, I think it should be my board without these equipment reasons. 1.2 Add Zero Packet mechanism
With the requirements of the USB protocol, you need to add a 0-pack mechanism to the bulkout transfer (direct translation of the follow up).
If your Linuxkernel version is new to 2.6.34, add it in file: [KERNEL]/DRIVERS/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 (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;
}
If the Linux version is below 2.6.35 is not the same as the above operation, it should be very few people use it now.
1.3 Add reset Resume callbackThis piece is related to the Linux device power management, when the microcontroller into hibernation/hibernate, some USB host controller/USB hub will lose power or reset.
mode, they cannot restore the USB device when the MCU exits suspend/hibernate mode; instead, they reset the operation to restore. You should add the following statement
Linux kernel version above 3.4 is added in file: [Kernel]/drivers/usb/serial/option.c files:
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
};
Linux kernel version Less than 3.5 is added in file: [KERNEL]/DRIVERS/USB/SERIAL/USB-SERIAL.C files:
/* 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,
};
1.4Use gobinet or Qmi WWANIf you use two drivers you also need to modify file: [Kernel]/drivers/usb/serial/option.c files (KERNEL higher than 2.6.30):It's worth noting here . The base option.c file in the document is different from mine.----Document: Static int option_probe (struct usb_serial *serial, const struct usb_device_id *id) {
struct Usb_wwan_intf_private *data;
......
#if 1//added by Quectel
Quectel UC20 ' s interface 4 can be used as USB network
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
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;
}
In my file: 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
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
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 beused As USB network device
if (Serial->dev->descriptor.idvendor = = Cpu_to_le16 (0x2c7c)
&& Serial->interface->cur_altsetting->desc.binterfacenumber >= 4)
Return-enodev;
#endif
data = Serial->private = Kzalloc (sizeof (struct usb_wwan_intf_private), gfp_kernel);
if (!data)
Return-enomem;
Data->send_setup = Option_send_setup;
Spin_lock_init (&data->susp_lock);
Data->private = (void *) id->driver_info;
return 0;
}
I do not know that the kernel is that version, see and describe a different look at the line of the above added are matching logic, the following is set function, a look will know that do not need to understand. I have tried it.
1.5 MenuconfigMenuconfig The following figure is set to save
1.6 TestStart with:
After compiling, run the kernel and you will find the figure:
The Dev directory already has a ttyusb* device, which proves that the USB serial drive has been completed.
Second, Gobinet Drive
When using the gobinet driver to move away from the module, Gobinet will create a network device (ETHX) and a QMI channel (Qcqmix),
Network devices are used for network transport QMI channel to be used for qmi information interaction.
2.1 The source of the module provided by the move away into the kernel
Later versions of the linux2.6 will be gobinet-driven sources into/[kernel]/drivers/usb/net/. If you are compiling the gobinet into the kernel, you can ignore
Goninet source code in the makefile, directly to the source code of the. C and. h files to the above directory.
2.2 Make Menuconfig
2.3 Add targets and dependencies in the makefile file
Add in the "KERNEL"/drivers/net/usb/makefile file:
obj-y + + GOBINET.O
GOBINET-OBJS: = GOBIUSBNET.O qmidevice.o qmi.o
2.4 Test