NUC977移植EC20

确认硬件是否正常,使用busybox lsusb查看

 USB Serial Driver

Add VID and PID

Add Reset Resume

Enlarge Bulk out URBs

Use GobiNet or QMI WWAN

File: [KERNEL]/drivers/usb/serial/option.c

root@virtual-machine:/linux-3.10.108/drivers/usb/serial# diff option.c /linux-3.10.x/drivers/usb/serial/option.c 
277d276
< #define TELIT_PRODUCT_LE910_USBCFG4        0x1206
379,382c378,380
< /* Gemalto's Cinterion products (formerly Siemens) */
< #define SIEMENS_VENDOR_ID            0x0681
< #define CINTERION_VENDOR_ID            0x1e2d
< #define CINTERION_PRODUCT_HC25_MDMNET        0x0040
---
> /* Cinterion (formerly Siemens) products */
> #define SIEMENS_VENDOR_ID                0x0681
> #define CINTERION_VENDOR_ID                0x1e2d
384c382
< #define CINTERION_PRODUCT_HC28_MDMNET        0x004A /* same for HC28J */
---
> #define CINTERION_PRODUCT_HC25_MDMNET    0x0040
385a384
> #define CINTERION_PRODUCT_HC28_MDMNET    0x004A /* same for HC28J */
391,394d389
< #define CINTERION_PRODUCT_PH8_2RMNET        0x0082
< #define CINTERION_PRODUCT_PH8_AUDIO        0x0083
< #define CINTERION_PRODUCT_AHXX_2RMNET        0x0084
< #define CINTERION_PRODUCT_AHXX_AUDIO        0x0085
649,652d643
< static const struct option_blacklist_info cinterion_rmnet2_blacklist = {
<     .reserved = BIT(4) | BIT(5),
< };

653a645,656
> #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
1210,1211d1212
<     { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910_USBCFG4),
<         .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 },
1726,1732c1727
<     { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8_2RMNET, 0xff),
<         .driver_info = (kernel_ulong_t)&cinterion_rmnet2_blacklist },
<     { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8_AUDIO, 0xff),
<         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
<     { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX_2RMNET, 0xff) },
<     { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX_AUDIO, 0xff) },
<     { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) },
---
>     { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, 
1838,1839d1832
<     { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e19, 0xff),            /* D-Link DWM-221 B1 */
<       .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
1844a1838
>     
1879a1874,1876
> #if 1 //Added by Quectel
>      .reset_resume = usb_wwan_resume, 
> #endif 
1946,1947c1943,2000

<     /* Store device id so we can use it during attach. */
---
> #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&EG91&EG95&EG06&EP06&EM06&BG96/AG35'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
> #if 1 //Added by Quectel
>      //For USB Auto Suspend
>      if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
>              serial->dev->descriptor.idProduct == cpu_to_le16(0x9090)) {
>          pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000);
>          usb_enable_autosuspend(serial->dev);
>      }
>      if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
>              serial->dev->descriptor.idProduct == cpu_to_le16(0x9003)) {
>          pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000);
>          usb_enable_autosuspend(serial->dev);
>      }
>      if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
>              serial->dev->descriptor.idProduct == cpu_to_le16(0x9215)) {
>          pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000); 
>          usb_enable_autosuspend(serial->dev);
>           }
>      if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C)) {
>          pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000);
>          usb_enable_autosuspend(serial->dev);
>      }
> #endif 
> #if 1 //Added by Quectel
>      //For USB Remote Wakeup
>      if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
>              serial->dev->descriptor.idProduct == cpu_to_le16(0x9090)) {
>          device_init_wakeup(&serial->dev->dev, 1); //usb remote wakeup
>      }
>      if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
>              serial->dev->descriptor.idProduct == cpu_to_le16(0x9003)) {
>          device_init_wakeup(&serial->dev->dev, 1); //usb remote wakeup
>      }
>      if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
>              serial->dev->descriptor.idProduct == cpu_to_le16(0x9215)) {
>          device_init_wakeup(&serial->dev->dev, 1); //usb remote wakeup
>      }
>      if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C)) {
>          device_init_wakeup(&serial->dev->dev, 1); //usb remote wakeup
>      }
> #endif 
>      /* Store device id so we can use it during attach. */
 

Add the Zero Packet Mechanism

File: [KERNEL]/drivers/usb/serial/usb_wwan.c 

root@virtual-machine:/linux-3.10.108/drivers/usb/serial# diff usb_wwan.c /linux-3.10.x/drivers/usb/serial/usb_wwan.c 
492,493c492,507
<               usb_sndbulkpipe(serial->dev, endpoint) | dir,
<               buf, len, callback, ctx);
---
>             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) && desc->idProduct == cpu_to_le16(0x0125)) 
>             urb->transfer_flags |= URB_ZERO_PACKET; 
>     } 
> #endif
 

Add Reset Resume

File: [KERNEL]/drivers/usb/serial/ usb-serial.c

root@virtual-machine: /linux-3.10.108/drivers/usb/serial# diff usb-serial.c /linux-3.10.x/drivers/usb/serial/usb-serial.c 
1447c1447
<         goto failed_usb_register;
---
>         return rc;
1465,1466d1464
< failed_usb_register:
<     kfree(udriver);
 

 QMI WWAN Driver

Add VID and PID 

Add Support for Raw IP Mode

[KERNEL]/drivers/net/usb/qmi_wwan.c 

root@yhj-virtual-machine:/home/yhj/sky9151/linux-3.10.108/drivers/net/usb# diff qmi_wwan.c /home/yhj/sky9151/linux-3.10.x/drivers/net/usb/qmi_wwan.c
21a22,81
> #if 1 //Added by Quectel
> #include <linux/etherdevice.h>
> struct sk_buff *qmi_wwan_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
> {
>     if (dev->udev->descriptor.idVendor != cpu_to_le16(0x2C7C))
>         return skb;
>     // Skip Ethernet header from message
>     if (skb_pull(skb, ETH_HLEN)) {
>         return skb;
>     } else {
>         dev_err(&dev->intf->dev, "Packet Dropped ");
>     }
>     // Filter the packet out, release it
>     dev_kfree_skb_any(skb);
>     return NULL;
> }
> #include <linux/version.h>
> #if (LINUX_VERSION_CODE < KERNEL_VERSION( 3,9,1 ))
> static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
> {
>     __be16 proto;
>     if (dev->udev->descriptor.idVendor != cpu_to_le16(0x2C7C))
>         return 1;
>     /* This check is no longer done by usbnet */
>     if (skb->len < dev->net->hard_header_len) 
>         return 0;
>     switch (skb->data[0] & 0xf0) {
>         case 0x40:
>             proto = htons(ETH_P_IP);
>             break;
>         case 0x60:
>             proto = htons(ETH_P_IPV6);
>             break;
>         case 0x00:
>             if (is_multicast_ether_addr(skb->data))
>                 return 1;
>             /* possibly bogus destination - rewrite just in case */
>             skb_reset_mac_header(skb);
>             goto fix_dest;
>         default:
>             /* pass along other packets without modifications */
>             return 1;
>     }
>     if (skb_headroom(skb) < ETH_HLEN)
>         return 0;
>     skb_push(skb, ETH_HLEN);
>     skb_reset_mac_header(skb);
>     eth_hdr(skb)->h_proto = proto;
>     memset(eth_hdr(skb)->h_source, 0, ETH_ALEN);
> fix_dest:
>     memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN);
>     return 1;
> }
> /* very simplistic detection of IPv4 or IPv6 headers */
> static bool possibly_iphdr(const char *data)
> {
>     return (data[0] & 0xd0) == 0x40;
> }
> #endif
> #endif 
334a395,416
> #if 1 //Added by Quectel
>      if (dev->udev->descriptor.idVendor == cpu_to_le16(0x2C7C)) {
>           printk("Quectel EC25&EC21&EG91&EG95&EG06&EP06&EM06&BG96&AG35 work on RawIP mode\n");
>            dev->net->flags |= IFF_NOARP;
> #if (LINUX_VERSION_CODE < KERNEL_VERSION( 3,9,1 ))
>             /* make MAC addr easily distinguishable from an IP header */
>             if (possibly_iphdr(dev->net->dev_addr)) {
>                  dev->net->dev_addr[0] |= 0x02; /* set local assignment bit */
>                   dev->net->dev_addr[0] &= 0xbf; /* clear "IP" bit */
>                    }
> #endif
>              usb_control_msg(
>                       interface_to_usbdev(intf),
>                        usb_sndctrlpipe(interface_to_usbdev(intf), 0),
>                         0x22, //USB_CDC_REQ_SET_CONTROL_LINE_STATE
>                          0x21, //USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE
>                           1, //active CDC DTR
>                            intf->cur_altsetting->desc.bInterfaceNumber,
>                             NULL, 0, 100);
>               }
> #endif

337a420,446
> static int qmi_wwan_bind_shared(struct usbnet *dev, struct usb_interface *intf)
> {
>     int status = -1;
> #if 1 //Added by Quectel
>          if (dev->udev->descriptor.idVendor == cpu_to_le16(0x2C7C)) {
>               printk("Quectel EC25&EC21&EG91&EG95&EG06&EP06&EM06&BG96&AG35 work on RawIP mode\n");
>                dev->net->flags |= IFF_NOARP;
> #if (LINUX_VERSION_CODE < KERNEL_VERSION( 3,9,1 ))
>                 /* make MAC addr easily distinguishable from an IP header */
>                 if (possibly_iphdr(dev->net->dev_addr)) {
>                      dev->net->dev_addr[0] |= 0x02; /* set local assignment bit */
>                       dev->net->dev_addr[0] &= 0xbf; /* clear "IP" bit */ 
>                        }
> #endif
>                  usb_control_msg(
>                           interface_to_usbdev(intf),
>                            usb_sndctrlpipe(interface_to_usbdev(intf), 0),
>                             0x22, //USB_CDC_REQ_SET_CONTROL_LINE_STATE
>                              0x21, //USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE
>                               1, //active CDC DTR
>                                intf->cur_altsetting->desc.bInterfaceNumber,
>                                 NULL, 0, 100);
>                   }
> #endif
> err:
>      return status;
> } 
418a528,543
> #if 1 //Added by Quectel
>      .tx_fixup = qmi_wwan_tx_fixup,
>       .rx_fixup = qmi_wwan_rx_fixup,
> #endif 
> };
> static const struct driver_info qmi_wwan_force_int4 = {
> #if 1 //Added by Quectel
>          .tx_fixup = qmi_wwan_tx_fixup,
>      .rx_fixup = qmi_wwan_rx_fixup,
> #endif
> };
> static const struct driver_info qmi_wwan_shared = {
> #if 1 //Added by Quectel
>          .tx_fixup = qmi_wwan_tx_fixup,
>      .rx_fixup = qmi_wwan_rx_fixup,
> #endif
436a562,584
> #if 1 //Added by Quectel
> #ifndef QMI_FIXED_INTF
>     /* map QMI/wwan function by a fixed interface number */
> #define QMI_FIXED_INTF(vend, prod, num) \
>      .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
>     USB_DEVICE_ID_MATCH_INT_INFO, \
>          .idVendor = vend, \
>           .idProduct = prod, \
>            .bInterfaceClass = 0xff, \
>             .bInterfaceSubClass = 0xff, \
>              .bInterfaceProtocol = 0xff, \
>               .driver_info = (unsigned long)&qmi_wwan_force_int##num,
> #endif
>      { QMI_FIXED_INTF(0x05C6, 0x9003, 4) }, /* Quectel UC20 */
>       { QMI_FIXED_INTF(0x2C7C, 0x0125, 4) }, /* Quectel EC25 */
>        { QMI_FIXED_INTF(0x2C7C, 0x0121, 4) }, /* Quectel EC21 */
>         { QMI_FIXED_INTF(0x05C6, 0x9215, 4) }, /* Quectel EC20 */
>         { QMI_FIXED_INTF(0x2C7C, 0x0191, 4) }, /* Quectel EG91 */
>         { QMI_FIXED_INTF(0x2C7C, 0x0195, 4) }, /* Quectel EG95 */
>         { QMI_FIXED_INTF(0x2C7C, 0x0306, 4) }, /* Quectel EG06/EP06/EM06 */
>         { QMI_FIXED_INTF(0x2C7C, 0x0296, 4) }, /* Quectel BG96 */
>         { QMI_FIXED_INTF(0x2C7C, 0x0435, 4) }, /* Quectel AG35 */
> #endif 
727d874
<     {QMI_FIXED_INTF(0x2001, 0x7e19, 4)},    /* D-Link DWM-221 B1 */
790a938,939
>     /*invoid to conflict EC20 module*/
> #if 0
791a941
> #endif
GobiNet Driver

[KERNEL]/drivers/usb/serial/qcserial.c

[KERNEL]/drivers/net/usb/qmi_wwan.c 

root@virtual-machine:/sky9151/linux-3.10.108/drivers/usb/serial# diff qcserial.c /sky9151/linux-3.10.x/drivers/usb/serial/qcserial.c 
81c81,84
<     {USB_DEVICE(0x05c6, 0x9215)},    /* Acer Gobi 2000 Modem device (VP413) */
---
>     /*invoid conflict with EC20 module*/
>     #if 0
>         {USB_DEVICE(0x05c6, 0x9215)},    /* Acer Gobi 2000 Modem device (VP413) */
>     #endif
 

Modify Kernel Configuration

[*] Device Drivers → 
-*- Network device support → 
USB Network Adapters → 
{*} Multi-purpose USB Networking Framework 
<*> QMI WWAN driver for Qualcomm MSM based 3G and LTE modems

[*] Device Drivers → 
[*] USB Support → 
[*] USB Modem (CDC ACM) support 

 

Power Management

[KERNEL]/drivers/usb/serial/option.c

[KERNEL]/drivers/usb/class/cdc-acm.c

root@virtual-machine:/linux-3.10.108/drivers/usb/class# diff cdc-acm.c /linux-3.10.x/drivers/usb/class/cdc-acm.c 
546,547c546
<     retval = usb_submit_urb(acm->ctrlurb, GFP_KERNEL);
<     if (retval) {
---
>     if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
554,555c553,554
<     retval = acm_set_control(acm, acm->ctrlout);
<     if (retval < 0 && (acm->ctrl_caps & USB_CDC_CAP_LINE))
---
>     if (acm_set_control(acm, acm->ctrlout) < 0 &&
>         (acm->ctrl_caps & USB_CDC_CAP_LINE))
557a557,558
>     usb_autopm_put_interface(acm->control);

566,567c567
<     retval = acm_submit_read_urbs(acm, GFP_KERNEL);
<     if (retval)
---
>     if (acm_submit_read_urbs(acm, GFP_KERNEL))
570,571d569
<     usb_autopm_put_interface(acm->control);

588,589c586

<     return usb_translate_errors(retval);
---
>     return retval;
1003,1005d999
<         /* we would crash */
<         if (!data_interface || !control_interface)
<             return -ENODEV;
1218a1213
>     acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress);
1267c1262
<                      usb_rcvintpipe(usb_dev, epread->bEndpointAddress),
---
>                      acm->rx_endpoint,
1274c1269
<                       usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress),
---
>                       acm->rx_endpoint,
1366c1361,1375

---
> #if 1 //Added by Quectel
>     //For USB Auto Suspend
>     if((usb_dev->descriptor.idVendor == 0x1519) && (usb_dev->descriptor.idProduct == 0x0020))
>     {
>         pm_runtime_set_autosuspend_delay(&usb_dev->dev, 3000);
>         usb_enable_autosuspend(usb_dev);
>     }
> #endif 
> #if 1 //Added by Quectel
>     //For USB Remote Wakeup
>     if ((usb_dev->descriptor.idVendor == 0x1519) && (usb_dev->descriptor.idProduct == 0x0020))
>     {
>         device_init_wakeup(&usb_dev->dev, 1); //usb remote wakeup
>     }
> #endif

启动log:

 

启动和创建链接:

~ # quectel-CM -s  cnet&
[01-01_00:00:41:440] WCDMA&LTE_QConnectManager_Linux&Android_V1.1.34
[01-01_00:00:41:440] quectel-CM profile[1] = cnet///0, pincode = (null)
[01-01_00:00:41:440] Find /sys/bus/usb/devices/1-2 idVendor=2c7c idProduct=0125
[01-01_00:00:41:440] Find /sys/bus/usb/devices/1-2:1.4/net/wwan0
[01-01_00:00:41:440] Find usbnet_adapter = wwan0
[01-01_00:00:41:480] Find /sys/bus/usb/devices/1-2:1.4/usbmisc/cdc-wdm0
[01-01_00:00:41:480] Find qmichannel = /dev/cdc-wdm0
[01-01_00:00:41:520] cdc_wdm_fd = 7
[01-01_00:00:41:610] Get clientWDS = 1
[01-01_00:00:41:640] Get clientDMS = 1
[01-01_00:00:41:710] Get clientNAS = 2
[01-01_00:00:41:740] Get clientUIM = 1
[01-01_00:00:41:770] Get clientWDA = 1
[01-01_00:00:41:800] requestBaseBandVersion EC20CEFILGR06A01M1G
[01-01_00:00:41:930] requestGetSIMStatus SIMStatus: SIM_READY
[01-01_00:00:41:930] requestSetProfile[1] cnet///0
[01-01_00:00:42:000] requestGetProfile[1] cnet///0
[01-01_00:00:42:030] requestRegistrationState2 MCC: 460, MNC: 1, PS: Attached, DataCap: LTE
[01-01_00:00:42:060] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
[01-01_00:00:42:140] requestRegistrationState2 MCC: 460, MNC: 1, PS: Attached, DataCap: LTE
[01-01_00:00:42:350] requestSetupDataCall WdsConnectionIPv4Handle: 0x86aedde0
[01-01_00:00:42:410] requestQueryDataCall IPv4ConnectionStatus: CONNECTED
[01-01_00:00:42:480] ifconfig wwan0 up
[01-01_00:00:42:590] busybox udhcpc -f -n -q -t 5 -i wwan0
[01-01_00:00:42:680] udhcpc (v1.22.1) started
[01-01_00:00:42:810] Sending discover...
ping: bad address 'www.baidu.com'
[01-01_00:00:42:870] Sending select for 10.234.194.25...
[01-01_00:00:42:950] Lease of 10.234.194.25 obtained, lease time 7200
[01-01_00:00:43:060] deleting routers
route: ioctl 0x890c failed: No such process
[01-01_00:00:43:170] adding dns 120.80.80.80
[01-01_00:00:43:170] adding dns 221.5.88.88

 

至此,可以正常工作啦。

 

ping www.baidu.com测试一下

打完收工!

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值