1 /* 2 * Copyright (c) 2012 Bjørn Mork <bjorn@mork.no> 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * version 2 as published by the Free Software Foundation. 7 */ 8 9 #include <linux/module.h> 10 #include <linux/netdevice.h> 11 #include <linux/ethtool.h> 12 #include <linux/mii.h> 13 #include <linux/usb.h> 14 #include <linux/usb/cdc.h> 15 #include <linux/usb/usbnet.h> 16 #include <linux/usb/cdc-wdm.h> 17 18 /* The name of the CDC Device Management driver */ 19 #define DM_DRIVER "cdc_wdm" 20 21 /* 22 * This driver supports wwan (3G/LTE/?) devices using a vendor 23 * specific management protocol called Qualcomm MSM Interface (QMI) - 24 * in addition to the more common AT commands over serial interface 25 * management 26 * 27 * QMI is wrapped in CDC, using CDC encapsulated commands on the 28 * control ("master") interface of a two-interface CDC Union 29 * resembling standard CDC ECM. The devices do not use the control 30 * interface for any other CDC messages. Most likely because the 31 * management protocol is used in place of the standard CDC 32 * notifications NOTIFY_NETWORK_CONNECTION and NOTIFY_SPEED_CHANGE 33 * 34 * Handling a protocol like QMI is out of the scope for any driver. 35 * It can be exported as a character device using the cdc-wdm driver, 36 * which will enable userspace applications ("modem managers") to 37 * handle it. This may be required to use the network interface 38 * provided by the driver. 39 * 40 * These devices may alternatively/additionally be configured using AT 41 * commands on any of the serial interfaces driven by the option driver 42 * 43 * This driver binds only to the data ("slave") interface to enable 44 * the cdc-wdm driver to bind to the control interface. It still 45 * parses the CDC functional descriptors on the control interface to 46 * a) verify that this is indeed a handled interface (CDC Union 47 * header lists it as slave) 48 * b) get MAC address and other ethernet config from the CDC Ethernet 49 * header 50 * c) enable user bind requests against the control interface, which 51 * is the common way to bind to CDC Ethernet Control Model type 52 * interfaces 53 * d) provide a hint to the user about which interface is the 54 * corresponding management interface 55 */ 56 57 static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf) 58 { 59 int status = -1; 60 struct usb_interface *control = NULL; 61 u8 *buf = intf->cur_altsetting->extra; 62 int len = intf->cur_altsetting->extralen; 63 struct usb_interface_descriptor *desc = &intf->cur_altsetting->desc; 64 struct usb_cdc_union_desc *cdc_union = NULL; 65 struct usb_cdc_ether_desc *cdc_ether = NULL; 66 u32 required = 1 << USB_CDC_HEADER_TYPE | 1 << USB_CDC_UNION_TYPE; 67 u32 found = 0; 68 atomic_t *pmcount = (void *)&dev->data[1]; 69 70 atomic_set(pmcount, 0); 71 72 /* 73 * assume a data interface has no additional descriptors and 74 * that the control and data interface are numbered 75 * consecutively - this holds for the Huawei device at least 76 */ 77 if (len == 0 && desc->bInterfaceNumber > 0) { 78 control = usb_ifnum_to_if(dev->udev, desc->bInterfaceNumber - 1); 79 if (!control) 80 goto err; 81 82 buf = control->cur_altsetting->extra; 83 len = control->cur_altsetting->extralen; 84 dev_dbg(&intf->dev, "guessing \"control\" => %s, \"data\" => this\n", 85 dev_name(&control->dev)); 86 } 87 88 while (len > 3) { 89 struct usb_descriptor_header *h = (void *)buf; 90 91 /* ignore any misplaced descriptors */ 92 if (h->bDescriptorType != USB_DT_CS_INTERFACE) 93 goto next_desc; 94 95 /* buf[2] is CDC descriptor subtype */ 96 switch (buf[2]) { 97 case USB_CDC_HEADER_TYPE: 98 if (found & 1 << USB_CDC_HEADER_TYPE) { 99 dev_dbg(&intf->dev, "extra CDC header\n"); 100 goto err; 101 } 102 if (h->bLength != sizeof(struct usb_cdc_header_desc)) { 103 dev_dbg(&intf->dev, "CDC header len %u\n", h->bLength); 104 goto err; 105 } 106 break; 107 case USB_CDC_UNION_TYPE: 108 if (found & 1 << USB_CDC_UNION_TYPE) { 109 dev_dbg(&intf->dev, "extra CDC union\n"); 110 goto err; 111 } 112 if (h->bLength != sizeof(struct usb_cdc_union_desc)) { 113 dev_dbg(&intf->dev, "CDC union len %u\n", h->bLength); 114 goto err; 115 } 116 cdc_union = (struct usb_cdc_union_desc *)buf; 117 break; 118 case USB_CDC_ETHERNET_TYPE: 119 if (found & 1 << USB_CDC_ETHERNET_TYPE) { 120 dev_dbg(&intf->dev, "extra CDC ether\n"); 121 goto err; 122 } 123 if (h->bLength != sizeof(struct usb_cdc_ether_desc)) { 124 dev_dbg(&intf->dev, "CDC ether len %u\n", h->bLength); 125 goto err; 126 } 127 cdc_ether = (struct usb_cdc_ether_desc *)buf; 128 break; 129 } 130 131 /* 132 * Remember which CDC functional descriptors we've seen. Works 133 * for all types we care about, of which USB_CDC_ETHERNET_TYPE 134 * (0x0f) is the highest numbered 135 */ 136 if (buf[2] < 32) 137 found |= 1 << buf[2]; 138 139 next_desc: 140 len -= h->bLength; 141 buf += h->bLength; 142 } 143 144 /* did we find all the required ones? */ 145 if ((found & required) != required) { 146 dev_err(&intf->dev, "CDC functional descriptors missing\n"); 147 goto err; 148 } 149 150 /* give the user a helpful hint if trying to bind to the wrong interface */ 151 if (cdc_union && desc->bInterfaceNumber == cdc_union->bMasterInterface0) { 152 dev_err(&intf->dev, "leaving \"control\" interface for " DM_DRIVER " - try binding to %s instead!\n", 153 dev_name(&usb_ifnum_to_if(dev->udev, cdc_union->bSlaveInterface0)->dev)); 154 goto err; 155 } 156 157 /* errors aren't fatal - we can live with the dynamic address */ 158 if (cdc_ether) { 159 dev->hard_mtu = le16_to_cpu(cdc_ether->wMaxSegmentSize); 160 usbnet_get_ethernet_addr(dev, cdc_ether->iMACAddress); 161 } 162 163 /* success! point the user to the management interface */ 164 if (control) 165 dev_info(&intf->dev, "Use \"" DM_DRIVER "\" for QMI interface %s\n", 166 dev_name(&control->dev)); 167 168 /* XXX: add a sysfs symlink somewhere to help management applications find it? */ 169 170 /* collect bulk endpoints now that we know intf == "data" interface */ 171 status = usbnet_get_endpoints(dev, intf); 172 173 err: 174 return status; 175 } 176 177 /* using a counter to merge subdriver requests with our own into a combined state */ 178 static int qmi_wwan_manage_power(struct usbnet *dev, int on) 179 { 180 atomic_t *pmcount = (void *)&dev->data[1]; 181 int rv = 0; 182 183 dev_dbg(&dev->intf->dev, "%s() pmcount=%d, on=%d\n", __func__, atomic_read(pmcount), on); 184 185 if ((on && atomic_add_return(1, pmcount) == 1) || (!on && atomic_dec_and_test(pmcount))) { 186 /* need autopm_get/put here to ensure the usbcore sees the new value */ 187 rv = usb_autopm_get_interface(dev->intf); 188 if (rv < 0) 189 goto err; 190 dev->intf->needs_remote_wakeup = on; 191 usb_autopm_put_interface(dev->intf); 192 } 193 err: 194 return rv; 195 } 196 197 static int qmi_wwan_cdc_wdm_manage_power(struct usb_interface *intf, int on) 198 { 199 struct usbnet *dev = usb_get_intfdata(intf); 200 return qmi_wwan_manage_power(dev, on); 201 } 202 203 /* Some devices combine the "control" and "data" functions into a 204 * single interface with all three endpoints: interrupt + bulk in and 205 * out 206 * 207 * Setting up cdc-wdm as a subdriver owning the interrupt endpoint 208 * will let it provide userspace access to the encapsulated QMI 209 * protocol without interfering with the usbnet operations. 210 */ 211 static int qmi_wwan_bind_shared(struct usbnet *dev, struct usb_interface *intf) 212 { 213 int rv; 214 struct usb_driver *subdriver = NULL; 215 atomic_t *pmcount = (void *)&dev->data[1]; 216 217 /* ZTE makes devices where the interface descriptors and endpoint 218 * configurations of two or more interfaces are identical, even 219 * though the functions are completely different. If set, then 220 * driver_info->data is a bitmap of acceptable interface numbers 221 * allowing us to bind to one such interface without binding to 222 * all of them 223 */ 224 if (dev->driver_info->data && 225 !test_bit(intf->cur_altsetting->desc.bInterfaceNumber, &dev->driver_info->data)) { 226 dev_info(&intf->dev, "not on our whitelist - ignored"); 227 rv = -ENODEV; 228 goto err; 229 } 230 231 atomic_set(pmcount, 0); 232 233 /* collect all three endpoints */ 234 rv = usbnet_get_endpoints(dev, intf); 235 if (rv < 0) 236 goto err; 237 238 /* require interrupt endpoint for subdriver */ 239 if (!dev->status) { 240 rv = -EINVAL; 241 goto err; 242 } 243 244 subdriver = usb_cdc_wdm_register(intf, &dev->status->desc, 512, &qmi_wwan_cdc_wdm_manage_power); 245 if (IS_ERR(subdriver)) { 246 rv = PTR_ERR(subdriver); 247 goto err; 248 } 249 250 /* can't let usbnet use the interrupt endpoint */ 251 dev->status = NULL; 252 253 /* save subdriver struct for suspend/resume wrappers */ 254 dev->data[0] = (unsigned long)subdriver; 255 256 err: 257 return rv; 258 } 259 260 /* Gobi devices uses identical class/protocol codes for all interfaces regardless 261 * of function. Some of these are CDC ACM like and have the exact same endpoints 262 * we are looking for. This leaves two possible strategies for identifying the 263 * correct interface: 264 * a) hardcoding interface number, or 265 * b) use the fact that the wwan interface is the only one lacking additional 266 * (CDC functional) descriptors 267 * 268 * Let's see if we can get away with the generic b) solution. 269 */ 270 static int qmi_wwan_bind_gobi(struct usbnet *dev, struct usb_interface *intf) 271 { 272 int rv = -EINVAL; 273 274 /* ignore any interface with additional descriptors */ 275 if (intf->cur_altsetting->extralen) 276 goto err; 277 278 rv = qmi_wwan_bind_shared(dev, intf); 279 err: 280 return rv; 281 } 282 283 static void qmi_wwan_unbind_shared(struct usbnet *dev, struct usb_interface *intf) 284 { 285 struct usb_driver *subdriver = (void *)dev->data[0]; 286 287 if (subdriver && subdriver->disconnect) 288 subdriver->disconnect(intf); 289 290 dev->data[0] = (unsigned long)NULL; 291 } 292 293 /* suspend/resume wrappers calling both usbnet and the cdc-wdm 294 * subdriver if present. 295 * 296 * NOTE: cdc-wdm also supports pre/post_reset, but we cannot provide 297 * wrappers for those without adding usbnet reset support first. 298 */ 299 static int qmi_wwan_suspend(struct usb_interface *intf, pm_message_t message) 300 { 301 struct usbnet *dev = usb_get_intfdata(intf); 302 struct usb_driver *subdriver = (void *)dev->data[0]; 303 int ret; 304 305 ret = usbnet_suspend(intf, message); 306 if (ret < 0) 307 goto err; 308 309 if (subdriver && subdriver->suspend) 310 ret = subdriver->suspend(intf, message); 311 if (ret < 0) 312 usbnet_resume(intf); 313 err: 314 return ret; 315 } 316 317 static int qmi_wwan_resume(struct usb_interface *intf) 318 { 319 struct usbnet *dev = usb_get_intfdata(intf); 320 struct usb_driver *subdriver = (void *)dev->data[0]; 321 int ret = 0; 322 323 if (subdriver && subdriver->resume) 324 ret = subdriver->resume(intf); 325 if (ret < 0) 326 goto err; 327 ret = usbnet_resume(intf); 328 if (ret < 0 && subdriver && subdriver->resume && subdriver->suspend) 329 subdriver->suspend(intf, PMSG_SUSPEND); 330 err: 331 return ret; 332 } 333 334 335 static const struct driver_info qmi_wwan_info = { 336 .description = "QMI speaking wwan device", 337 .flags = FLAG_WWAN, 338 .bind = qmi_wwan_bind, 339 .manage_power = qmi_wwan_manage_power, 340 }; 341 342 static const struct driver_info qmi_wwan_shared = { 343 .description = "QMI speaking wwan device with combined interface", 344 .flags = FLAG_WWAN, 345 .bind = qmi_wwan_bind_shared, 346 .unbind = qmi_wwan_unbind_shared, 347 .manage_power = qmi_wwan_manage_power, 348 }; 349 350 static const struct driver_info qmi_wwan_gobi = { 351 .description = "Qualcomm Gobi wwan/QMI device", 352 .flags = FLAG_WWAN, 353 .bind = qmi_wwan_bind_gobi, 354 .unbind = qmi_wwan_unbind_shared, 355 .manage_power = qmi_wwan_manage_power, 356 }; 357 358 /* ZTE suck at making USB descriptors */ 359 static const struct driver_info qmi_wwan_force_int1 = { 360 .description = "Qualcomm WWAN/QMI device", 361 .flags = FLAG_WWAN, 362 .bind = qmi_wwan_bind_shared, 363 .unbind = qmi_wwan_unbind_shared, 364 .manage_power = qmi_wwan_manage_power, 365 .data = BIT(1), /* interface whitelist bitmap */ 366 }; 367 368 static const struct driver_info qmi_wwan_force_int4 = { 369 .description = "Qualcomm WWAN/QMI device", 370 .flags = FLAG_WWAN, 371 .bind = qmi_wwan_bind_shared, 372 .unbind = qmi_wwan_unbind_shared, 373 .manage_power = qmi_wwan_manage_power, 374 .data = BIT(4), /* interface whitelist bitmap */ 375 }; 376 377 /* Sierra Wireless provide equally useless interface descriptors 378 * Devices in QMI mode can be switched between two different 379 * configurations: 380 * a) USB interface #8 is QMI/wwan 381 * b) USB interfaces #8, #19 and #20 are QMI/wwan 382 * 383 * Both configurations provide a number of other interfaces (serial++), 384 * some of which have the same endpoint configuration as we expect, so 385 * a whitelist or blacklist is necessary. 386 * 387 * FIXME: The below whitelist should include BIT(20). It does not 388 * because I cannot get it to work... 389 */ 390 static const struct driver_info qmi_wwan_sierra = { 391 .description = "Sierra Wireless wwan/QMI device", 392 .flags = FLAG_WWAN, 393 .bind = qmi_wwan_bind_gobi, 394 .unbind = qmi_wwan_unbind_shared, 395 .manage_power = qmi_wwan_manage_power, 396 .data = BIT(8) | BIT(19), /* interface whitelist bitmap */ 397 }; 398 399 #define HUAWEI_VENDOR_ID 0x12D1 400 #define QMI_GOBI_DEVICE(vend, prod) \ 401 USB_DEVICE(vend, prod), \ 402 .driver_info = (unsigned long)&qmi_wwan_gobi 403 404 static const struct usb_device_id products[] = { 405 { /* Huawei E392, E398 and possibly others sharing both device id and more... */ 406 .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, 407 .idVendor = HUAWEI_VENDOR_ID, 408 .bInterfaceClass = USB_CLASS_VENDOR_SPEC, 409 .bInterfaceSubClass = 1, 410 .bInterfaceProtocol = 8, /* NOTE: This is the *slave* interface of the CDC Union! */ 411 .driver_info = (unsigned long)&qmi_wwan_info, 412 }, 413 { /* Vodafone/Huawei K5005 (12d1:14c8) and similar modems */ 414 .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, 415 .idVendor = HUAWEI_VENDOR_ID, 416 .bInterfaceClass = USB_CLASS_VENDOR_SPEC, 417 .bInterfaceSubClass = 1, 418 .bInterfaceProtocol = 56, /* NOTE: This is the *slave* interface of the CDC Union! */ 419 .driver_info = (unsigned long)&qmi_wwan_info, 420 }, 421 { /* Huawei E392, E398 and possibly others in "Windows mode" 422 * using a combined control and data interface without any CDC 423 * functional descriptors 424 */ 425 .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, 426 .idVendor = HUAWEI_VENDOR_ID, 427 .bInterfaceClass = USB_CLASS_VENDOR_SPEC, 428 .bInterfaceSubClass = 1, 429 .bInterfaceProtocol = 17, 430 .driver_info = (unsigned long)&qmi_wwan_shared, 431 }, 432 { /* Pantech UML290 */ 433 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, 434 .idVendor = 0x106c, 435 .idProduct = 0x3718, 436 .bInterfaceClass = 0xff, 437 .bInterfaceSubClass = 0xf0, 438 .bInterfaceProtocol = 0xff, 439 .driver_info = (unsigned long)&qmi_wwan_shared, 440 }, 441 { /* ZTE MF820D */ 442 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, 443 .idVendor = 0x19d2, 444 .idProduct = 0x0167, 445 .bInterfaceClass = 0xff, 446 .bInterfaceSubClass = 0xff, 447 .bInterfaceProtocol = 0xff, 448 .driver_info = (unsigned long)&qmi_wwan_force_int4, 449 }, 450 { /* ZTE (Vodafone) K3520-Z */ 451 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, 452 .idVendor = 0x19d2, 453 .idProduct = 0x0055, 454 .bInterfaceClass = 0xff, 455 .bInterfaceSubClass = 0xff, 456 .bInterfaceProtocol = 0xff, 457 .driver_info = (unsigned long)&qmi_wwan_force_int1, 458 }, 459 { /* ZTE (Vodafone) K3565-Z */ 460 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, 461 .idVendor = 0x19d2, 462 .idProduct = 0x0063, 463 .bInterfaceClass = 0xff, 464 .bInterfaceSubClass = 0xff, 465 .bInterfaceProtocol = 0xff, 466 .driver_info = (unsigned long)&qmi_wwan_force_int4, 467 }, 468 { /* ZTE (Vodafone) K3570-Z */ 469 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, 470 .idVendor = 0x19d2, 471 .idProduct = 0x1008, 472 .bInterfaceClass = 0xff, 473 .bInterfaceSubClass = 0xff, 474 .bInterfaceProtocol = 0xff, 475 .driver_info = (unsigned long)&qmi_wwan_force_int4, 476 }, 477 { /* ZTE (Vodafone) K3571-Z */ 478 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, 479 .idVendor = 0x19d2, 480 .idProduct = 0x1010, 481 .bInterfaceClass = 0xff, 482 .bInterfaceSubClass = 0xff, 483 .bInterfaceProtocol = 0xff, 484 .driver_info = (unsigned long)&qmi_wwan_force_int4, 485 }, 486 { /* ZTE (Vodafone) K3765-Z */ 487 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, 488 .idVendor = 0x19d2, 489 .idProduct = 0x2002, 490 .bInterfaceClass = 0xff, 491 .bInterfaceSubClass = 0xff, 492 .bInterfaceProtocol = 0xff, 493 .driver_info = (unsigned long)&qmi_wwan_force_int4, 494 }, 495 { /* ZTE (Vodafone) K4505-Z */ 496 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, 497 .idVendor = 0x19d2, 498 .idProduct = 0x0104, 499 .bInterfaceClass = 0xff, 500 .bInterfaceSubClass = 0xff, 501 .bInterfaceProtocol = 0xff, 502 .driver_info = (unsigned long)&qmi_wwan_force_int4, 503 }, 504 { /* Sierra Wireless MC77xx in QMI mode */ 505 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, 506 .idVendor = 0x1199, 507 .idProduct = 0x68a2, 508 .bInterfaceClass = 0xff, 509 .bInterfaceSubClass = 0xff, 510 .bInterfaceProtocol = 0xff, 511 .driver_info = (unsigned long)&qmi_wwan_sierra, 512 }, 513 {QMI_GOBI_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ 514 {QMI_GOBI_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ 515 {QMI_GOBI_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ 516 {QMI_GOBI_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */ 517 {QMI_GOBI_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */ 518 {QMI_GOBI_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ 519 {QMI_GOBI_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */ 520 {QMI_GOBI_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */ 521 {QMI_GOBI_DEVICE(0x05c6, 0x9001)}, /* Generic Gobi Modem device */ 522 {QMI_GOBI_DEVICE(0x05c6, 0x9002)}, /* Generic Gobi Modem device */ 523 {QMI_GOBI_DEVICE(0x05c6, 0x9202)}, /* Generic Gobi Modem device */ 524 {QMI_GOBI_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */ 525 {QMI_GOBI_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */ 526 {QMI_GOBI_DEVICE(0x05c6, 0x9009)}, /* Generic Gobi Modem device */ 527 {QMI_GOBI_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */ 528 {QMI_GOBI_DEVICE(0x05c6, 0x920b)}, /* Generic Gobi 2000 Modem device */ 529 {QMI_GOBI_DEVICE(0x05c6, 0x9225)}, /* Sony Gobi 2000 Modem device (N0279, VU730) */ 530 {QMI_GOBI_DEVICE(0x05c6, 0x9245)}, /* Samsung Gobi 2000 Modem device (VL176) */ 531 {QMI_GOBI_DEVICE(0x03f0, 0x251d)}, /* HP Gobi 2000 Modem device (VP412) */ 532 {QMI_GOBI_DEVICE(0x05c6, 0x9215)}, /* Acer Gobi 2000 Modem device (VP413) */ 533 {QMI_GOBI_DEVICE(0x05c6, 0x9265)}, /* Asus Gobi 2000 Modem device (VR305) */ 534 {QMI_GOBI_DEVICE(0x05c6, 0x9235)}, /* Top Global Gobi 2000 Modem device (VR306) */ 535 {QMI_GOBI_DEVICE(0x05c6, 0x9275)}, /* iRex Technologies Gobi 2000 Modem device (VR307) */ 536 {QMI_GOBI_DEVICE(0x1199, 0x9001)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ 537 {QMI_GOBI_DEVICE(0x1199, 0x9002)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ 538 {QMI_GOBI_DEVICE(0x1199, 0x9003)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ 539 {QMI_GOBI_DEVICE(0x1199, 0x9004)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ 540 {QMI_GOBI_DEVICE(0x1199, 0x9005)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ 541 {QMI_GOBI_DEVICE(0x1199, 0x9006)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ 542 {QMI_GOBI_DEVICE(0x1199, 0x9007)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ 543 {QMI_GOBI_DEVICE(0x1199, 0x9008)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ 544 {QMI_GOBI_DEVICE(0x1199, 0x9009)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ 545 {QMI_GOBI_DEVICE(0x1199, 0x900a)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ 546 {QMI_GOBI_DEVICE(0x1199, 0x9011)}, /* Sierra Wireless Gobi 2000 Modem device (MC8305) */ 547 {QMI_GOBI_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */ 548 {QMI_GOBI_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */ 549 {QMI_GOBI_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */ 550 {QMI_GOBI_DEVICE(0x1199, 0x9015)}, /* Sierra Wireless Gobi 3000 Modem device */ 551 {QMI_GOBI_DEVICE(0x1199, 0x9019)}, /* Sierra Wireless Gobi 3000 Modem device */ 552 { } /* END */ 553 }; 554 MODULE_DEVICE_TABLE(usb, products); 555 556 static struct usb_driver qmi_wwan_driver = { 557 .name = "qmi_wwan", 558 .id_table = products, 559 .probe = usbnet_probe, 560 .disconnect = usbnet_disconnect, 561 .suspend = qmi_wwan_suspend, 562 .resume = qmi_wwan_resume, 563 .reset_resume = qmi_wwan_resume, 564 .supports_autosuspend = 1, 565 .disable_hub_initiated_lpm = 1, 566 }; 567 568 static int __init qmi_wwan_init(void) 569 { 570 return usb_register(&qmi_wwan_driver); 571 } 572 module_init(qmi_wwan_init); 573 574 static void __exit qmi_wwan_exit(void) 575 { 576 usb_deregister(&qmi_wwan_driver); 577 } 578 module_exit(qmi_wwan_exit); 579 580 MODULE_AUTHOR("Bjørn Mork <bjorn@mork.no>"); 581 MODULE_DESCRIPTION("Qualcomm MSM Interface (QMI) WWAN driver"); 582 MODULE_LICENSE("GPL"); 583