root/drivers/usb/serial/bus.c

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

DEFINITIONS

This source file includes following definitions.
  1. usb_serial_device_match
  2. usb_serial_device_probe
  3. usb_serial_device_remove
  4. new_id_store
  5. new_id_show
  6. free_dynids
  7. usb_serial_bus_register
  8. usb_serial_bus_deregister

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * USB Serial Converter Bus specific functions
   4  *
   5  * Copyright (C) 2002 Greg Kroah-Hartman (greg@kroah.com)
   6  */
   7 
   8 #include <linux/kernel.h>
   9 #include <linux/errno.h>
  10 #include <linux/tty.h>
  11 #include <linux/slab.h>
  12 #include <linux/module.h>
  13 #include <linux/usb.h>
  14 #include <linux/usb/serial.h>
  15 
  16 static int usb_serial_device_match(struct device *dev,
  17                                                 struct device_driver *drv)
  18 {
  19         struct usb_serial_driver *driver;
  20         const struct usb_serial_port *port;
  21 
  22         /*
  23          * drivers are already assigned to ports in serial_probe so it's
  24          * a simple check here.
  25          */
  26         port = to_usb_serial_port(dev);
  27         if (!port)
  28                 return 0;
  29 
  30         driver = to_usb_serial_driver(drv);
  31 
  32         if (driver == port->serial->type)
  33                 return 1;
  34 
  35         return 0;
  36 }
  37 
  38 static int usb_serial_device_probe(struct device *dev)
  39 {
  40         struct usb_serial_driver *driver;
  41         struct usb_serial_port *port;
  42         struct device *tty_dev;
  43         int retval = 0;
  44         int minor;
  45 
  46         port = to_usb_serial_port(dev);
  47         if (!port)
  48                 return -ENODEV;
  49 
  50         /* make sure suspend/resume doesn't race against port_probe */
  51         retval = usb_autopm_get_interface(port->serial->interface);
  52         if (retval)
  53                 return retval;
  54 
  55         driver = port->serial->type;
  56         if (driver->port_probe) {
  57                 retval = driver->port_probe(port);
  58                 if (retval)
  59                         goto err_autopm_put;
  60         }
  61 
  62         minor = port->minor;
  63         tty_dev = tty_port_register_device(&port->port, usb_serial_tty_driver,
  64                                            minor, dev);
  65         if (IS_ERR(tty_dev)) {
  66                 retval = PTR_ERR(tty_dev);
  67                 goto err_port_remove;
  68         }
  69 
  70         usb_autopm_put_interface(port->serial->interface);
  71 
  72         dev_info(&port->serial->dev->dev,
  73                  "%s converter now attached to ttyUSB%d\n",
  74                  driver->description, minor);
  75 
  76         return 0;
  77 
  78 err_port_remove:
  79         if (driver->port_remove)
  80                 driver->port_remove(port);
  81 err_autopm_put:
  82         usb_autopm_put_interface(port->serial->interface);
  83 
  84         return retval;
  85 }
  86 
  87 static int usb_serial_device_remove(struct device *dev)
  88 {
  89         struct usb_serial_driver *driver;
  90         struct usb_serial_port *port;
  91         int retval = 0;
  92         int minor;
  93         int autopm_err;
  94 
  95         port = to_usb_serial_port(dev);
  96         if (!port)
  97                 return -ENODEV;
  98 
  99         /*
 100          * Make sure suspend/resume doesn't race against port_remove.
 101          *
 102          * Note that no further runtime PM callbacks will be made if
 103          * autopm_get fails.
 104          */
 105         autopm_err = usb_autopm_get_interface(port->serial->interface);
 106 
 107         minor = port->minor;
 108         tty_unregister_device(usb_serial_tty_driver, minor);
 109 
 110         driver = port->serial->type;
 111         if (driver->port_remove)
 112                 retval = driver->port_remove(port);
 113 
 114         dev_info(dev, "%s converter now disconnected from ttyUSB%d\n",
 115                  driver->description, minor);
 116 
 117         if (!autopm_err)
 118                 usb_autopm_put_interface(port->serial->interface);
 119 
 120         return retval;
 121 }
 122 
 123 static ssize_t new_id_store(struct device_driver *driver,
 124                             const char *buf, size_t count)
 125 {
 126         struct usb_serial_driver *usb_drv = to_usb_serial_driver(driver);
 127         ssize_t retval = usb_store_new_id(&usb_drv->dynids, usb_drv->id_table,
 128                                          driver, buf, count);
 129 
 130         if (retval >= 0 && usb_drv->usb_driver != NULL)
 131                 retval = usb_store_new_id(&usb_drv->usb_driver->dynids,
 132                                           usb_drv->usb_driver->id_table,
 133                                           &usb_drv->usb_driver->drvwrap.driver,
 134                                           buf, count);
 135         return retval;
 136 }
 137 
 138 static ssize_t new_id_show(struct device_driver *driver, char *buf)
 139 {
 140         struct usb_serial_driver *usb_drv = to_usb_serial_driver(driver);
 141 
 142         return usb_show_dynids(&usb_drv->dynids, buf);
 143 }
 144 static DRIVER_ATTR_RW(new_id);
 145 
 146 static struct attribute *usb_serial_drv_attrs[] = {
 147         &driver_attr_new_id.attr,
 148         NULL,
 149 };
 150 ATTRIBUTE_GROUPS(usb_serial_drv);
 151 
 152 static void free_dynids(struct usb_serial_driver *drv)
 153 {
 154         struct usb_dynid *dynid, *n;
 155 
 156         spin_lock(&drv->dynids.lock);
 157         list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
 158                 list_del(&dynid->node);
 159                 kfree(dynid);
 160         }
 161         spin_unlock(&drv->dynids.lock);
 162 }
 163 
 164 struct bus_type usb_serial_bus_type = {
 165         .name =         "usb-serial",
 166         .match =        usb_serial_device_match,
 167         .probe =        usb_serial_device_probe,
 168         .remove =       usb_serial_device_remove,
 169         .drv_groups =   usb_serial_drv_groups,
 170 };
 171 
 172 int usb_serial_bus_register(struct usb_serial_driver *driver)
 173 {
 174         int retval;
 175 
 176         driver->driver.bus = &usb_serial_bus_type;
 177         spin_lock_init(&driver->dynids.lock);
 178         INIT_LIST_HEAD(&driver->dynids.list);
 179 
 180         retval = driver_register(&driver->driver);
 181 
 182         return retval;
 183 }
 184 
 185 void usb_serial_bus_deregister(struct usb_serial_driver *driver)
 186 {
 187         free_dynids(driver);
 188         driver_unregister(&driver->driver);
 189 }
 190 

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