cdc_mbim.c (19736B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 2012 Smith Micro Software, Inc. 4 * Copyright (c) 2012 Bjørn Mork <bjorn@mork.no> 5 * 6 * This driver is based on and reuse most of cdc_ncm, which is 7 * Copyright (C) ST-Ericsson 2010-2012 8 */ 9 10#include <linux/module.h> 11#include <linux/netdevice.h> 12#include <linux/ethtool.h> 13#include <linux/if_vlan.h> 14#include <linux/ip.h> 15#include <linux/mii.h> 16#include <linux/usb.h> 17#include <linux/usb/cdc.h> 18#include <linux/usb/usbnet.h> 19#include <linux/usb/cdc-wdm.h> 20#include <linux/usb/cdc_ncm.h> 21#include <net/ipv6.h> 22#include <net/addrconf.h> 23#include <net/ipv6_stubs.h> 24#include <net/ndisc.h> 25 26/* alternative VLAN for IP session 0 if not untagged */ 27#define MBIM_IPS0_VID 4094 28 29/* driver specific data - must match cdc_ncm usage */ 30struct cdc_mbim_state { 31 struct cdc_ncm_ctx *ctx; 32 atomic_t pmcount; 33 struct usb_driver *subdriver; 34 unsigned long _unused; 35 unsigned long flags; 36}; 37 38/* flags for the cdc_mbim_state.flags field */ 39enum cdc_mbim_flags { 40 FLAG_IPS0_VLAN = 1 << 0, /* IP session 0 is tagged */ 41}; 42 43/* using a counter to merge subdriver requests with our own into a combined state */ 44static int cdc_mbim_manage_power(struct usbnet *dev, int on) 45{ 46 struct cdc_mbim_state *info = (void *)&dev->data; 47 int rv = 0; 48 49 dev_dbg(&dev->intf->dev, "%s() pmcount=%d, on=%d\n", __func__, atomic_read(&info->pmcount), on); 50 51 if ((on && atomic_add_return(1, &info->pmcount) == 1) || (!on && atomic_dec_and_test(&info->pmcount))) { 52 /* need autopm_get/put here to ensure the usbcore sees the new value */ 53 rv = usb_autopm_get_interface(dev->intf); 54 dev->intf->needs_remote_wakeup = on; 55 if (!rv) 56 usb_autopm_put_interface(dev->intf); 57 } 58 return 0; 59} 60 61static int cdc_mbim_wdm_manage_power(struct usb_interface *intf, int status) 62{ 63 struct usbnet *dev = usb_get_intfdata(intf); 64 65 /* can be called while disconnecting */ 66 if (!dev) 67 return 0; 68 69 return cdc_mbim_manage_power(dev, status); 70} 71 72static int cdc_mbim_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid) 73{ 74 struct usbnet *dev = netdev_priv(netdev); 75 struct cdc_mbim_state *info = (void *)&dev->data; 76 77 /* creation of this VLAN is a request to tag IP session 0 */ 78 if (vid == MBIM_IPS0_VID) 79 info->flags |= FLAG_IPS0_VLAN; 80 else 81 if (vid >= 512) /* we don't map these to MBIM session */ 82 return -EINVAL; 83 return 0; 84} 85 86static int cdc_mbim_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid) 87{ 88 struct usbnet *dev = netdev_priv(netdev); 89 struct cdc_mbim_state *info = (void *)&dev->data; 90 91 /* this is a request for an untagged IP session 0 */ 92 if (vid == MBIM_IPS0_VID) 93 info->flags &= ~FLAG_IPS0_VLAN; 94 return 0; 95} 96 97static const struct net_device_ops cdc_mbim_netdev_ops = { 98 .ndo_open = usbnet_open, 99 .ndo_stop = usbnet_stop, 100 .ndo_start_xmit = usbnet_start_xmit, 101 .ndo_tx_timeout = usbnet_tx_timeout, 102 .ndo_get_stats64 = dev_get_tstats64, 103 .ndo_change_mtu = cdc_ncm_change_mtu, 104 .ndo_set_mac_address = eth_mac_addr, 105 .ndo_validate_addr = eth_validate_addr, 106 .ndo_vlan_rx_add_vid = cdc_mbim_rx_add_vid, 107 .ndo_vlan_rx_kill_vid = cdc_mbim_rx_kill_vid, 108}; 109 110/* Change the control interface altsetting and update the .driver_info 111 * pointer if the matching entry after changing class codes points to 112 * a different struct 113 */ 114static int cdc_mbim_set_ctrlalt(struct usbnet *dev, struct usb_interface *intf, u8 alt) 115{ 116 struct usb_driver *driver = to_usb_driver(intf->dev.driver); 117 const struct usb_device_id *id; 118 struct driver_info *info; 119 int ret; 120 121 ret = usb_set_interface(dev->udev, 122 intf->cur_altsetting->desc.bInterfaceNumber, 123 alt); 124 if (ret) 125 return ret; 126 127 id = usb_match_id(intf, driver->id_table); 128 if (!id) 129 return -ENODEV; 130 131 info = (struct driver_info *)id->driver_info; 132 if (info != dev->driver_info) { 133 dev_dbg(&intf->dev, "driver_info updated to '%s'\n", 134 info->description); 135 dev->driver_info = info; 136 } 137 return 0; 138} 139 140static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf) 141{ 142 struct cdc_ncm_ctx *ctx; 143 struct usb_driver *subdriver = ERR_PTR(-ENODEV); 144 int ret = -ENODEV; 145 u8 data_altsetting = 1; 146 struct cdc_mbim_state *info = (void *)&dev->data; 147 148 /* should we change control altsetting on a NCM/MBIM function? */ 149 if (cdc_ncm_select_altsetting(intf) == CDC_NCM_COMM_ALTSETTING_MBIM) { 150 data_altsetting = CDC_NCM_DATA_ALTSETTING_MBIM; 151 ret = cdc_mbim_set_ctrlalt(dev, intf, CDC_NCM_COMM_ALTSETTING_MBIM); 152 if (ret) 153 goto err; 154 ret = -ENODEV; 155 } 156 157 /* we will hit this for NCM/MBIM functions if prefer_mbim is false */ 158 if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting)) 159 goto err; 160 161 ret = cdc_ncm_bind_common(dev, intf, data_altsetting, dev->driver_info->data); 162 if (ret) 163 goto err; 164 165 ctx = info->ctx; 166 167 /* The MBIM descriptor and the status endpoint are required */ 168 if (ctx->mbim_desc && dev->status) 169 subdriver = usb_cdc_wdm_register(ctx->control, 170 &dev->status->desc, 171 le16_to_cpu(ctx->mbim_desc->wMaxControlMessage), 172 WWAN_PORT_MBIM, 173 cdc_mbim_wdm_manage_power); 174 if (IS_ERR(subdriver)) { 175 ret = PTR_ERR(subdriver); 176 cdc_ncm_unbind(dev, intf); 177 goto err; 178 } 179 180 /* can't let usbnet use the interrupt endpoint */ 181 dev->status = NULL; 182 info->subdriver = subdriver; 183 184 /* MBIM cannot do ARP */ 185 dev->net->flags |= IFF_NOARP; 186 187 /* no need to put the VLAN tci in the packet headers */ 188 dev->net->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_FILTER; 189 190 /* monitor VLAN additions and removals */ 191 dev->net->netdev_ops = &cdc_mbim_netdev_ops; 192err: 193 return ret; 194} 195 196static void cdc_mbim_unbind(struct usbnet *dev, struct usb_interface *intf) 197{ 198 struct cdc_mbim_state *info = (void *)&dev->data; 199 struct cdc_ncm_ctx *ctx = info->ctx; 200 201 /* disconnect subdriver from control interface */ 202 if (info->subdriver && info->subdriver->disconnect) 203 info->subdriver->disconnect(ctx->control); 204 info->subdriver = NULL; 205 206 /* let NCM unbind clean up both control and data interface */ 207 cdc_ncm_unbind(dev, intf); 208} 209 210/* verify that the ethernet protocol is IPv4 or IPv6 */ 211static bool is_ip_proto(__be16 proto) 212{ 213 switch (proto) { 214 case htons(ETH_P_IP): 215 case htons(ETH_P_IPV6): 216 return true; 217 } 218 return false; 219} 220 221static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) 222{ 223 struct sk_buff *skb_out; 224 struct cdc_mbim_state *info = (void *)&dev->data; 225 struct cdc_ncm_ctx *ctx = info->ctx; 226 __le32 sign = cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN); 227 u16 tci = 0; 228 bool is_ip; 229 u8 *c; 230 231 if (!ctx) 232 goto error; 233 234 if (skb) { 235 if (skb->len <= ETH_HLEN) 236 goto error; 237 238 /* Some applications using e.g. packet sockets will 239 * bypass the VLAN acceleration and create tagged 240 * ethernet frames directly. We primarily look for 241 * the accelerated out-of-band tag, but fall back if 242 * required 243 */ 244 skb_reset_mac_header(skb); 245 if (vlan_get_tag(skb, &tci) < 0 && skb->len > VLAN_ETH_HLEN && 246 __vlan_get_tag(skb, &tci) == 0) { 247 is_ip = is_ip_proto(vlan_eth_hdr(skb)->h_vlan_encapsulated_proto); 248 skb_pull(skb, VLAN_ETH_HLEN); 249 } else { 250 is_ip = is_ip_proto(eth_hdr(skb)->h_proto); 251 skb_pull(skb, ETH_HLEN); 252 } 253 254 /* Is IP session <0> tagged too? */ 255 if (info->flags & FLAG_IPS0_VLAN) { 256 /* drop all untagged packets */ 257 if (!tci) 258 goto error; 259 /* map MBIM_IPS0_VID to IPS<0> */ 260 if (tci == MBIM_IPS0_VID) 261 tci = 0; 262 } 263 264 /* mapping VLANs to MBIM sessions: 265 * no tag => IPS session <0> if !FLAG_IPS0_VLAN 266 * 1 - 255 => IPS session <vlanid> 267 * 256 - 511 => DSS session <vlanid - 256> 268 * 512 - 4093 => unsupported, drop 269 * 4094 => IPS session <0> if FLAG_IPS0_VLAN 270 */ 271 272 switch (tci & 0x0f00) { 273 case 0x0000: /* VLAN ID 0 - 255 */ 274 if (!is_ip) 275 goto error; 276 c = (u8 *)&sign; 277 c[3] = tci; 278 break; 279 case 0x0100: /* VLAN ID 256 - 511 */ 280 if (is_ip) 281 goto error; 282 sign = cpu_to_le32(USB_CDC_MBIM_NDP16_DSS_SIGN); 283 c = (u8 *)&sign; 284 c[3] = tci; 285 break; 286 default: 287 netif_err(dev, tx_err, dev->net, 288 "unsupported tci=0x%04x\n", tci); 289 goto error; 290 } 291 } 292 293 spin_lock_bh(&ctx->mtx); 294 skb_out = cdc_ncm_fill_tx_frame(dev, skb, sign); 295 spin_unlock_bh(&ctx->mtx); 296 return skb_out; 297 298error: 299 if (skb) 300 dev_kfree_skb_any(skb); 301 302 return NULL; 303} 304 305/* Some devices are known to send Neighbor Solicitation messages and 306 * require Neighbor Advertisement replies. The IPv6 core will not 307 * respond since IFF_NOARP is set, so we must handle them ourselves. 308 */ 309static void do_neigh_solicit(struct usbnet *dev, u8 *buf, u16 tci) 310{ 311 struct ipv6hdr *iph = (void *)buf; 312 struct nd_msg *msg = (void *)(iph + 1); 313 struct net_device *netdev; 314 struct inet6_dev *in6_dev; 315 bool is_router; 316 317 /* we'll only respond to requests from unicast addresses to 318 * our solicited node addresses. 319 */ 320 if (!ipv6_addr_is_solict_mult(&iph->daddr) || 321 !(ipv6_addr_type(&iph->saddr) & IPV6_ADDR_UNICAST)) 322 return; 323 324 /* need to send the NA on the VLAN dev, if any */ 325 rcu_read_lock(); 326 if (tci) { 327 netdev = __vlan_find_dev_deep_rcu(dev->net, htons(ETH_P_8021Q), 328 tci); 329 if (!netdev) { 330 rcu_read_unlock(); 331 return; 332 } 333 } else { 334 netdev = dev->net; 335 } 336 dev_hold(netdev); 337 rcu_read_unlock(); 338 339 in6_dev = in6_dev_get(netdev); 340 if (!in6_dev) 341 goto out; 342 is_router = !!in6_dev->cnf.forwarding; 343 in6_dev_put(in6_dev); 344 345 /* ipv6_stub != NULL if in6_dev_get returned an inet6_dev */ 346 ipv6_stub->ndisc_send_na(netdev, &iph->saddr, &msg->target, 347 is_router /* router */, 348 true /* solicited */, 349 false /* override */, 350 true /* inc_opt */); 351out: 352 dev_put(netdev); 353} 354 355static bool is_neigh_solicit(u8 *buf, size_t len) 356{ 357 struct ipv6hdr *iph = (void *)buf; 358 struct nd_msg *msg = (void *)(iph + 1); 359 360 return (len >= sizeof(struct ipv6hdr) + sizeof(struct nd_msg) && 361 iph->nexthdr == IPPROTO_ICMPV6 && 362 msg->icmph.icmp6_code == 0 && 363 msg->icmph.icmp6_type == NDISC_NEIGHBOUR_SOLICITATION); 364} 365 366 367static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_t len, u16 tci) 368{ 369 __be16 proto = htons(ETH_P_802_3); 370 struct sk_buff *skb = NULL; 371 372 if (tci < 256 || tci == MBIM_IPS0_VID) { /* IPS session? */ 373 if (len < sizeof(struct iphdr)) 374 goto err; 375 376 switch (*buf & 0xf0) { 377 case 0x40: 378 proto = htons(ETH_P_IP); 379 break; 380 case 0x60: 381 if (is_neigh_solicit(buf, len)) 382 do_neigh_solicit(dev, buf, tci); 383 proto = htons(ETH_P_IPV6); 384 break; 385 default: 386 goto err; 387 } 388 } 389 390 skb = netdev_alloc_skb_ip_align(dev->net, len + ETH_HLEN); 391 if (!skb) 392 goto err; 393 394 /* add an ethernet header */ 395 skb_put(skb, ETH_HLEN); 396 skb_reset_mac_header(skb); 397 eth_hdr(skb)->h_proto = proto; 398 eth_zero_addr(eth_hdr(skb)->h_source); 399 memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN); 400 401 /* add datagram */ 402 skb_put_data(skb, buf, len); 403 404 /* map MBIM session to VLAN */ 405 if (tci) 406 __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), tci); 407err: 408 return skb; 409} 410 411static int cdc_mbim_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in) 412{ 413 struct sk_buff *skb; 414 struct cdc_mbim_state *info = (void *)&dev->data; 415 struct cdc_ncm_ctx *ctx = info->ctx; 416 int len; 417 int nframes; 418 int x; 419 int offset; 420 struct usb_cdc_ncm_ndp16 *ndp16; 421 struct usb_cdc_ncm_dpe16 *dpe16; 422 int ndpoffset; 423 int loopcount = 50; /* arbitrary max preventing infinite loop */ 424 u32 payload = 0; 425 u8 *c; 426 u16 tci; 427 428 ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in); 429 if (ndpoffset < 0) 430 goto error; 431 432next_ndp: 433 nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset); 434 if (nframes < 0) 435 goto error; 436 437 ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset); 438 439 switch (ndp16->dwSignature & cpu_to_le32(0x00ffffff)) { 440 case cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN): 441 c = (u8 *)&ndp16->dwSignature; 442 tci = c[3]; 443 /* tag IPS<0> packets too if MBIM_IPS0_VID exists */ 444 if (!tci && info->flags & FLAG_IPS0_VLAN) 445 tci = MBIM_IPS0_VID; 446 break; 447 case cpu_to_le32(USB_CDC_MBIM_NDP16_DSS_SIGN): 448 c = (u8 *)&ndp16->dwSignature; 449 tci = c[3] + 256; 450 break; 451 default: 452 netif_dbg(dev, rx_err, dev->net, 453 "unsupported NDP signature <0x%08x>\n", 454 le32_to_cpu(ndp16->dwSignature)); 455 goto err_ndp; 456 457 } 458 459 dpe16 = ndp16->dpe16; 460 for (x = 0; x < nframes; x++, dpe16++) { 461 offset = le16_to_cpu(dpe16->wDatagramIndex); 462 len = le16_to_cpu(dpe16->wDatagramLength); 463 464 /* 465 * CDC NCM ch. 3.7 466 * All entries after first NULL entry are to be ignored 467 */ 468 if ((offset == 0) || (len == 0)) { 469 if (!x) 470 goto err_ndp; /* empty NTB */ 471 break; 472 } 473 474 /* sanity checking */ 475 if (((offset + len) > skb_in->len) || (len > ctx->rx_max)) { 476 netif_dbg(dev, rx_err, dev->net, 477 "invalid frame detected (ignored) offset[%u]=%u, length=%u, skb=%p\n", 478 x, offset, len, skb_in); 479 if (!x) 480 goto err_ndp; 481 break; 482 } else { 483 skb = cdc_mbim_process_dgram(dev, skb_in->data + offset, len, tci); 484 if (!skb) 485 goto error; 486 usbnet_skb_return(dev, skb); 487 payload += len; /* count payload bytes in this NTB */ 488 } 489 } 490err_ndp: 491 /* are there more NDPs to process? */ 492 ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex); 493 if (ndpoffset && loopcount--) 494 goto next_ndp; 495 496 /* update stats */ 497 ctx->rx_overhead += skb_in->len - payload; 498 ctx->rx_ntbs++; 499 500 return 1; 501error: 502 return 0; 503} 504 505static int cdc_mbim_suspend(struct usb_interface *intf, pm_message_t message) 506{ 507 int ret = -ENODEV; 508 struct usbnet *dev = usb_get_intfdata(intf); 509 struct cdc_mbim_state *info = (void *)&dev->data; 510 struct cdc_ncm_ctx *ctx = info->ctx; 511 512 if (!ctx) 513 goto error; 514 515 /* 516 * Both usbnet_suspend() and subdriver->suspend() MUST return 0 517 * in system sleep context, otherwise, the resume callback has 518 * to recover device from previous suspend failure. 519 */ 520 ret = usbnet_suspend(intf, message); 521 if (ret < 0) 522 goto error; 523 524 if (intf == ctx->control && info->subdriver && info->subdriver->suspend) 525 ret = info->subdriver->suspend(intf, message); 526 if (ret < 0) 527 usbnet_resume(intf); 528 529error: 530 return ret; 531} 532 533static int cdc_mbim_resume(struct usb_interface *intf) 534{ 535 int ret = 0; 536 struct usbnet *dev = usb_get_intfdata(intf); 537 struct cdc_mbim_state *info = (void *)&dev->data; 538 struct cdc_ncm_ctx *ctx = info->ctx; 539 bool callsub = (intf == ctx->control && info->subdriver && info->subdriver->resume); 540 541 if (callsub) 542 ret = info->subdriver->resume(intf); 543 if (ret < 0) 544 goto err; 545 ret = usbnet_resume(intf); 546 if (ret < 0 && callsub) 547 info->subdriver->suspend(intf, PMSG_SUSPEND); 548err: 549 return ret; 550} 551 552static const struct driver_info cdc_mbim_info = { 553 .description = "CDC MBIM", 554 .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN, 555 .bind = cdc_mbim_bind, 556 .unbind = cdc_mbim_unbind, 557 .manage_power = cdc_mbim_manage_power, 558 .rx_fixup = cdc_mbim_rx_fixup, 559 .tx_fixup = cdc_mbim_tx_fixup, 560}; 561 562/* MBIM and NCM devices should not need a ZLP after NTBs with 563 * dwNtbOutMaxSize length. Nevertheless, a number of devices from 564 * different vendor IDs will fail unless we send ZLPs, forcing us 565 * to make this the default. 566 * 567 * This default may cause a performance penalty for spec conforming 568 * devices wanting to take advantage of optimizations possible without 569 * ZLPs. A whitelist is added in an attempt to avoid this for devices 570 * known to conform to the MBIM specification. 571 * 572 * All known devices supporting NCM compatibility mode are also 573 * conforming to the NCM and MBIM specifications. For this reason, the 574 * NCM subclass entry is also in the ZLP whitelist. 575 */ 576static const struct driver_info cdc_mbim_info_zlp = { 577 .description = "CDC MBIM", 578 .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN | FLAG_SEND_ZLP, 579 .bind = cdc_mbim_bind, 580 .unbind = cdc_mbim_unbind, 581 .manage_power = cdc_mbim_manage_power, 582 .rx_fixup = cdc_mbim_rx_fixup, 583 .tx_fixup = cdc_mbim_tx_fixup, 584}; 585 586/* The spefication explicitly allows NDPs to be placed anywhere in the 587 * frame, but some devices fail unless the NDP is placed after the IP 588 * packets. Using the CDC_NCM_FLAG_NDP_TO_END flags to force this 589 * behaviour. 590 * 591 * Note: The current implementation of this feature restricts each NTB 592 * to a single NDP, implying that multiplexed sessions cannot share an 593 * NTB. This might affect performance for multiplexed sessions. 594 */ 595static const struct driver_info cdc_mbim_info_ndp_to_end = { 596 .description = "CDC MBIM", 597 .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN, 598 .bind = cdc_mbim_bind, 599 .unbind = cdc_mbim_unbind, 600 .manage_power = cdc_mbim_manage_power, 601 .rx_fixup = cdc_mbim_rx_fixup, 602 .tx_fixup = cdc_mbim_tx_fixup, 603 .data = CDC_NCM_FLAG_NDP_TO_END, 604}; 605 606/* Some modems (e.g. Telit LE922A6) do not work properly with altsetting 607 * toggle done in cdc_ncm_bind_common. CDC_MBIM_FLAG_AVOID_ALTSETTING_TOGGLE 608 * flag is used to avoid this procedure. 609 */ 610static const struct driver_info cdc_mbim_info_avoid_altsetting_toggle = { 611 .description = "CDC MBIM", 612 .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN | FLAG_SEND_ZLP, 613 .bind = cdc_mbim_bind, 614 .unbind = cdc_mbim_unbind, 615 .manage_power = cdc_mbim_manage_power, 616 .rx_fixup = cdc_mbim_rx_fixup, 617 .tx_fixup = cdc_mbim_tx_fixup, 618 .data = CDC_MBIM_FLAG_AVOID_ALTSETTING_TOGGLE, 619}; 620 621static const struct usb_device_id mbim_devs[] = { 622 /* This duplicate NCM entry is intentional. MBIM devices can 623 * be disguised as NCM by default, and this is necessary to 624 * allow us to bind the correct driver_info to such devices. 625 * 626 * bind() will sort out this for us, selecting the correct 627 * entry and reject the other 628 */ 629 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), 630 .driver_info = (unsigned long)&cdc_mbim_info, 631 }, 632 /* ZLP conformance whitelist: All Ericsson MBIM devices */ 633 { USB_VENDOR_AND_INTERFACE_INFO(0x0bdb, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), 634 .driver_info = (unsigned long)&cdc_mbim_info, 635 }, 636 637 /* Some Huawei devices, ME906s-158 (12d1:15c1) and E3372 638 * (12d1:157d), are known to fail unless the NDP is placed 639 * after the IP packets. Applying the quirk to all Huawei 640 * devices is broader than necessary, but harmless. 641 */ 642 { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), 643 .driver_info = (unsigned long)&cdc_mbim_info_ndp_to_end, 644 }, 645 646 /* The HP lt4132 (03f0:a31d) is a rebranded Huawei ME906s-158, 647 * therefore it too requires the above "NDP to end" quirk. 648 */ 649 { USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0xa31d, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), 650 .driver_info = (unsigned long)&cdc_mbim_info_ndp_to_end, 651 }, 652 653 /* Telit LE922A6 in MBIM composition */ 654 { USB_DEVICE_AND_INTERFACE_INFO(0x1bc7, 0x1041, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), 655 .driver_info = (unsigned long)&cdc_mbim_info_avoid_altsetting_toggle, 656 }, 657 658 /* Telit LN920 */ 659 { USB_DEVICE_AND_INTERFACE_INFO(0x1bc7, 0x1061, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), 660 .driver_info = (unsigned long)&cdc_mbim_info_avoid_altsetting_toggle, 661 }, 662 663 /* Telit FN990 */ 664 { USB_DEVICE_AND_INTERFACE_INFO(0x1bc7, 0x1071, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), 665 .driver_info = (unsigned long)&cdc_mbim_info_avoid_altsetting_toggle, 666 }, 667 668 /* default entry */ 669 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), 670 .driver_info = (unsigned long)&cdc_mbim_info_zlp, 671 }, 672 { 673 }, 674}; 675MODULE_DEVICE_TABLE(usb, mbim_devs); 676 677static struct usb_driver cdc_mbim_driver = { 678 .name = "cdc_mbim", 679 .id_table = mbim_devs, 680 .probe = usbnet_probe, 681 .disconnect = usbnet_disconnect, 682 .suspend = cdc_mbim_suspend, 683 .resume = cdc_mbim_resume, 684 .reset_resume = cdc_mbim_resume, 685 .supports_autosuspend = 1, 686 .disable_hub_initiated_lpm = 1, 687}; 688module_usb_driver(cdc_mbim_driver); 689 690MODULE_AUTHOR("Greg Suarez <gsuarez@smithmicro.com>"); 691MODULE_AUTHOR("Bjørn Mork <bjorn@mork.no>"); 692MODULE_DESCRIPTION("USB CDC MBIM host driver"); 693MODULE_LICENSE("GPL");