从linux-3.10.11移植qmi_wwan.c到MT7620原生SDK使用的linux-2.6.36.x
该驱动对应使用 Qualcomm MSM Interface (QMI)的2G/4G dongle,源码中解释如下:
/* This driver supports wwan (3G/LTE/?) devices using a vendor
* specific management protocol called Qualcomm MSM Interface (QMI) -
* in addition to the more common AT commands over serial interface
* management
*
* QMI is wrapped in CDC, using CDC encapsulated commands on the
* control ("master") interface of a two-interface CDC Union
* resembling standard CDC ECM. The devices do not use the control
* interface for any other CDC messages. Most likely because the
* management protocol is used in place of the standard CDC
* notifications NOTIFY_NETWORK_CONNECTION and NOTIFY_SPEED_CHANGE
*
* Alternatively, control and data functions can be combined in a
* single USB interface.
*
* Handling a protocol like QMI is out of the scope for any driver.
* It is exported as a character device using the cdc-wdm driver as
* a subdriver, enabling userspace applications ("modem managers") to
* handle it.
*
* These devices may alternatively/additionally be configured using AT
* commands on a serial interface
*/
首先拷贝"linux-3.10.11\drivers\net\usb\qmi_wwan.c"到“linux-2.6.36.x\drivers\net\usb\”目录,以及修改该目录的makefile,kconfig;编译时会有错误,需要在做一些工作,其中的一部分如下所示:
1)修改“linux-2.6.36.x\include\linux\mod_devicetable.h” 增加“__u8 bInterfaceNumber;”
/**
* struct usb_device_id - identifies USB devices for probing and hotplugging
* @match_flags: Bit mask controlling of the other fields are used to match
* against new devices. Any field except for driver_info may be used,
* although some only make sense in conjunction with other fields.
* This is usually set by a USB_DEVICE_*() macro, which sets all
* other fields in this structure except for driver_info.
* @idVendor: USB vendor ID for a device; numbers are assigned
* by the USB forum to its members.
* @idProduct: Vendor-assigned product ID.
* @bcdDevice_lo: Low end of range of vendor-assigned product version numbers.
* This is also used to identify individual product versions, for
* a range consisting of a single device.
* @bcdDevice_hi: High end of version number range. The range of product
* versions is inclusive.
* @bDeviceClass: Class of device; numbers are assigned
* by the USB forum. Products may choose to implement classes,
* or be vendor-specific. Device classes specify behavior of all
* the interfaces on a devices.
* @bDeviceSubClass: Subclass of device; associated with bDeviceClass.
* @bDeviceProtocol: Protocol of device; associated with bDeviceClass.
* @bInterfaceClass: Class of interface; numbers are assigned
* by the USB forum. Products may choose to implement classes,
* or be vendor-specific. Interface classes specify behavior only
* of a given interface; other interfaces may support other classes.
* @bInterfaceSubClass: Subclass of interface; associated with bInterfaceClass.
* @bInterfaceProtocol: Protocol of interface; associated with bInterfaceClass.
* @bInterfaceNumber: Number of interface; composite devices may use
* fixed interface numbers to differentiate between vendor-specific
* interfaces.
* @driver_info: Holds information used by the driver. Usually it holds
* a pointer to a descriptor understood by the driver, or perhaps
* device flags.
*
* In most cases, drivers will create a table of device IDs by using
* USB_DEVICE(), or similar macros designed for that purpose.
* They will then export it to userspace using MODULE_DEVICE_TABLE(),
* and provide it to the USB core through their usb_driver structure.
*
* See the usb_match_id() function for information about how matches are
* performed. Briefly, you will normally use one of several macros to help
* construct these entries. Each entry you provide will either identify
* one or more specific products, or will identify a class of products
* which have agreed to behave the same. You should put the more specific
* matches towards the beginning of your table, so that driver_info can
* record quirks of specific products.
*/
struct usb_device_id {
/* which fields to match against? */
__u16 match_flags;
/* Used for product specific matches; range is inclusive */
__u16 idVendor;
__u16 idProduct;
__u16 bcdDevice_lo;
__u16 bcdDevice_hi;
/* Used for device class matches */
__u8 bDeviceClass;
__u8 bDeviceSubClass;
__u8 bDeviceProtocol;
/* Used for interface class matches */
__u8 bInterfaceClass;
__u8 bInterfaceSubClass;
__u8 bInterfaceProtocol;
/* Used for vendor-specific interface matches */
__u8 bInterfaceNumber;
/* not matched against */
kernel_ulong_t driver_info
__attribute__((aligned(sizeof(kernel_ulong_t))));
};
2)拷贝“linux-3.10.11\include\uapi\linux\usb\cdc-wdm.h”到“linux-2.6.36.x\include\uapi\linux\usb\”目录
3)
drivers/net/usb/qmi_wwan.c: In function `qmi_wwan_mac_addr':
drivers/net/usb/qmi_wwan.c:127: error: implicit declaration of function `eth_prepare_mac_addr_change'
drivers/net/usb/qmi_wwan.c:132: error: implicit declaration of function `eth_commit_mac_addr_change'
drivers/net/usb/qmi_wwan.c: In function `qmi_wwan_bind':
drivers/net/usb/qmi_wwan.c:327: error: implicit declaration of function `eth_hw_addr_random'
解决上面的错误,修改linux-2.6.36.x\net\ethernet\eth.c
linux-2.6.36.x\include\linux\etherdevice.h
根据linux-3.10.11对应修改。尽量只解决编译问题,不引起太大的改动。例如“alloc_etherdev_mq”函数涉及到的地方比较多,尽量保持linux-2.6.36.x中的定义。
4)
error: unknown field `disable_hub_initiated_lpm' specified in initializer
修改 “linux-2.6.36.x\include\linux\usb.h”中“struct usb_driver”,增加“unsigned int disable_hub_initiated_lpm:1;”
struct usb_driver {
const char *name;
int (*probe) (struct usb_interface *intf,
const struct usb_device_id *id);
void (*disconnect) (struct usb_interface *intf);
int (*unlocked_ioctl) (struct usb_interface *intf, unsigned int code,
void *buf);
int (*suspend) (struct usb_interface *intf, pm_message_t message);
int (*resume) (struct usb_interface *intf);
int (*reset_resume)(struct usb_interface *intf);
int (*pre_reset)(struct usb_interface *intf);
int (*post_reset)(struct usb_interface *intf);
const struct usb_device_id *id_table;
struct usb_dynids dynids;
struct usbdrv_wrap drvwrap;
unsigned int no_dynamic_id:1;
unsigned int supports_autosuspend:1;
unsigned int disable_hub_initiated_lpm:1;
unsigned int soft_unbind:1;
};
5)
CC net/ethernet/eth.o
net/ethernet/eth.c: In function `eth_prepare_mac_addr_change':
net/ethernet/eth.c:282: error: `IFF_LIVE_ADDR_CHANGE' undeclared (first use in this function)
找到如下定义,添加到eth.c中
#define IFF_LIVE_ADDR_CHANGE 0x100000 /* device supports hardware address
* change when it's running */
总之,遇到编译错误,就从linux-3.10.11中将相关代码移植到linux 2.6.36;
最终是可以编译过的,不过手上没有相应的dongle,无法验证工作是否OK。