diff options
Diffstat (limited to 'drivers/usb/serial/usb-serial.c')
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 109 |
1 files changed, 72 insertions, 37 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 97355a15bbea..6a1b609a0d94 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * USB Serial Converter driver | 2 | * USB Serial Converter driver |
3 | * | 3 | * |
4 | * Copyright (C) 1999 - 2005 Greg Kroah-Hartman (greg@kroah.com) | 4 | * Copyright (C) 1999 - 2012 Greg Kroah-Hartman (greg@kroah.com) |
5 | * Copyright (C) 2000 Peter Berger (pberger@brimson.com) | 5 | * Copyright (C) 2000 Peter Berger (pberger@brimson.com) |
6 | * Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com) | 6 | * Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com) |
7 | * | 7 | * |
@@ -43,17 +43,6 @@ | |||
43 | #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/" | 43 | #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/" |
44 | #define DRIVER_DESC "USB Serial Driver core" | 44 | #define DRIVER_DESC "USB Serial Driver core" |
45 | 45 | ||
46 | /* Driver structure we register with the USB core */ | ||
47 | static struct usb_driver usb_serial_driver = { | ||
48 | .name = "usbserial", | ||
49 | .probe = usb_serial_probe, | ||
50 | .disconnect = usb_serial_disconnect, | ||
51 | .suspend = usb_serial_suspend, | ||
52 | .resume = usb_serial_resume, | ||
53 | .no_dynamic_id = 1, | ||
54 | .supports_autosuspend = 1, | ||
55 | }; | ||
56 | |||
57 | /* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead | 46 | /* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead |
58 | the MODULE_DEVICE_TABLE declarations in each serial driver | 47 | the MODULE_DEVICE_TABLE declarations in each serial driver |
59 | cause the "hotplug" program to pull in whatever module is necessary | 48 | cause the "hotplug" program to pull in whatever module is necessary |
@@ -710,7 +699,7 @@ static const struct tty_port_operations serial_port_ops = { | |||
710 | .shutdown = serial_down, | 699 | .shutdown = serial_down, |
711 | }; | 700 | }; |
712 | 701 | ||
713 | int usb_serial_probe(struct usb_interface *interface, | 702 | static int usb_serial_probe(struct usb_interface *interface, |
714 | const struct usb_device_id *id) | 703 | const struct usb_device_id *id) |
715 | { | 704 | { |
716 | struct usb_device *dev = interface_to_usbdev(interface); | 705 | struct usb_device *dev = interface_to_usbdev(interface); |
@@ -856,6 +845,8 @@ int usb_serial_probe(struct usb_interface *interface, | |||
856 | module_put(type->driver.owner); | 845 | module_put(type->driver.owner); |
857 | return -EIO; | 846 | return -EIO; |
858 | } | 847 | } |
848 | dev_info(&interface->dev, "The \"generic\" usb-serial driver is only for testing and one-off prototypes.\n"); | ||
849 | dev_info(&interface->dev, "Tell linux-usb@vger.kernel.org to add your device to a proper driver.\n"); | ||
859 | } | 850 | } |
860 | #endif | 851 | #endif |
861 | if (!num_ports) { | 852 | if (!num_ports) { |
@@ -1043,6 +1034,8 @@ int usb_serial_probe(struct usb_interface *interface, | |||
1043 | dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined"); | 1034 | dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined"); |
1044 | } | 1035 | } |
1045 | 1036 | ||
1037 | usb_set_intfdata(interface, serial); | ||
1038 | |||
1046 | /* if this device type has an attach function, call it */ | 1039 | /* if this device type has an attach function, call it */ |
1047 | if (type->attach) { | 1040 | if (type->attach) { |
1048 | retval = type->attach(serial); | 1041 | retval = type->attach(serial); |
@@ -1087,10 +1080,7 @@ int usb_serial_probe(struct usb_interface *interface, | |||
1087 | serial->disconnected = 0; | 1080 | serial->disconnected = 0; |
1088 | 1081 | ||
1089 | usb_serial_console_init(debug, minor); | 1082 | usb_serial_console_init(debug, minor); |
1090 | |||
1091 | exit: | 1083 | exit: |
1092 | /* success */ | ||
1093 | usb_set_intfdata(interface, serial); | ||
1094 | module_put(type->driver.owner); | 1084 | module_put(type->driver.owner); |
1095 | return 0; | 1085 | return 0; |
1096 | 1086 | ||
@@ -1099,9 +1089,8 @@ probe_error: | |||
1099 | module_put(type->driver.owner); | 1089 | module_put(type->driver.owner); |
1100 | return -EIO; | 1090 | return -EIO; |
1101 | } | 1091 | } |
1102 | EXPORT_SYMBOL_GPL(usb_serial_probe); | ||
1103 | 1092 | ||
1104 | void usb_serial_disconnect(struct usb_interface *interface) | 1093 | static void usb_serial_disconnect(struct usb_interface *interface) |
1105 | { | 1094 | { |
1106 | int i; | 1095 | int i; |
1107 | struct usb_serial *serial = usb_get_intfdata(interface); | 1096 | struct usb_serial *serial = usb_get_intfdata(interface); |
@@ -1112,7 +1101,6 @@ void usb_serial_disconnect(struct usb_interface *interface) | |||
1112 | dbg("%s", __func__); | 1101 | dbg("%s", __func__); |
1113 | 1102 | ||
1114 | mutex_lock(&serial->disc_mutex); | 1103 | mutex_lock(&serial->disc_mutex); |
1115 | usb_set_intfdata(interface, NULL); | ||
1116 | /* must set a flag, to signal subdrivers */ | 1104 | /* must set a flag, to signal subdrivers */ |
1117 | serial->disconnected = 1; | 1105 | serial->disconnected = 1; |
1118 | mutex_unlock(&serial->disc_mutex); | 1106 | mutex_unlock(&serial->disc_mutex); |
@@ -1137,7 +1125,6 @@ void usb_serial_disconnect(struct usb_interface *interface) | |||
1137 | usb_serial_put(serial); | 1125 | usb_serial_put(serial); |
1138 | dev_info(dev, "device disconnected\n"); | 1126 | dev_info(dev, "device disconnected\n"); |
1139 | } | 1127 | } |
1140 | EXPORT_SYMBOL_GPL(usb_serial_disconnect); | ||
1141 | 1128 | ||
1142 | int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) | 1129 | int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) |
1143 | { | 1130 | { |
@@ -1181,6 +1168,22 @@ int usb_serial_resume(struct usb_interface *intf) | |||
1181 | } | 1168 | } |
1182 | EXPORT_SYMBOL(usb_serial_resume); | 1169 | EXPORT_SYMBOL(usb_serial_resume); |
1183 | 1170 | ||
1171 | static int usb_serial_reset_resume(struct usb_interface *intf) | ||
1172 | { | ||
1173 | struct usb_serial *serial = usb_get_intfdata(intf); | ||
1174 | int rv; | ||
1175 | |||
1176 | serial->suspending = 0; | ||
1177 | if (serial->type->reset_resume) | ||
1178 | rv = serial->type->reset_resume(serial); | ||
1179 | else { | ||
1180 | rv = -EOPNOTSUPP; | ||
1181 | intf->needs_binding = 1; | ||
1182 | } | ||
1183 | |||
1184 | return rv; | ||
1185 | } | ||
1186 | |||
1184 | static const struct tty_operations serial_ops = { | 1187 | static const struct tty_operations serial_ops = { |
1185 | .open = serial_open, | 1188 | .open = serial_open, |
1186 | .close = serial_close, | 1189 | .close = serial_close, |
@@ -1204,6 +1207,17 @@ static const struct tty_operations serial_ops = { | |||
1204 | 1207 | ||
1205 | struct tty_driver *usb_serial_tty_driver; | 1208 | struct tty_driver *usb_serial_tty_driver; |
1206 | 1209 | ||
1210 | /* Driver structure we register with the USB core */ | ||
1211 | static struct usb_driver usb_serial_driver = { | ||
1212 | .name = "usbserial", | ||
1213 | .probe = usb_serial_probe, | ||
1214 | .disconnect = usb_serial_disconnect, | ||
1215 | .suspend = usb_serial_suspend, | ||
1216 | .resume = usb_serial_resume, | ||
1217 | .no_dynamic_id = 1, | ||
1218 | .supports_autosuspend = 1, | ||
1219 | }; | ||
1220 | |||
1207 | static int __init usb_serial_init(void) | 1221 | static int __init usb_serial_init(void) |
1208 | { | 1222 | { |
1209 | int i; | 1223 | int i; |
@@ -1338,7 +1352,6 @@ static int usb_serial_register(struct usb_serial_driver *driver) | |||
1338 | driver->description); | 1352 | driver->description); |
1339 | return -EINVAL; | 1353 | return -EINVAL; |
1340 | } | 1354 | } |
1341 | driver->usb_driver->supports_autosuspend = 1; | ||
1342 | 1355 | ||
1343 | /* Add this device to our list of devices */ | 1356 | /* Add this device to our list of devices */ |
1344 | mutex_lock(&table_lock); | 1357 | mutex_lock(&table_lock); |
@@ -1369,18 +1382,19 @@ static void usb_serial_deregister(struct usb_serial_driver *device) | |||
1369 | 1382 | ||
1370 | /** | 1383 | /** |
1371 | * usb_serial_register_drivers - register drivers for a usb-serial module | 1384 | * usb_serial_register_drivers - register drivers for a usb-serial module |
1372 | * @udriver: usb_driver used for matching devices/interfaces | ||
1373 | * @serial_drivers: NULL-terminated array of pointers to drivers to be registered | 1385 | * @serial_drivers: NULL-terminated array of pointers to drivers to be registered |
1386 | * @name: name of the usb_driver for this set of @serial_drivers | ||
1387 | * @id_table: list of all devices this @serial_drivers set binds to | ||
1374 | * | 1388 | * |
1375 | * Registers @udriver and all the drivers in the @serial_drivers array. | 1389 | * Registers all the drivers in the @serial_drivers array, and dynamically |
1376 | * Automatically fills in the .no_dynamic_id field in @udriver and | 1390 | * creates a struct usb_driver with the name @name and id_table of @id_table. |
1377 | * the .usb_driver field in each serial driver. | ||
1378 | */ | 1391 | */ |
1379 | int usb_serial_register_drivers(struct usb_driver *udriver, | 1392 | int usb_serial_register_drivers(struct usb_serial_driver *const serial_drivers[], |
1380 | struct usb_serial_driver * const serial_drivers[]) | 1393 | const char *name, |
1394 | const struct usb_device_id *id_table) | ||
1381 | { | 1395 | { |
1382 | int rc; | 1396 | int rc; |
1383 | const struct usb_device_id *saved_id_table; | 1397 | struct usb_driver *udriver; |
1384 | struct usb_serial_driver * const *sd; | 1398 | struct usb_serial_driver * const *sd; |
1385 | 1399 | ||
1386 | /* | 1400 | /* |
@@ -1391,12 +1405,30 @@ int usb_serial_register_drivers(struct usb_driver *udriver, | |||
1391 | * Performance hack: We don't want udriver to be probed until | 1405 | * Performance hack: We don't want udriver to be probed until |
1392 | * the serial drivers are registered, because the probe would | 1406 | * the serial drivers are registered, because the probe would |
1393 | * simply fail for lack of a matching serial driver. | 1407 | * simply fail for lack of a matching serial driver. |
1394 | * Therefore save off udriver's id_table until we are all set. | 1408 | * So we leave udriver's id_table set to NULL until we are all set. |
1409 | * | ||
1410 | * Suspend/resume support is implemented in the usb-serial core, | ||
1411 | * so fill in the PM-related fields in udriver. | ||
1395 | */ | 1412 | */ |
1396 | saved_id_table = udriver->id_table; | 1413 | udriver = kzalloc(sizeof(*udriver), GFP_KERNEL); |
1397 | udriver->id_table = NULL; | 1414 | if (!udriver) |
1415 | return -ENOMEM; | ||
1398 | 1416 | ||
1417 | udriver->name = name; | ||
1399 | udriver->no_dynamic_id = 1; | 1418 | udriver->no_dynamic_id = 1; |
1419 | udriver->supports_autosuspend = 1; | ||
1420 | udriver->suspend = usb_serial_suspend; | ||
1421 | udriver->resume = usb_serial_resume; | ||
1422 | udriver->probe = usb_serial_probe; | ||
1423 | udriver->disconnect = usb_serial_disconnect; | ||
1424 | |||
1425 | /* we only set the reset_resume field if the serial_driver has one */ | ||
1426 | for (sd = serial_drivers; *sd; ++sd) { | ||
1427 | if ((*sd)->reset_resume) | ||
1428 | udriver->reset_resume = usb_serial_reset_resume; | ||
1429 | break; | ||
1430 | } | ||
1431 | |||
1400 | rc = usb_register(udriver); | 1432 | rc = usb_register(udriver); |
1401 | if (rc) | 1433 | if (rc) |
1402 | return rc; | 1434 | return rc; |
@@ -1408,8 +1440,8 @@ int usb_serial_register_drivers(struct usb_driver *udriver, | |||
1408 | goto failed; | 1440 | goto failed; |
1409 | } | 1441 | } |
1410 | 1442 | ||
1411 | /* Now restore udriver's id_table and look for matches */ | 1443 | /* Now set udriver's id_table and look for matches */ |
1412 | udriver->id_table = saved_id_table; | 1444 | udriver->id_table = id_table; |
1413 | rc = driver_attach(&udriver->drvwrap.driver); | 1445 | rc = driver_attach(&udriver->drvwrap.driver); |
1414 | return 0; | 1446 | return 0; |
1415 | 1447 | ||
@@ -1423,17 +1455,20 @@ EXPORT_SYMBOL_GPL(usb_serial_register_drivers); | |||
1423 | 1455 | ||
1424 | /** | 1456 | /** |
1425 | * usb_serial_deregister_drivers - deregister drivers for a usb-serial module | 1457 | * usb_serial_deregister_drivers - deregister drivers for a usb-serial module |
1426 | * @udriver: usb_driver to unregister | ||
1427 | * @serial_drivers: NULL-terminated array of pointers to drivers to be deregistered | 1458 | * @serial_drivers: NULL-terminated array of pointers to drivers to be deregistered |
1428 | * | 1459 | * |
1429 | * Deregisters @udriver and all the drivers in the @serial_drivers array. | 1460 | * Deregisters all the drivers in the @serial_drivers array and deregisters and |
1461 | * frees the struct usb_driver that was created by the call to | ||
1462 | * usb_serial_register_drivers(). | ||
1430 | */ | 1463 | */ |
1431 | void usb_serial_deregister_drivers(struct usb_driver *udriver, | 1464 | void usb_serial_deregister_drivers(struct usb_serial_driver *const serial_drivers[]) |
1432 | struct usb_serial_driver * const serial_drivers[]) | ||
1433 | { | 1465 | { |
1466 | struct usb_driver *udriver = (*serial_drivers)->usb_driver; | ||
1467 | |||
1434 | for (; *serial_drivers; ++serial_drivers) | 1468 | for (; *serial_drivers; ++serial_drivers) |
1435 | usb_serial_deregister(*serial_drivers); | 1469 | usb_serial_deregister(*serial_drivers); |
1436 | usb_deregister(udriver); | 1470 | usb_deregister(udriver); |
1471 | kfree(udriver); | ||
1437 | } | 1472 | } |
1438 | EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers); | 1473 | EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers); |
1439 | 1474 | ||