root/drivers/net/usb/cdc-phonet.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. usbpn_xmit
  2. tx_complete
  3. rx_submit
  4. rx_complete
  5. usbpn_open
  6. usbpn_close
  7. usbpn_ioctl
  8. usbpn_setup
  9. usbpn_probe
  10. usbpn_disconnect

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

/* [<][>][^][v][top][bottom][index][help] */