Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * phonet.c -- USB CDC Phonet host driver
0004  *
0005  * Copyright (C) 2008-2009 Nokia Corporation. All rights reserved.
0006  *
0007  * Author: Rémi Denis-Courmont
0008  */
0009 
0010 #include <linux/kernel.h>
0011 #include <linux/mm.h>
0012 #include <linux/module.h>
0013 #include <linux/gfp.h>
0014 #include <linux/usb.h>
0015 #include <linux/usb/cdc.h>
0016 #include <linux/netdevice.h>
0017 #include <linux/if_arp.h>
0018 #include <linux/if_phonet.h>
0019 #include <linux/phonet.h>
0020 
0021 #define PN_MEDIA_USB    0x1B
0022 
0023 static const unsigned rxq_size = 17;
0024 
0025 struct usbpn_dev {
0026     struct net_device   *dev;
0027 
0028     struct usb_interface    *intf, *data_intf;
0029     struct usb_device   *usb;
0030     unsigned int        tx_pipe, rx_pipe;
0031     u8 active_setting;
0032     u8 disconnected;
0033 
0034     unsigned        tx_queue;
0035     spinlock_t      tx_lock;
0036 
0037     spinlock_t      rx_lock;
0038     struct sk_buff      *rx_skb;
0039     struct urb      *urbs[];
0040 };
0041 
0042 static void tx_complete(struct urb *req);
0043 static void rx_complete(struct urb *req);
0044 
0045 /*
0046  * Network device callbacks
0047  */
0048 static netdev_tx_t usbpn_xmit(struct sk_buff *skb, struct net_device *dev)
0049 {
0050     struct usbpn_dev *pnd = netdev_priv(dev);
0051     struct urb *req = NULL;
0052     unsigned long flags;
0053     int err;
0054 
0055     if (skb->protocol != htons(ETH_P_PHONET))
0056         goto drop;
0057 
0058     req = usb_alloc_urb(0, GFP_ATOMIC);
0059     if (!req)
0060         goto drop;
0061     usb_fill_bulk_urb(req, pnd->usb, pnd->tx_pipe, skb->data, skb->len,
0062                 tx_complete, skb);
0063     req->transfer_flags = URB_ZERO_PACKET;
0064     err = usb_submit_urb(req, GFP_ATOMIC);
0065     if (err) {
0066         usb_free_urb(req);
0067         goto drop;
0068     }
0069 
0070     spin_lock_irqsave(&pnd->tx_lock, flags);
0071     pnd->tx_queue++;
0072     if (pnd->tx_queue >= dev->tx_queue_len)
0073         netif_stop_queue(dev);
0074     spin_unlock_irqrestore(&pnd->tx_lock, flags);
0075     return NETDEV_TX_OK;
0076 
0077 drop:
0078     dev_kfree_skb(skb);
0079     dev->stats.tx_dropped++;
0080     return NETDEV_TX_OK;
0081 }
0082 
0083 static void tx_complete(struct urb *req)
0084 {
0085     struct sk_buff *skb = req->context;
0086     struct net_device *dev = skb->dev;
0087     struct usbpn_dev *pnd = netdev_priv(dev);
0088     int status = req->status;
0089     unsigned long flags;
0090 
0091     switch (status) {
0092     case 0:
0093         dev->stats.tx_bytes += skb->len;
0094         break;
0095 
0096     case -ENOENT:
0097     case -ECONNRESET:
0098     case -ESHUTDOWN:
0099         dev->stats.tx_aborted_errors++;
0100         fallthrough;
0101     default:
0102         dev->stats.tx_errors++;
0103         dev_dbg(&dev->dev, "TX error (%d)\n", status);
0104     }
0105     dev->stats.tx_packets++;
0106 
0107     spin_lock_irqsave(&pnd->tx_lock, flags);
0108     pnd->tx_queue--;
0109     netif_wake_queue(dev);
0110     spin_unlock_irqrestore(&pnd->tx_lock, flags);
0111 
0112     dev_kfree_skb_any(skb);
0113     usb_free_urb(req);
0114 }
0115 
0116 static int rx_submit(struct usbpn_dev *pnd, struct urb *req, gfp_t gfp_flags)
0117 {
0118     struct net_device *dev = pnd->dev;
0119     struct page *page;
0120     int err;
0121 
0122     page = __dev_alloc_page(gfp_flags | __GFP_NOMEMALLOC);
0123     if (!page)
0124         return -ENOMEM;
0125 
0126     usb_fill_bulk_urb(req, pnd->usb, pnd->rx_pipe, page_address(page),
0127                 PAGE_SIZE, rx_complete, dev);
0128     req->transfer_flags = 0;
0129     err = usb_submit_urb(req, gfp_flags);
0130     if (unlikely(err)) {
0131         dev_dbg(&dev->dev, "RX submit error (%d)\n", err);
0132         put_page(page);
0133     }
0134     return err;
0135 }
0136 
0137 static void rx_complete(struct urb *req)
0138 {
0139     struct net_device *dev = req->context;
0140     struct usbpn_dev *pnd = netdev_priv(dev);
0141     struct page *page = virt_to_page(req->transfer_buffer);
0142     struct sk_buff *skb;
0143     unsigned long flags;
0144     int status = req->status;
0145 
0146     switch (status) {
0147     case 0:
0148         spin_lock_irqsave(&pnd->rx_lock, flags);
0149         skb = pnd->rx_skb;
0150         if (!skb) {
0151             skb = pnd->rx_skb = netdev_alloc_skb(dev, 12);
0152             if (likely(skb)) {
0153                 /* Can't use pskb_pull() on page in IRQ */
0154                 skb_put_data(skb, page_address(page), 1);
0155                 skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
0156                         page, 1, req->actual_length,
0157                         PAGE_SIZE);
0158                 page = NULL;
0159             }
0160         } else {
0161             skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
0162                     page, 0, req->actual_length,
0163                     PAGE_SIZE);
0164             page = NULL;
0165         }
0166         if (req->actual_length < PAGE_SIZE)
0167             pnd->rx_skb = NULL; /* Last fragment */
0168         else
0169             skb = NULL;
0170         spin_unlock_irqrestore(&pnd->rx_lock, flags);
0171         if (skb) {
0172             skb->protocol = htons(ETH_P_PHONET);
0173             skb_reset_mac_header(skb);
0174             __skb_pull(skb, 1);
0175             skb->dev = dev;
0176             dev->stats.rx_packets++;
0177             dev->stats.rx_bytes += skb->len;
0178 
0179             netif_rx(skb);
0180         }
0181         goto resubmit;
0182 
0183     case -ENOENT:
0184     case -ECONNRESET:
0185     case -ESHUTDOWN:
0186         req = NULL;
0187         break;
0188 
0189     case -EOVERFLOW:
0190         dev->stats.rx_over_errors++;
0191         dev_dbg(&dev->dev, "RX overflow\n");
0192         break;
0193 
0194     case -EILSEQ:
0195         dev->stats.rx_crc_errors++;
0196         break;
0197     }
0198 
0199     dev->stats.rx_errors++;
0200 resubmit:
0201     if (page)
0202         put_page(page);
0203     if (req)
0204         rx_submit(pnd, req, GFP_ATOMIC);
0205 }
0206 
0207 static int usbpn_close(struct net_device *dev);
0208 
0209 static int usbpn_open(struct net_device *dev)
0210 {
0211     struct usbpn_dev *pnd = netdev_priv(dev);
0212     int err;
0213     unsigned i;
0214     unsigned num = pnd->data_intf->cur_altsetting->desc.bInterfaceNumber;
0215 
0216     err = usb_set_interface(pnd->usb, num, pnd->active_setting);
0217     if (err)
0218         return err;
0219 
0220     for (i = 0; i < rxq_size; i++) {
0221         struct urb *req = usb_alloc_urb(0, GFP_KERNEL);
0222 
0223         if (!req || rx_submit(pnd, req, GFP_KERNEL)) {
0224             usb_free_urb(req);
0225             usbpn_close(dev);
0226             return -ENOMEM;
0227         }
0228         pnd->urbs[i] = req;
0229     }
0230 
0231     netif_wake_queue(dev);
0232     return 0;
0233 }
0234 
0235 static int usbpn_close(struct net_device *dev)
0236 {
0237     struct usbpn_dev *pnd = netdev_priv(dev);
0238     unsigned i;
0239     unsigned num = pnd->data_intf->cur_altsetting->desc.bInterfaceNumber;
0240 
0241     netif_stop_queue(dev);
0242 
0243     for (i = 0; i < rxq_size; i++) {
0244         struct urb *req = pnd->urbs[i];
0245 
0246         if (!req)
0247             continue;
0248         usb_kill_urb(req);
0249         usb_free_urb(req);
0250         pnd->urbs[i] = NULL;
0251     }
0252 
0253     return usb_set_interface(pnd->usb, num, !pnd->active_setting);
0254 }
0255 
0256 static int usbpn_siocdevprivate(struct net_device *dev, struct ifreq *ifr,
0257                 void __user *data, int cmd)
0258 {
0259     struct if_phonet_req *req = (struct if_phonet_req *)ifr;
0260 
0261     switch (cmd) {
0262     case SIOCPNGAUTOCONF:
0263         req->ifr_phonet_autoconf.device = PN_DEV_PC;
0264         return 0;
0265     }
0266     return -ENOIOCTLCMD;
0267 }
0268 
0269 static const struct net_device_ops usbpn_ops = {
0270     .ndo_open   = usbpn_open,
0271     .ndo_stop   = usbpn_close,
0272     .ndo_start_xmit = usbpn_xmit,
0273     .ndo_siocdevprivate = usbpn_siocdevprivate,
0274 };
0275 
0276 static void usbpn_setup(struct net_device *dev)
0277 {
0278     const u8 addr = PN_MEDIA_USB;
0279 
0280     dev->features       = 0;
0281     dev->netdev_ops     = &usbpn_ops;
0282     dev->header_ops     = &phonet_header_ops;
0283     dev->type       = ARPHRD_PHONET;
0284     dev->flags      = IFF_POINTOPOINT | IFF_NOARP;
0285     dev->mtu        = PHONET_MAX_MTU;
0286     dev->min_mtu        = PHONET_MIN_MTU;
0287     dev->max_mtu        = PHONET_MAX_MTU;
0288     dev->hard_header_len    = 1;
0289     dev->addr_len       = 1;
0290     dev_addr_set(dev, &addr);
0291     dev->tx_queue_len   = 3;
0292 
0293     dev->needs_free_netdev  = true;
0294 }
0295 
0296 /*
0297  * USB driver callbacks
0298  */
0299 static const struct usb_device_id usbpn_ids[] = {
0300     {
0301         .match_flags = USB_DEVICE_ID_MATCH_VENDOR
0302             | USB_DEVICE_ID_MATCH_INT_CLASS
0303             | USB_DEVICE_ID_MATCH_INT_SUBCLASS,
0304         .idVendor = 0x0421, /* Nokia */
0305         .bInterfaceClass = USB_CLASS_COMM,
0306         .bInterfaceSubClass = 0xFE,
0307     },
0308     { },
0309 };
0310 
0311 MODULE_DEVICE_TABLE(usb, usbpn_ids);
0312 
0313 static struct usb_driver usbpn_driver;
0314 
0315 static int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id)
0316 {
0317     static const char ifname[] = "usbpn%d";
0318     const struct usb_cdc_union_desc *union_header = NULL;
0319     const struct usb_host_interface *data_desc;
0320     struct usb_interface *data_intf;
0321     struct usb_device *usbdev = interface_to_usbdev(intf);
0322     struct net_device *dev;
0323     struct usbpn_dev *pnd;
0324     u8 *data;
0325     int phonet = 0;
0326     int len, err;
0327     struct usb_cdc_parsed_header hdr;
0328 
0329     data = intf->altsetting->extra;
0330     len = intf->altsetting->extralen;
0331     cdc_parse_cdc_header(&hdr, intf, data, len);
0332     union_header = hdr.usb_cdc_union_desc;
0333     phonet = hdr.phonet_magic_present;
0334 
0335     if (!union_header || !phonet)
0336         return -EINVAL;
0337 
0338     data_intf = usb_ifnum_to_if(usbdev, union_header->bSlaveInterface0);
0339     if (data_intf == NULL)
0340         return -ENODEV;
0341     /* Data interface has one inactive and one active setting */
0342     if (data_intf->num_altsetting != 2)
0343         return -EINVAL;
0344     if (data_intf->altsetting[0].desc.bNumEndpoints == 0 &&
0345         data_intf->altsetting[1].desc.bNumEndpoints == 2)
0346         data_desc = data_intf->altsetting + 1;
0347     else
0348     if (data_intf->altsetting[0].desc.bNumEndpoints == 2 &&
0349         data_intf->altsetting[1].desc.bNumEndpoints == 0)
0350         data_desc = data_intf->altsetting;
0351     else
0352         return -EINVAL;
0353 
0354     dev = alloc_netdev(struct_size(pnd, urbs, rxq_size), ifname,
0355                NET_NAME_UNKNOWN, usbpn_setup);
0356     if (!dev)
0357         return -ENOMEM;
0358 
0359     pnd = netdev_priv(dev);
0360     SET_NETDEV_DEV(dev, &intf->dev);
0361 
0362     pnd->dev = dev;
0363     pnd->usb = usbdev;
0364     pnd->intf = intf;
0365     pnd->data_intf = data_intf;
0366     spin_lock_init(&pnd->tx_lock);
0367     spin_lock_init(&pnd->rx_lock);
0368     /* Endpoints */
0369     if (usb_pipein(data_desc->endpoint[0].desc.bEndpointAddress)) {
0370         pnd->rx_pipe = usb_rcvbulkpipe(usbdev,
0371             data_desc->endpoint[0].desc.bEndpointAddress);
0372         pnd->tx_pipe = usb_sndbulkpipe(usbdev,
0373             data_desc->endpoint[1].desc.bEndpointAddress);
0374     } else {
0375         pnd->rx_pipe = usb_rcvbulkpipe(usbdev,
0376             data_desc->endpoint[1].desc.bEndpointAddress);
0377         pnd->tx_pipe = usb_sndbulkpipe(usbdev,
0378             data_desc->endpoint[0].desc.bEndpointAddress);
0379     }
0380     pnd->active_setting = data_desc - data_intf->altsetting;
0381 
0382     err = usb_driver_claim_interface(&usbpn_driver, data_intf, pnd);
0383     if (err)
0384         goto out;
0385 
0386     /* Force inactive mode until the network device is brought UP */
0387     usb_set_interface(usbdev, union_header->bSlaveInterface0,
0388                 !pnd->active_setting);
0389     usb_set_intfdata(intf, pnd);
0390 
0391     err = register_netdev(dev);
0392     if (err) {
0393         /* Set disconnected flag so that disconnect() returns early. */
0394         pnd->disconnected = 1;
0395         usb_driver_release_interface(&usbpn_driver, data_intf);
0396         goto out;
0397     }
0398 
0399     dev_dbg(&dev->dev, "USB CDC Phonet device found\n");
0400     return 0;
0401 
0402 out:
0403     usb_set_intfdata(intf, NULL);
0404     free_netdev(dev);
0405     return err;
0406 }
0407 
0408 static void usbpn_disconnect(struct usb_interface *intf)
0409 {
0410     struct usbpn_dev *pnd = usb_get_intfdata(intf);
0411 
0412     if (pnd->disconnected)
0413         return;
0414 
0415     pnd->disconnected = 1;
0416     usb_driver_release_interface(&usbpn_driver,
0417             (pnd->intf == intf) ? pnd->data_intf : pnd->intf);
0418     unregister_netdev(pnd->dev);
0419 }
0420 
0421 static struct usb_driver usbpn_driver = {
0422     .name =     "cdc_phonet",
0423     .probe =    usbpn_probe,
0424     .disconnect =   usbpn_disconnect,
0425     .id_table = usbpn_ids,
0426     .disable_hub_initiated_lpm = 1,
0427 };
0428 
0429 module_usb_driver(usbpn_driver);
0430 
0431 MODULE_AUTHOR("Remi Denis-Courmont");
0432 MODULE_DESCRIPTION("USB CDC Phonet host interface");
0433 MODULE_LICENSE("GPL");