root/drivers/usb/atm/xusbatm.c

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

DEFINITIONS

This source file includes following definitions.
  1. xusbatm_find_intf
  2. xusbatm_capture_intf
  3. xusbatm_release_intf
  4. xusbatm_bind
  5. xusbatm_unbind
  6. xusbatm_atm_start
  7. xusbatm_usb_probe
  8. xusbatm_init
  9. xusbatm_exit

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /******************************************************************************
   3  *  xusbatm.c - dumb usbatm-based driver for modems initialized in userspace
   4  *
   5  *  Copyright (C) 2005 Duncan Sands, Roman Kagan (rkagan % mail ! ru)
   6  ******************************************************************************/
   7 
   8 #include <linux/module.h>
   9 #include <linux/etherdevice.h>          /* for eth_random_addr() */
  10 
  11 #include "usbatm.h"
  12 
  13 
  14 #define XUSBATM_DRIVERS_MAX     8
  15 
  16 #define XUSBATM_PARM(name, type, parmtype, desc) \
  17         static type name[XUSBATM_DRIVERS_MAX]; \
  18         static unsigned int num_##name; \
  19         module_param_array(name, parmtype, &num_##name, 0444); \
  20         MODULE_PARM_DESC(name, desc)
  21 
  22 XUSBATM_PARM(vendor, unsigned short, ushort, "USB device vendor");
  23 XUSBATM_PARM(product, unsigned short, ushort, "USB device product");
  24 
  25 XUSBATM_PARM(rx_endpoint, unsigned char, byte, "rx endpoint number");
  26 XUSBATM_PARM(tx_endpoint, unsigned char, byte, "tx endpoint number");
  27 XUSBATM_PARM(rx_padding, unsigned char, byte, "rx padding (default 0)");
  28 XUSBATM_PARM(tx_padding, unsigned char, byte, "tx padding (default 0)");
  29 XUSBATM_PARM(rx_altsetting, unsigned char, byte, "rx altsetting (default 0)");
  30 XUSBATM_PARM(tx_altsetting, unsigned char, byte, "rx altsetting (default 0)");
  31 
  32 static const char xusbatm_driver_name[] = "xusbatm";
  33 
  34 static struct usbatm_driver xusbatm_drivers[XUSBATM_DRIVERS_MAX];
  35 static struct usb_device_id xusbatm_usb_ids[XUSBATM_DRIVERS_MAX + 1];
  36 static struct usb_driver xusbatm_usb_driver;
  37 
  38 static struct usb_interface *xusbatm_find_intf(struct usb_device *usb_dev, int altsetting, u8 ep)
  39 {
  40         struct usb_host_interface *alt;
  41         struct usb_interface *intf;
  42         int i, j;
  43 
  44         for (i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++)
  45                 if ((intf = usb_dev->actconfig->interface[i]) && (alt = usb_altnum_to_altsetting(intf, altsetting)))
  46                         for (j = 0; j < alt->desc.bNumEndpoints; j++)
  47                                 if (alt->endpoint[j].desc.bEndpointAddress == ep)
  48                                         return intf;
  49         return NULL;
  50 }
  51 
  52 static int xusbatm_capture_intf(struct usbatm_data *usbatm, struct usb_device *usb_dev,
  53                 struct usb_interface *intf, int altsetting, int claim)
  54 {
  55         int ifnum = intf->altsetting->desc.bInterfaceNumber;
  56         int ret;
  57 
  58         if (claim && (ret = usb_driver_claim_interface(&xusbatm_usb_driver, intf, usbatm))) {
  59                 usb_err(usbatm, "%s: failed to claim interface %2d (%d)!\n", __func__, ifnum, ret);
  60                 return ret;
  61         }
  62         ret = usb_set_interface(usb_dev, ifnum, altsetting);
  63         if (ret) {
  64                 usb_err(usbatm, "%s: altsetting %2d for interface %2d failed (%d)!\n", __func__, altsetting, ifnum, ret);
  65                 return ret;
  66         }
  67         return 0;
  68 }
  69 
  70 static void xusbatm_release_intf(struct usb_device *usb_dev, struct usb_interface *intf, int claimed)
  71 {
  72         if (claimed) {
  73                 usb_set_intfdata(intf, NULL);
  74                 usb_driver_release_interface(&xusbatm_usb_driver, intf);
  75         }
  76 }
  77 
  78 static int xusbatm_bind(struct usbatm_data *usbatm,
  79                         struct usb_interface *intf, const struct usb_device_id *id)
  80 {
  81         struct usb_device *usb_dev = interface_to_usbdev(intf);
  82         int drv_ix = id - xusbatm_usb_ids;
  83         int rx_alt = rx_altsetting[drv_ix];
  84         int tx_alt = tx_altsetting[drv_ix];
  85         struct usb_interface *rx_intf = xusbatm_find_intf(usb_dev, rx_alt, rx_endpoint[drv_ix]);
  86         struct usb_interface *tx_intf = xusbatm_find_intf(usb_dev, tx_alt, tx_endpoint[drv_ix]);
  87         int ret;
  88 
  89         usb_dbg(usbatm, "%s: binding driver %d: vendor %04x product %04x"
  90                 " rx: ep %02x padd %d alt %2d tx: ep %02x padd %d alt %2d\n",
  91                 __func__, drv_ix, vendor[drv_ix], product[drv_ix],
  92                 rx_endpoint[drv_ix], rx_padding[drv_ix], rx_alt,
  93                 tx_endpoint[drv_ix], tx_padding[drv_ix], tx_alt);
  94 
  95         if (!rx_intf || !tx_intf) {
  96                 if (!rx_intf)
  97                         usb_dbg(usbatm, "%s: no interface contains endpoint %02x in altsetting %2d\n",
  98                                 __func__, rx_endpoint[drv_ix], rx_alt);
  99                 if (!tx_intf)
 100                         usb_dbg(usbatm, "%s: no interface contains endpoint %02x in altsetting %2d\n",
 101                                 __func__, tx_endpoint[drv_ix], tx_alt);
 102                 return -ENODEV;
 103         }
 104 
 105         if ((rx_intf != intf) && (tx_intf != intf))
 106                 return -ENODEV;
 107 
 108         if ((rx_intf == tx_intf) && (rx_alt != tx_alt)) {
 109                 usb_err(usbatm, "%s: altsettings clash on interface %2d (%2d vs %2d)!\n", __func__,
 110                                 rx_intf->altsetting->desc.bInterfaceNumber, rx_alt, tx_alt);
 111                 return -EINVAL;
 112         }
 113 
 114         usb_dbg(usbatm, "%s: rx If#=%2d; tx If#=%2d\n", __func__,
 115                         rx_intf->altsetting->desc.bInterfaceNumber,
 116                         tx_intf->altsetting->desc.bInterfaceNumber);
 117 
 118         ret = xusbatm_capture_intf(usbatm, usb_dev, rx_intf, rx_alt, rx_intf != intf);
 119         if (ret)
 120                 return ret;
 121 
 122         if ((tx_intf != rx_intf) && (ret = xusbatm_capture_intf(usbatm, usb_dev, tx_intf, tx_alt, tx_intf != intf))) {
 123                 xusbatm_release_intf(usb_dev, rx_intf, rx_intf != intf);
 124                 return ret;
 125         }
 126 
 127         return 0;
 128 }
 129 
 130 static void xusbatm_unbind(struct usbatm_data *usbatm,
 131                            struct usb_interface *intf)
 132 {
 133         struct usb_device *usb_dev = interface_to_usbdev(intf);
 134         int i;
 135 
 136         usb_dbg(usbatm, "%s entered\n", __func__);
 137 
 138         for (i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) {
 139                 struct usb_interface *cur_intf = usb_dev->actconfig->interface[i];
 140 
 141                 if (cur_intf && (usb_get_intfdata(cur_intf) == usbatm)) {
 142                         usb_set_intfdata(cur_intf, NULL);
 143                         usb_driver_release_interface(&xusbatm_usb_driver, cur_intf);
 144                 }
 145         }
 146 }
 147 
 148 static int xusbatm_atm_start(struct usbatm_data *usbatm,
 149                              struct atm_dev *atm_dev)
 150 {
 151         atm_dbg(usbatm, "%s entered\n", __func__);
 152 
 153         /* use random MAC as we've no way to get it from the device */
 154         eth_random_addr(atm_dev->esi);
 155 
 156         return 0;
 157 }
 158 
 159 
 160 static int xusbatm_usb_probe(struct usb_interface *intf,
 161                              const struct usb_device_id *id)
 162 {
 163         return usbatm_usb_probe(intf, id,
 164                                 xusbatm_drivers + (id - xusbatm_usb_ids));
 165 }
 166 
 167 static struct usb_driver xusbatm_usb_driver = {
 168         .name           = xusbatm_driver_name,
 169         .probe          = xusbatm_usb_probe,
 170         .disconnect     = usbatm_usb_disconnect,
 171         .id_table       = xusbatm_usb_ids
 172 };
 173 
 174 static int __init xusbatm_init(void)
 175 {
 176         int i;
 177 
 178         if (!num_vendor ||
 179             num_vendor != num_product ||
 180             num_vendor != num_rx_endpoint ||
 181             num_vendor != num_tx_endpoint) {
 182                 printk(KERN_WARNING "xusbatm: malformed module parameters\n");
 183                 return -EINVAL;
 184         }
 185 
 186         for (i = 0; i < num_vendor; i++) {
 187                 rx_endpoint[i] |= USB_DIR_IN;
 188                 tx_endpoint[i] &= USB_ENDPOINT_NUMBER_MASK;
 189 
 190                 xusbatm_usb_ids[i].match_flags  = USB_DEVICE_ID_MATCH_DEVICE;
 191                 xusbatm_usb_ids[i].idVendor     = vendor[i];
 192                 xusbatm_usb_ids[i].idProduct    = product[i];
 193 
 194                 xusbatm_drivers[i].driver_name  = xusbatm_driver_name;
 195                 xusbatm_drivers[i].bind         = xusbatm_bind;
 196                 xusbatm_drivers[i].unbind       = xusbatm_unbind;
 197                 xusbatm_drivers[i].atm_start    = xusbatm_atm_start;
 198                 xusbatm_drivers[i].bulk_in      = rx_endpoint[i];
 199                 xusbatm_drivers[i].bulk_out     = tx_endpoint[i];
 200                 xusbatm_drivers[i].rx_padding   = rx_padding[i];
 201                 xusbatm_drivers[i].tx_padding   = tx_padding[i];
 202         }
 203 
 204         return usb_register(&xusbatm_usb_driver);
 205 }
 206 module_init(xusbatm_init);
 207 
 208 static void __exit xusbatm_exit(void)
 209 {
 210         usb_deregister(&xusbatm_usb_driver);
 211 }
 212 module_exit(xusbatm_exit);
 213 
 214 MODULE_AUTHOR("Roman Kagan, Duncan Sands");
 215 MODULE_DESCRIPTION("Driver for USB ADSL modems initialized in userspace");
 216 MODULE_LICENSE("GPL");

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