1 /* 2 * Copyright (c) 2012 Smith Micro Software, Inc. 3 * Copyright (c) 2012 Bjørn Mork <bjorn@mork.no> 4 * 5 * This driver is based on and reuse most of cdc_ncm, which is 6 * Copyright (C) ST-Ericsson 2010-2012 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * version 2 as published by the Free Software Foundation. 11 */ 12 13 #include <linux/module.h> 14 #include <linux/netdevice.h> 15 #include <linux/ethtool.h> 16 #include <linux/if_vlan.h> 17 #include <linux/ip.h> 18 #include <linux/mii.h> 19 #include <linux/usb.h> 20 #include <linux/usb/cdc.h> 21 #include <linux/usb/usbnet.h> 22 #include <linux/usb/cdc-wdm.h> 23 #include <linux/usb/cdc_ncm.h> 24 25 /* driver specific data - must match cdc_ncm usage */ 26 struct cdc_mbim_state { 27 struct cdc_ncm_ctx *ctx; 28 atomic_t pmcount; 29 struct usb_driver *subdriver; 30 struct usb_interface *control; 31 struct usb_interface *data; 32 }; 33 34 /* using a counter to merge subdriver requests with our own into a combined state */ 35 static int cdc_mbim_manage_power(struct usbnet *dev, int on) 36 { 37 struct cdc_mbim_state *info = (void *)&dev->data; 38 int rv = 0; 39 40 dev_dbg(&dev->intf->dev, "%s() pmcount=%d, on=%d\n", __func__, atomic_read(&info->pmcount), on); 41 42 if ((on && atomic_add_return(1, &info->pmcount) == 1) || (!on && atomic_dec_and_test(&info->pmcount))) { 43 /* need autopm_get/put here to ensure the usbcore sees the new value */ 44 rv = usb_autopm_get_interface(dev->intf); 45 if (rv < 0) 46 goto err; 47 dev->intf->needs_remote_wakeup = on; 48 usb_autopm_put_interface(dev->intf); 49 } 50 err: 51 return rv; 52 } 53 54 static int cdc_mbim_wdm_manage_power(struct usb_interface *intf, int status) 55 { 56 struct usbnet *dev = usb_get_intfdata(intf); 57 58 /* can be called while disconnecting */ 59 if (!dev) 60 return 0; 61 62 return cdc_mbim_manage_power(dev, status); 63 } 64 65 66 static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf) 67 { 68 struct cdc_ncm_ctx *ctx; 69 struct usb_driver *subdriver = ERR_PTR(-ENODEV); 70 int ret = -ENODEV; 71 u8 data_altsetting = CDC_NCM_DATA_ALTSETTING_NCM; 72 struct cdc_mbim_state *info = (void *)&dev->data; 73 74 /* see if interface supports MBIM alternate setting */ 75 if (intf->num_altsetting == 2) { 76 if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting)) 77 usb_set_interface(dev->udev, 78 intf->cur_altsetting->desc.bInterfaceNumber, 79 CDC_NCM_COMM_ALTSETTING_MBIM); 80 data_altsetting = CDC_NCM_DATA_ALTSETTING_MBIM; 81 } 82 83 /* Probably NCM, defer for cdc_ncm_bind */ 84 if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting)) 85 goto err; 86 87 ret = cdc_ncm_bind_common(dev, intf, data_altsetting); 88 if (ret) 89 goto err; 90 91 ctx = info->ctx; 92 93 /* The MBIM descriptor and the status endpoint are required */ 94 if (ctx->mbim_desc && dev->status) 95 subdriver = usb_cdc_wdm_register(ctx->control, 96 &dev->status->desc, 97 le16_to_cpu(ctx->mbim_desc->wMaxControlMessage), 98 cdc_mbim_wdm_manage_power); 99 if (IS_ERR(subdriver)) { 100 ret = PTR_ERR(subdriver); 101 cdc_ncm_unbind(dev, intf); 102 goto err; 103 } 104 105 /* can't let usbnet use the interrupt endpoint */ 106 dev->status = NULL; 107 info->subdriver = subdriver; 108 109 /* MBIM cannot do ARP */ 110 dev->net->flags |= IFF_NOARP; 111 112 /* no need to put the VLAN tci in the packet headers */ 113 dev->net->features |= NETIF_F_HW_VLAN_TX; 114 err: 115 return ret; 116 } 117 118 static void cdc_mbim_unbind(struct usbnet *dev, struct usb_interface *intf) 119 { 120 struct cdc_mbim_state *info = (void *)&dev->data; 121 struct cdc_ncm_ctx *ctx = info->ctx; 122 123 /* disconnect subdriver from control interface */ 124 if (info->subdriver && info->subdriver->disconnect) 125 info->subdriver->disconnect(ctx->control); 126 info->subdriver = NULL; 127 128 /* let NCM unbind clean up both control and data interface */ 129 cdc_ncm_unbind(dev, intf); 130 } 131 132 133 static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) 134 { 135 struct sk_buff *skb_out; 136 struct cdc_mbim_state *info = (void *)&dev->data; 137 struct cdc_ncm_ctx *ctx = info->ctx; 138 __le32 sign = cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN); 139 u16 tci = 0; 140 u8 *c; 141 142 if (!ctx) 143 goto error; 144 145 if (skb) { 146 if (skb->len <= sizeof(ETH_HLEN)) 147 goto error; 148 149 /* mapping VLANs to MBIM sessions: 150 * no tag => IPS session <0> 151 * 1 - 255 => IPS session <vlanid> 152 * 256 - 511 => DSS session <vlanid - 256> 153 * 512 - 4095 => unsupported, drop 154 */ 155 vlan_get_tag(skb, &tci); 156 157 switch (tci & 0x0f00) { 158 case 0x0000: /* VLAN ID 0 - 255 */ 159 /* verify that datagram is IPv4 or IPv6 */ 160 skb_reset_mac_header(skb); 161 switch (eth_hdr(skb)->h_proto) { 162 case htons(ETH_P_IP): 163 case htons(ETH_P_IPV6): 164 break; 165 default: 166 goto error; 167 } 168 c = (u8 *)&sign; 169 c[3] = tci; 170 break; 171 case 0x0100: /* VLAN ID 256 - 511 */ 172 sign = cpu_to_le32(USB_CDC_MBIM_NDP16_DSS_SIGN); 173 c = (u8 *)&sign; 174 c[3] = tci; 175 break; 176 default: 177 netif_err(dev, tx_err, dev->net, 178 "unsupported tci=0x%04x\n", tci); 179 goto error; 180 } 181 skb_pull(skb, ETH_HLEN); 182 } 183 184 spin_lock_bh(&ctx->mtx); 185 skb_out = cdc_ncm_fill_tx_frame(ctx, skb, sign); 186 spin_unlock_bh(&ctx->mtx); 187 return skb_out; 188 189 error: 190 if (skb) 191 dev_kfree_skb_any(skb); 192 193 return NULL; 194 } 195 196 static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_t len, u16 tci) 197 { 198 __be16 proto = htons(ETH_P_802_3); 199 struct sk_buff *skb = NULL; 200 201 if (tci < 256) { /* IPS session? */ 202 if (len < sizeof(struct iphdr)) 203 goto err; 204 205 switch (*buf & 0xf0) { 206 case 0x40: 207 proto = htons(ETH_P_IP); 208 break; 209 case 0x60: 210 proto = htons(ETH_P_IPV6); 211 break; 212 default: 213 goto err; 214 } 215 } 216 217 skb = netdev_alloc_skb_ip_align(dev->net, len + ETH_HLEN); 218 if (!skb) 219 goto err; 220 221 /* add an ethernet header */ 222 skb_put(skb, ETH_HLEN); 223 skb_reset_mac_header(skb); 224 eth_hdr(skb)->h_proto = proto; 225 memset(eth_hdr(skb)->h_source, 0, ETH_ALEN); 226 memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN); 227 228 /* add datagram */ 229 memcpy(skb_put(skb, len), buf, len); 230 231 /* map MBIM session to VLAN */ 232 if (tci) 233 vlan_put_tag(skb, tci); 234 err: 235 return skb; 236 } 237 238 static int cdc_mbim_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in) 239 { 240 struct sk_buff *skb; 241 struct cdc_mbim_state *info = (void *)&dev->data; 242 struct cdc_ncm_ctx *ctx = info->ctx; 243 int len; 244 int nframes; 245 int x; 246 int offset; 247 struct usb_cdc_ncm_ndp16 *ndp16; 248 struct usb_cdc_ncm_dpe16 *dpe16; 249 int ndpoffset; 250 int loopcount = 50; /* arbitrary max preventing infinite loop */ 251 u8 *c; 252 u16 tci; 253 254 ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in); 255 if (ndpoffset < 0) 256 goto error; 257 258 next_ndp: 259 nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset); 260 if (nframes < 0) 261 goto error; 262 263 ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset); 264 265 switch (ndp16->dwSignature & cpu_to_le32(0x00ffffff)) { 266 case cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN): 267 c = (u8 *)&ndp16->dwSignature; 268 tci = c[3]; 269 break; 270 case cpu_to_le32(USB_CDC_MBIM_NDP16_DSS_SIGN): 271 c = (u8 *)&ndp16->dwSignature; 272 tci = c[3] + 256; 273 break; 274 default: 275 netif_dbg(dev, rx_err, dev->net, 276 "unsupported NDP signature <0x%08x>\n", 277 le32_to_cpu(ndp16->dwSignature)); 278 goto err_ndp; 279 280 } 281 282 dpe16 = ndp16->dpe16; 283 for (x = 0; x < nframes; x++, dpe16++) { 284 offset = le16_to_cpu(dpe16->wDatagramIndex); 285 len = le16_to_cpu(dpe16->wDatagramLength); 286 287 /* 288 * CDC NCM ch. 3.7 289 * All entries after first NULL entry are to be ignored 290 */ 291 if ((offset == 0) || (len == 0)) { 292 if (!x) 293 goto err_ndp; /* empty NTB */ 294 break; 295 } 296 297 /* sanity checking */ 298 if (((offset + len) > skb_in->len) || (len > ctx->rx_max)) { 299 netif_dbg(dev, rx_err, dev->net, 300 "invalid frame detected (ignored) offset[%u]=%u, length=%u, skb=%p\n", 301 x, offset, len, skb_in); 302 if (!x) 303 goto err_ndp; 304 break; 305 } else { 306 skb = cdc_mbim_process_dgram(dev, skb_in->data + offset, len, tci); 307 if (!skb) 308 goto error; 309 usbnet_skb_return(dev, skb); 310 } 311 } 312 err_ndp: 313 /* are there more NDPs to process? */ 314 ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex); 315 if (ndpoffset && loopcount--) 316 goto next_ndp; 317 318 return 1; 319 error: 320 return 0; 321 } 322 323 static int cdc_mbim_suspend(struct usb_interface *intf, pm_message_t message) 324 { 325 int ret = 0; 326 struct usbnet *dev = usb_get_intfdata(intf); 327 struct cdc_mbim_state *info = (void *)&dev->data; 328 struct cdc_ncm_ctx *ctx = info->ctx; 329 330 if (ctx == NULL) { 331 ret = -1; 332 goto error; 333 } 334 335 ret = usbnet_suspend(intf, message); 336 if (ret < 0) 337 goto error; 338 339 if (intf == ctx->control && info->subdriver && info->subdriver->suspend) 340 ret = info->subdriver->suspend(intf, message); 341 if (ret < 0) 342 usbnet_resume(intf); 343 344 error: 345 return ret; 346 } 347 348 static int cdc_mbim_resume(struct usb_interface *intf) 349 { 350 int ret = 0; 351 struct usbnet *dev = usb_get_intfdata(intf); 352 struct cdc_mbim_state *info = (void *)&dev->data; 353 struct cdc_ncm_ctx *ctx = info->ctx; 354 bool callsub = (intf == ctx->control && info->subdriver && info->subdriver->resume); 355 356 if (callsub) 357 ret = info->subdriver->resume(intf); 358 if (ret < 0) 359 goto err; 360 ret = usbnet_resume(intf); 361 if (ret < 0 && callsub && info->subdriver->suspend) 362 info->subdriver->suspend(intf, PMSG_SUSPEND); 363 err: 364 return ret; 365 } 366 367 static const struct driver_info cdc_mbim_info = { 368 .description = "CDC MBIM", 369 .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN, 370 .bind = cdc_mbim_bind, 371 .unbind = cdc_mbim_unbind, 372 .manage_power = cdc_mbim_manage_power, 373 .rx_fixup = cdc_mbim_rx_fixup, 374 .tx_fixup = cdc_mbim_tx_fixup, 375 }; 376 377 static const struct usb_device_id mbim_devs[] = { 378 /* This duplicate NCM entry is intentional. MBIM devices can 379 * be disguised as NCM by default, and this is necessary to 380 * allow us to bind the correct driver_info to such devices. 381 * 382 * bind() will sort out this for us, selecting the correct 383 * entry and reject the other 384 */ 385 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), 386 .driver_info = (unsigned long)&cdc_mbim_info, 387 }, 388 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), 389 .driver_info = (unsigned long)&cdc_mbim_info, 390 }, 391 { 392 }, 393 }; 394 MODULE_DEVICE_TABLE(usb, mbim_devs); 395 396 static struct usb_driver cdc_mbim_driver = { 397 .name = "cdc_mbim", 398 .id_table = mbim_devs, 399 .probe = usbnet_probe, 400 .disconnect = usbnet_disconnect, 401 .suspend = cdc_mbim_suspend, 402 .resume = cdc_mbim_resume, 403 .reset_resume = cdc_mbim_resume, 404 .supports_autosuspend = 1, 405 .disable_hub_initiated_lpm = 1, 406 }; 407 module_usb_driver(cdc_mbim_driver); 408 409 MODULE_AUTHOR("Greg Suarez <gsuarez@smithmicro.com>"); 410 MODULE_AUTHOR("Bjørn Mork <bjorn@mork.no>"); 411 MODULE_DESCRIPTION("USB CDC MBIM host driver"); 412 MODULE_LICENSE("GPL"); 413