1 /* 2 * phonet.c -- USB CDC Phonet host driver 3 * 4 * Copyright (C) 2008-2009 Nokia Corporation. All rights reserved. 5 * 6 * Author: Rémi Denis-Courmont 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 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 * 02110-1301 USA 21 */ 22 23 #include <linux/kernel.h> 24 #include <linux/module.h> 25 #include <linux/gfp.h> 26 #include <linux/usb.h> 27 #include <linux/usb/cdc.h> 28 #include <linux/netdevice.h> 29 #include <linux/if_arp.h> 30 #include <linux/if_phonet.h> 31 #include <linux/phonet.h> 32 33 #define PN_MEDIA_USB 0x1B 34 35 static const unsigned rxq_size = 17; 36 37 struct usbpn_dev { 38 struct net_device *dev; 39 40 struct usb_interface *intf, *data_intf; 41 struct usb_device *usb; 42 unsigned int tx_pipe, rx_pipe; 43 u8 active_setting; 44 u8 disconnected; 45 46 unsigned tx_queue; 47 spinlock_t tx_lock; 48 49 spinlock_t rx_lock; 50 struct sk_buff *rx_skb; 51 struct urb *urbs[0]; 52 }; 53 54 static void tx_complete(struct urb *req); 55 static void rx_complete(struct urb *req); 56 57 /* 58 * Network device callbacks 59 */ 60 static netdev_tx_t usbpn_xmit(struct sk_buff *skb, struct net_device *dev) 61 { 62 struct usbpn_dev *pnd = netdev_priv(dev); 63 struct urb *req = NULL; 64 unsigned long flags; 65 int err; 66 67 if (skb->protocol != htons(ETH_P_PHONET)) 68 goto drop; 69 70 req = usb_alloc_urb(0, GFP_ATOMIC); 71 if (!req) 72 goto drop; 73 usb_fill_bulk_urb(req, pnd->usb, pnd->tx_pipe, skb->data, skb->len, 74 tx_complete, skb); 75 req->transfer_flags = URB_ZERO_PACKET; 76 err = usb_submit_urb(req, GFP_ATOMIC); 77 if (err) { 78 usb_free_urb(req); 79 goto drop; 80 } 81 82 spin_lock_irqsave(&pnd->tx_lock, flags); 83 pnd->tx_queue++; 84 if (pnd->tx_queue >= dev->tx_queue_len) 85 netif_stop_queue(dev); 86 spin_unlock_irqrestore(&pnd->tx_lock, flags); 87 return NETDEV_TX_OK; 88 89 drop: 90 dev_kfree_skb(skb); 91 dev->stats.tx_dropped++; 92 return NETDEV_TX_OK; 93 } 94 95 static void tx_complete(struct urb *req) 96 { 97 struct sk_buff *skb = req->context; 98 struct net_device *dev = skb->dev; 99 struct usbpn_dev *pnd = netdev_priv(dev); 100 int status = req->status; 101 102 switch (status) { 103 case 0: 104 dev->stats.tx_bytes += skb->len; 105 break; 106 107 case -ENOENT: 108 case -ECONNRESET: 109 case -ESHUTDOWN: 110 dev->stats.tx_aborted_errors++; 111 default: 112 dev->stats.tx_errors++; 113 dev_dbg(&dev->dev, "TX error (%d)\n", status); 114 } 115 dev->stats.tx_packets++; 116 117 spin_lock(&pnd->tx_lock); 118 pnd->tx_queue--; 119 netif_wake_queue(dev); 120 spin_unlock(&pnd->tx_lock); 121 122 dev_kfree_skb_any(skb); 123 usb_free_urb(req); 124 } 125 126 static int rx_submit(struct usbpn_dev *pnd, struct urb *req, gfp_t gfp_flags) 127 { 128 struct net_device *dev = pnd->dev; 129 struct page *page; 130 int err; 131 132 page = __netdev_alloc_page(dev, gfp_flags); 133 if (!page) 134 return -ENOMEM; 135 136 usb_fill_bulk_urb(req, pnd->usb, pnd->rx_pipe, page_address(page), 137 PAGE_SIZE, rx_complete, dev); 138 req->transfer_flags = 0; 139 err = usb_submit_urb(req, gfp_flags); 140 if (unlikely(err)) { 141 dev_dbg(&dev->dev, "RX submit error (%d)\n", err); 142 netdev_free_page(dev, page); 143 } 144 return err; 145 } 146 147 static void rx_complete(struct urb *req) 148 { 149 struct net_device *dev = req->context; 150 struct usbpn_dev *pnd = netdev_priv(dev); 151 struct page *page = virt_to_page(req->transfer_buffer); 152 struct sk_buff *skb; 153 unsigned long flags; 154 int status = req->status; 155 156 switch (status) { 157 case 0: 158 spin_lock_irqsave(&pnd->rx_lock, flags); 159 skb = pnd->rx_skb; 160 if (!skb) { 161 skb = pnd->rx_skb = netdev_alloc_skb(dev, 12); 162 if (likely(skb)) { 163 /* Can't use pskb_pull() on page in IRQ */ 164 memcpy(skb_put(skb, 1), page_address(page), 1); 165 skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, 166 page, 1, req->actual_length); 167 page = NULL; 168 } 169 } else { 170 skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, 171 page, 0, req->actual_length); 172 page = NULL; 173 } 174 if (req->actual_length < PAGE_SIZE) 175 pnd->rx_skb = NULL; /* Last fragment */ 176 else 177 skb = NULL; 178 spin_unlock_irqrestore(&pnd->rx_lock, flags); 179 if (skb) { 180 skb->protocol = htons(ETH_P_PHONET); 181 skb_reset_mac_header(skb); 182 __skb_pull(skb, 1); 183 skb->dev = dev; 184 dev->stats.rx_packets++; 185 dev->stats.rx_bytes += skb->len; 186 187 netif_rx(skb); 188 } 189 goto resubmit; 190 191 case -ENOENT: 192 case -ECONNRESET: 193 case -ESHUTDOWN: 194 req = NULL; 195 break; 196 197 case -EOVERFLOW: 198 dev->stats.rx_over_errors++; 199 dev_dbg(&dev->dev, "RX overflow\n"); 200 break; 201 202 case -EILSEQ: 203 dev->stats.rx_crc_errors++; 204 break; 205 } 206 207 dev->stats.rx_errors++; 208 resubmit: 209 if (page) 210 netdev_free_page(dev, page); 211 if (req) 212 rx_submit(pnd, req, GFP_ATOMIC); 213 } 214 215 static int usbpn_close(struct net_device *dev); 216 217 static int usbpn_open(struct net_device *dev) 218 { 219 struct usbpn_dev *pnd = netdev_priv(dev); 220 int err; 221 unsigned i; 222 unsigned num = pnd->data_intf->cur_altsetting->desc.bInterfaceNumber; 223 224 err = usb_set_interface(pnd->usb, num, pnd->active_setting); 225 if (err) 226 return err; 227 228 for (i = 0; i < rxq_size; i++) { 229 struct urb *req = usb_alloc_urb(0, GFP_KERNEL); 230 231 if (!req || rx_submit(pnd, req, GFP_KERNEL)) { 232 usbpn_close(dev); 233 return -ENOMEM; 234 } 235 pnd->urbs[i] = req; 236 } 237 238 netif_wake_queue(dev); 239 return 0; 240 } 241 242 static int usbpn_close(struct net_device *dev) 243 { 244 struct usbpn_dev *pnd = netdev_priv(dev); 245 unsigned i; 246 unsigned num = pnd->data_intf->cur_altsetting->desc.bInterfaceNumber; 247 248 netif_stop_queue(dev); 249 250 for (i = 0; i < rxq_size; i++) { 251 struct urb *req = pnd->urbs[i]; 252 253 if (!req) 254 continue; 255 usb_kill_urb(req); 256 usb_free_urb(req); 257 pnd->urbs[i] = NULL; 258 } 259 260 return usb_set_interface(pnd->usb, num, !pnd->active_setting); 261 } 262 263 static int usbpn_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 264 { 265 struct if_phonet_req *req = (struct if_phonet_req *)ifr; 266 267 switch (cmd) { 268 case SIOCPNGAUTOCONF: 269 req->ifr_phonet_autoconf.device = PN_DEV_PC; 270 return 0; 271 } 272 return -ENOIOCTLCMD; 273 } 274 275 static int usbpn_set_mtu(struct net_device *dev, int new_mtu) 276 { 277 if ((new_mtu < PHONET_MIN_MTU) || (new_mtu > PHONET_MAX_MTU)) 278 return -EINVAL; 279 280 dev->mtu = new_mtu; 281 return 0; 282 } 283 284 static const struct net_device_ops usbpn_ops = { 285 .ndo_open = usbpn_open, 286 .ndo_stop = usbpn_close, 287 .ndo_start_xmit = usbpn_xmit, 288 .ndo_do_ioctl = usbpn_ioctl, 289 .ndo_change_mtu = usbpn_set_mtu, 290 }; 291 292 static void usbpn_setup(struct net_device *dev) 293 { 294 dev->features = 0; 295 dev->netdev_ops = &usbpn_ops, 296 dev->header_ops = &phonet_header_ops; 297 dev->type = ARPHRD_PHONET; 298 dev->flags = IFF_POINTOPOINT | IFF_NOARP; 299 dev->mtu = PHONET_MAX_MTU; 300 dev->hard_header_len = 1; 301 dev->dev_addr[0] = PN_MEDIA_USB; 302 dev->addr_len = 1; 303 dev->tx_queue_len = 3; 304 305 dev->destructor = free_netdev; 306 } 307 308 /* 309 * USB driver callbacks 310 */ 311 static struct usb_device_id usbpn_ids[] = { 312 { 313 .match_flags = USB_DEVICE_ID_MATCH_VENDOR 314 | USB_DEVICE_ID_MATCH_INT_CLASS 315 | USB_DEVICE_ID_MATCH_INT_SUBCLASS, 316 .idVendor = 0x0421, /* Nokia */ 317 .bInterfaceClass = USB_CLASS_COMM, 318 .bInterfaceSubClass = 0xFE, 319 }, 320 { }, 321 }; 322 323 MODULE_DEVICE_TABLE(usb, usbpn_ids); 324 325 static struct usb_driver usbpn_driver; 326 327 int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id) 328 { 329 static const char ifname[] = "usbpn%d"; 330 const struct usb_cdc_union_desc *union_header = NULL; 331 const struct usb_cdc_header_desc *phonet_header = NULL; 332 const struct usb_host_interface *data_desc; 333 struct usb_interface *data_intf; 334 struct usb_device *usbdev = interface_to_usbdev(intf); 335 struct net_device *dev; 336 struct usbpn_dev *pnd; 337 u8 *data; 338 int len, err; 339 340 data = intf->altsetting->extra; 341 len = intf->altsetting->extralen; 342 while (len >= 3) { 343 u8 dlen = data[0]; 344 if (dlen < 3) 345 return -EINVAL; 346 347 /* bDescriptorType */ 348 if (data[1] == USB_DT_CS_INTERFACE) { 349 /* bDescriptorSubType */ 350 switch (data[2]) { 351 case USB_CDC_UNION_TYPE: 352 if (union_header || dlen < 5) 353 break; 354 union_header = 355 (struct usb_cdc_union_desc *)data; 356 break; 357 case 0xAB: 358 if (phonet_header || dlen < 5) 359 break; 360 phonet_header = 361 (struct usb_cdc_header_desc *)data; 362 break; 363 } 364 } 365 data += dlen; 366 len -= dlen; 367 } 368 369 if (!union_header || !phonet_header) 370 return -EINVAL; 371 372 data_intf = usb_ifnum_to_if(usbdev, union_header->bSlaveInterface0); 373 if (data_intf == NULL) 374 return -ENODEV; 375 /* Data interface has one inactive and one active setting */ 376 if (data_intf->num_altsetting != 2) 377 return -EINVAL; 378 if (data_intf->altsetting[0].desc.bNumEndpoints == 0 && 379 data_intf->altsetting[1].desc.bNumEndpoints == 2) 380 data_desc = data_intf->altsetting + 1; 381 else 382 if (data_intf->altsetting[0].desc.bNumEndpoints == 2 && 383 data_intf->altsetting[1].desc.bNumEndpoints == 0) 384 data_desc = data_intf->altsetting; 385 else 386 return -EINVAL; 387 388 dev = alloc_netdev(sizeof(*pnd) + sizeof(pnd->urbs[0]) * rxq_size, 389 ifname, usbpn_setup); 390 if (!dev) 391 return -ENOMEM; 392 393 pnd = netdev_priv(dev); 394 SET_NETDEV_DEV(dev, &intf->dev); 395 netif_stop_queue(dev); 396 397 pnd->dev = dev; 398 pnd->usb = usb_get_dev(usbdev); 399 pnd->intf = intf; 400 pnd->data_intf = data_intf; 401 spin_lock_init(&pnd->tx_lock); 402 spin_lock_init(&pnd->rx_lock); 403 /* Endpoints */ 404 if (usb_pipein(data_desc->endpoint[0].desc.bEndpointAddress)) { 405 pnd->rx_pipe = usb_rcvbulkpipe(usbdev, 406 data_desc->endpoint[0].desc.bEndpointAddress); 407 pnd->tx_pipe = usb_sndbulkpipe(usbdev, 408 data_desc->endpoint[1].desc.bEndpointAddress); 409 } else { 410 pnd->rx_pipe = usb_rcvbulkpipe(usbdev, 411 data_desc->endpoint[1].desc.bEndpointAddress); 412 pnd->tx_pipe = usb_sndbulkpipe(usbdev, 413 data_desc->endpoint[0].desc.bEndpointAddress); 414 } 415 pnd->active_setting = data_desc - data_intf->altsetting; 416 417 err = usb_driver_claim_interface(&usbpn_driver, data_intf, pnd); 418 if (err) 419 goto out; 420 421 /* Force inactive mode until the network device is brought UP */ 422 usb_set_interface(usbdev, union_header->bSlaveInterface0, 423 !pnd->active_setting); 424 usb_set_intfdata(intf, pnd); 425 426 err = register_netdev(dev); 427 if (err) { 428 usb_driver_release_interface(&usbpn_driver, data_intf); 429 goto out; 430 } 431 432 dev_dbg(&dev->dev, "USB CDC Phonet device found\n"); 433 return 0; 434 435 out: 436 usb_set_intfdata(intf, NULL); 437 free_netdev(dev); 438 return err; 439 } 440 441 static void usbpn_disconnect(struct usb_interface *intf) 442 { 443 struct usbpn_dev *pnd = usb_get_intfdata(intf); 444 struct usb_device *usb = pnd->usb; 445 446 if (pnd->disconnected) 447 return; 448 449 pnd->disconnected = 1; 450 usb_driver_release_interface(&usbpn_driver, 451 (pnd->intf == intf) ? pnd->data_intf : pnd->intf); 452 unregister_netdev(pnd->dev); 453 usb_put_dev(usb); 454 } 455 456 static struct usb_driver usbpn_driver = { 457 .name = "cdc_phonet", 458 .probe = usbpn_probe, 459 .disconnect = usbpn_disconnect, 460 .id_table = usbpn_ids, 461 }; 462 463 static int __init usbpn_init(void) 464 { 465 return usb_register(&usbpn_driver); 466 } 467 468 static void __exit usbpn_exit(void) 469 { 470 usb_deregister(&usbpn_driver); 471 } 472 473 module_init(usbpn_init); 474 module_exit(usbpn_exit); 475 476 MODULE_AUTHOR("Remi Denis-Courmont"); 477 MODULE_DESCRIPTION("USB CDC Phonet host interface"); 478 MODULE_LICENSE("GPL"); 479