diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2005-10-24 16:24:14 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-10-28 19:47:51 -0400 |
commit | 4f62efe67f077db17dad03a1d4c9665000a3eb45 (patch) | |
tree | 27f1837fd08ce3dccb94a88a5afef6eb1a5ed738 | |
parent | 16f16d117c1eb99451e4c73c87546eef05c66790 (diff) |
[PATCH] usbcore: Fix handling of sysfs strings and other attributes
This patch (as592) makes a few small improvements to the way device
strings are handled, and it fixes some bugs in a couple of other sysfs
attribute routines. (Look at show_configuration_string() to see what I
mean.)
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/usb/core/config.c | 10 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 22 | ||||
-rw-r--r-- | drivers/usb/core/message.c | 48 | ||||
-rw-r--r-- | drivers/usb/core/sysfs.c | 36 | ||||
-rw-r--r-- | drivers/usb/core/usb.h | 1 | ||||
-rw-r--r-- | include/linux/usb.h | 10 |
6 files changed, 62 insertions, 65 deletions
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 63f374e62db2..993019500cc3 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c | |||
@@ -112,8 +112,12 @@ void usb_release_interface_cache(struct kref *ref) | |||
112 | struct usb_interface_cache *intfc = ref_to_usb_interface_cache(ref); | 112 | struct usb_interface_cache *intfc = ref_to_usb_interface_cache(ref); |
113 | int j; | 113 | int j; |
114 | 114 | ||
115 | for (j = 0; j < intfc->num_altsetting; j++) | 115 | for (j = 0; j < intfc->num_altsetting; j++) { |
116 | kfree(intfc->altsetting[j].endpoint); | 116 | struct usb_host_interface *alt = &intfc->altsetting[j]; |
117 | |||
118 | kfree(alt->endpoint); | ||
119 | kfree(alt->string); | ||
120 | } | ||
117 | kfree(intfc); | 121 | kfree(intfc); |
118 | } | 122 | } |
119 | 123 | ||
@@ -420,8 +424,6 @@ void usb_destroy_configuration(struct usb_device *dev) | |||
420 | struct usb_host_config *cf = &dev->config[c]; | 424 | struct usb_host_config *cf = &dev->config[c]; |
421 | 425 | ||
422 | kfree(cf->string); | 426 | kfree(cf->string); |
423 | cf->string = NULL; | ||
424 | |||
425 | for (i = 0; i < cf->desc.bNumInterfaces; i++) { | 427 | for (i = 0; i < cf->desc.bNumInterfaces; i++) { |
426 | if (cf->intf_cache[i]) | 428 | if (cf->intf_cache[i]) |
427 | kref_put(&cf->intf_cache[i]->ref, | 429 | kref_put(&cf->intf_cache[i]->ref, |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 8ba5854e5387..1bacb374b007 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -1204,21 +1204,6 @@ static inline void show_string(struct usb_device *udev, char *id, char *string) | |||
1204 | {} | 1204 | {} |
1205 | #endif | 1205 | #endif |
1206 | 1206 | ||
1207 | static void get_string(struct usb_device *udev, char **string, int index) | ||
1208 | { | ||
1209 | char *buf; | ||
1210 | |||
1211 | if (!index) | ||
1212 | return; | ||
1213 | buf = kmalloc(256, GFP_KERNEL); | ||
1214 | if (!buf) | ||
1215 | return; | ||
1216 | if (usb_string(udev, index, buf, 256) > 0) | ||
1217 | *string = buf; | ||
1218 | else | ||
1219 | kfree(buf); | ||
1220 | } | ||
1221 | |||
1222 | 1207 | ||
1223 | #ifdef CONFIG_USB_OTG | 1208 | #ifdef CONFIG_USB_OTG |
1224 | #include "otg_whitelist.h" | 1209 | #include "otg_whitelist.h" |
@@ -1257,9 +1242,10 @@ int usb_new_device(struct usb_device *udev) | |||
1257 | } | 1242 | } |
1258 | 1243 | ||
1259 | /* read the standard strings and cache them if present */ | 1244 | /* read the standard strings and cache them if present */ |
1260 | get_string(udev, &udev->product, udev->descriptor.iProduct); | 1245 | udev->product = usb_cache_string(udev, udev->descriptor.iProduct); |
1261 | get_string(udev, &udev->manufacturer, udev->descriptor.iManufacturer); | 1246 | udev->manufacturer = usb_cache_string(udev, |
1262 | get_string(udev, &udev->serial, udev->descriptor.iSerialNumber); | 1247 | udev->descriptor.iManufacturer); |
1248 | udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber); | ||
1263 | 1249 | ||
1264 | /* Tell the world! */ | 1250 | /* Tell the world! */ |
1265 | dev_dbg(&udev->dev, "new device strings: Mfr=%d, Product=%d, " | 1251 | dev_dbg(&udev->dev, "new device strings: Mfr=%d, Product=%d, " |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 3519f317898e..644a3d4f12aa 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
@@ -787,6 +787,31 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) | |||
787 | return err; | 787 | return err; |
788 | } | 788 | } |
789 | 789 | ||
790 | /** | ||
791 | * usb_cache_string - read a string descriptor and cache it for later use | ||
792 | * @udev: the device whose string descriptor is being read | ||
793 | * @index: the descriptor index | ||
794 | * | ||
795 | * Returns a pointer to a kmalloc'ed buffer containing the descriptor string, | ||
796 | * or NULL if the index is 0 or the string could not be read. | ||
797 | */ | ||
798 | char *usb_cache_string(struct usb_device *udev, int index) | ||
799 | { | ||
800 | char *buf; | ||
801 | char *smallbuf = NULL; | ||
802 | int len; | ||
803 | |||
804 | if (index > 0 && (buf = kmalloc(256, GFP_KERNEL)) != NULL) { | ||
805 | if ((len = usb_string(udev, index, buf, 256)) > 0) { | ||
806 | if ((smallbuf = kmalloc(++len, GFP_KERNEL)) == NULL) | ||
807 | return buf; | ||
808 | memcpy(smallbuf, buf, len); | ||
809 | } | ||
810 | kfree(buf); | ||
811 | } | ||
812 | return smallbuf; | ||
813 | } | ||
814 | |||
790 | /* | 815 | /* |
791 | * usb_get_device_descriptor - (re)reads the device descriptor (usbcore) | 816 | * usb_get_device_descriptor - (re)reads the device descriptor (usbcore) |
792 | * @dev: the device whose device descriptor is being updated | 817 | * @dev: the device whose device descriptor is being updated |
@@ -1008,8 +1033,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) | |||
1008 | dev_dbg (&dev->dev, "unregistering interface %s\n", | 1033 | dev_dbg (&dev->dev, "unregistering interface %s\n", |
1009 | interface->dev.bus_id); | 1034 | interface->dev.bus_id); |
1010 | usb_remove_sysfs_intf_files(interface); | 1035 | usb_remove_sysfs_intf_files(interface); |
1011 | kfree(interface->cur_altsetting->string); | ||
1012 | interface->cur_altsetting->string = NULL; | ||
1013 | device_del (&interface->dev); | 1036 | device_del (&interface->dev); |
1014 | } | 1037 | } |
1015 | 1038 | ||
@@ -1422,12 +1445,9 @@ free_interfaces: | |||
1422 | } | 1445 | } |
1423 | kfree(new_interfaces); | 1446 | kfree(new_interfaces); |
1424 | 1447 | ||
1425 | if ((cp->desc.iConfiguration) && | 1448 | if (cp->string == NULL) |
1426 | (cp->string == NULL)) { | 1449 | cp->string = usb_cache_string(dev, |
1427 | cp->string = kmalloc(256, GFP_KERNEL); | 1450 | cp->desc.iConfiguration); |
1428 | if (cp->string) | ||
1429 | usb_string(dev, cp->desc.iConfiguration, cp->string, 256); | ||
1430 | } | ||
1431 | 1451 | ||
1432 | /* Now that all the interfaces are set up, register them | 1452 | /* Now that all the interfaces are set up, register them |
1433 | * to trigger binding of drivers to interfaces. probe() | 1453 | * to trigger binding of drivers to interfaces. probe() |
@@ -1437,13 +1457,12 @@ free_interfaces: | |||
1437 | */ | 1457 | */ |
1438 | for (i = 0; i < nintf; ++i) { | 1458 | for (i = 0; i < nintf; ++i) { |
1439 | struct usb_interface *intf = cp->interface[i]; | 1459 | struct usb_interface *intf = cp->interface[i]; |
1440 | struct usb_interface_descriptor *desc; | 1460 | struct usb_host_interface *alt = intf->cur_altsetting; |
1441 | 1461 | ||
1442 | desc = &intf->altsetting [0].desc; | ||
1443 | dev_dbg (&dev->dev, | 1462 | dev_dbg (&dev->dev, |
1444 | "adding %s (config #%d, interface %d)\n", | 1463 | "adding %s (config #%d, interface %d)\n", |
1445 | intf->dev.bus_id, configuration, | 1464 | intf->dev.bus_id, configuration, |
1446 | desc->bInterfaceNumber); | 1465 | alt->desc.bInterfaceNumber); |
1447 | ret = device_add (&intf->dev); | 1466 | ret = device_add (&intf->dev); |
1448 | if (ret != 0) { | 1467 | if (ret != 0) { |
1449 | dev_err(&dev->dev, | 1468 | dev_err(&dev->dev, |
@@ -1452,13 +1471,6 @@ free_interfaces: | |||
1452 | ret); | 1471 | ret); |
1453 | continue; | 1472 | continue; |
1454 | } | 1473 | } |
1455 | if ((intf->cur_altsetting->desc.iInterface) && | ||
1456 | (intf->cur_altsetting->string == NULL)) { | ||
1457 | intf->cur_altsetting->string = kmalloc(256, GFP_KERNEL); | ||
1458 | if (intf->cur_altsetting->string) | ||
1459 | usb_string(dev, intf->cur_altsetting->desc.iInterface, | ||
1460 | intf->cur_altsetting->string, 256); | ||
1461 | } | ||
1462 | usb_create_sysfs_intf_files (intf); | 1474 | usb_create_sysfs_intf_files (intf); |
1463 | } | 1475 | } |
1464 | } | 1476 | } |
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 4cca77cf0c48..edd83e014452 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c | |||
@@ -249,18 +249,12 @@ static ssize_t show_configuration_string(struct device *dev, | |||
249 | { | 249 | { |
250 | struct usb_device *udev; | 250 | struct usb_device *udev; |
251 | struct usb_host_config *actconfig; | 251 | struct usb_host_config *actconfig; |
252 | int len; | ||
253 | 252 | ||
254 | udev = to_usb_device (dev); | 253 | udev = to_usb_device (dev); |
255 | actconfig = udev->actconfig; | 254 | actconfig = udev->actconfig; |
256 | if ((!actconfig) || (!actconfig->string)) | 255 | if ((!actconfig) || (!actconfig->string)) |
257 | return 0; | 256 | return 0; |
258 | len = sprintf(buf, actconfig->string, PAGE_SIZE); | 257 | return sprintf(buf, "%s\n", actconfig->string); |
259 | if (len < 0) | ||
260 | return 0; | ||
261 | buf[len] = '\n'; | ||
262 | buf[len+1] = 0; | ||
263 | return len+1; | ||
264 | } | 258 | } |
265 | static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL); | 259 | static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL); |
266 | 260 | ||
@@ -291,15 +285,9 @@ static ssize_t show_##name(struct device *dev, \ | |||
291 | struct device_attribute *attr, char *buf) \ | 285 | struct device_attribute *attr, char *buf) \ |
292 | { \ | 286 | { \ |
293 | struct usb_device *udev; \ | 287 | struct usb_device *udev; \ |
294 | int len; \ | ||
295 | \ | 288 | \ |
296 | udev = to_usb_device (dev); \ | 289 | udev = to_usb_device (dev); \ |
297 | len = snprintf(buf, 256, "%s", udev->name); \ | 290 | return sprintf(buf, "%s\n", udev->name); \ |
298 | if (len < 0) \ | ||
299 | return 0; \ | ||
300 | buf[len] = '\n'; \ | ||
301 | buf[len+1] = 0; \ | ||
302 | return len+1; \ | ||
303 | } \ | 291 | } \ |
304 | static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); | 292 | static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); |
305 | 293 | ||
@@ -449,11 +437,11 @@ void usb_remove_sysfs_dev_files (struct usb_device *udev) | |||
449 | usb_remove_ep_files(&udev->ep0); | 437 | usb_remove_ep_files(&udev->ep0); |
450 | sysfs_remove_group(&dev->kobj, &dev_attr_grp); | 438 | sysfs_remove_group(&dev->kobj, &dev_attr_grp); |
451 | 439 | ||
452 | if (udev->descriptor.iManufacturer) | 440 | if (udev->manufacturer) |
453 | device_remove_file(dev, &dev_attr_manufacturer); | 441 | device_remove_file(dev, &dev_attr_manufacturer); |
454 | if (udev->descriptor.iProduct) | 442 | if (udev->product) |
455 | device_remove_file(dev, &dev_attr_product); | 443 | device_remove_file(dev, &dev_attr_product); |
456 | if (udev->descriptor.iSerialNumber) | 444 | if (udev->serial) |
457 | device_remove_file(dev, &dev_attr_serial); | 445 | device_remove_file(dev, &dev_attr_serial); |
458 | device_remove_file (dev, &dev_attr_configuration); | 446 | device_remove_file (dev, &dev_attr_configuration); |
459 | } | 447 | } |
@@ -535,7 +523,8 @@ static struct attribute_group intf_attr_grp = { | |||
535 | .attrs = intf_attrs, | 523 | .attrs = intf_attrs, |
536 | }; | 524 | }; |
537 | 525 | ||
538 | static inline void usb_create_intf_ep_files(struct usb_interface *intf) | 526 | static inline void usb_create_intf_ep_files(struct usb_interface *intf, |
527 | struct usb_device *udev) | ||
539 | { | 528 | { |
540 | struct usb_host_interface *iface_desc; | 529 | struct usb_host_interface *iface_desc; |
541 | int i; | 530 | int i; |
@@ -543,7 +532,7 @@ static inline void usb_create_intf_ep_files(struct usb_interface *intf) | |||
543 | iface_desc = intf->cur_altsetting; | 532 | iface_desc = intf->cur_altsetting; |
544 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) | 533 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) |
545 | usb_create_ep_files(&intf->dev.kobj, &iface_desc->endpoint[i], | 534 | usb_create_ep_files(&intf->dev.kobj, &iface_desc->endpoint[i], |
546 | interface_to_usbdev(intf)); | 535 | udev); |
547 | } | 536 | } |
548 | 537 | ||
549 | static inline void usb_remove_intf_ep_files(struct usb_interface *intf) | 538 | static inline void usb_remove_intf_ep_files(struct usb_interface *intf) |
@@ -558,11 +547,16 @@ static inline void usb_remove_intf_ep_files(struct usb_interface *intf) | |||
558 | 547 | ||
559 | void usb_create_sysfs_intf_files (struct usb_interface *intf) | 548 | void usb_create_sysfs_intf_files (struct usb_interface *intf) |
560 | { | 549 | { |
550 | struct usb_device *udev = interface_to_usbdev(intf); | ||
551 | struct usb_host_interface *alt = intf->cur_altsetting; | ||
552 | |||
561 | sysfs_create_group(&intf->dev.kobj, &intf_attr_grp); | 553 | sysfs_create_group(&intf->dev.kobj, &intf_attr_grp); |
562 | 554 | ||
563 | if (intf->cur_altsetting->string) | 555 | if (alt->string == NULL) |
556 | alt->string = usb_cache_string(udev, alt->desc.iInterface); | ||
557 | if (alt->string) | ||
564 | device_create_file(&intf->dev, &dev_attr_interface); | 558 | device_create_file(&intf->dev, &dev_attr_interface); |
565 | usb_create_intf_ep_files(intf); | 559 | usb_create_intf_ep_files(intf, udev); |
566 | } | 560 | } |
567 | 561 | ||
568 | void usb_remove_sysfs_intf_files (struct usb_interface *intf) | 562 | void usb_remove_sysfs_intf_files (struct usb_interface *intf) |
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 888dbe443695..1c4a68499dce 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
@@ -13,6 +13,7 @@ extern void usb_disable_device (struct usb_device *dev, int skip_ep0); | |||
13 | 13 | ||
14 | extern int usb_get_device_descriptor(struct usb_device *dev, | 14 | extern int usb_get_device_descriptor(struct usb_device *dev, |
15 | unsigned int size); | 15 | unsigned int size); |
16 | extern char *usb_cache_string(struct usb_device *udev, int index); | ||
16 | extern int usb_set_configuration(struct usb_device *dev, int configuration); | 17 | extern int usb_set_configuration(struct usb_device *dev, int configuration); |
17 | 18 | ||
18 | extern void usb_lock_all_devices(void); | 19 | extern void usb_lock_all_devices(void); |
diff --git a/include/linux/usb.h b/include/linux/usb.h index c500d6b5a16d..748d04385256 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
@@ -231,7 +231,7 @@ struct usb_interface_cache { | |||
231 | struct usb_host_config { | 231 | struct usb_host_config { |
232 | struct usb_config_descriptor desc; | 232 | struct usb_config_descriptor desc; |
233 | 233 | ||
234 | char *string; | 234 | char *string; /* iConfiguration string, if present */ |
235 | /* the interfaces associated with this configuration, | 235 | /* the interfaces associated with this configuration, |
236 | * stored in no particular order */ | 236 | * stored in no particular order */ |
237 | struct usb_interface *interface[USB_MAXINTERFACES]; | 237 | struct usb_interface *interface[USB_MAXINTERFACES]; |
@@ -351,9 +351,11 @@ struct usb_device { | |||
351 | int have_langid; /* whether string_langid is valid */ | 351 | int have_langid; /* whether string_langid is valid */ |
352 | int string_langid; /* language ID for strings */ | 352 | int string_langid; /* language ID for strings */ |
353 | 353 | ||
354 | char *product; | 354 | /* static strings from the device */ |
355 | char *manufacturer; | 355 | char *product; /* iProduct string, if present */ |
356 | char *serial; /* static strings from the device */ | 356 | char *manufacturer; /* iManufacturer string, if present */ |
357 | char *serial; /* iSerialNumber string, if present */ | ||
358 | |||
357 | struct list_head filelist; | 359 | struct list_head filelist; |
358 | struct class_device *class_dev; | 360 | struct class_device *class_dev; |
359 | struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */ | 361 | struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */ |