aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2005-10-24 16:24:14 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-10-28 19:47:51 -0400
commit4f62efe67f077db17dad03a1d4c9665000a3eb45 (patch)
tree27f1837fd08ce3dccb94a88a5afef6eb1a5ed738
parent16f16d117c1eb99451e4c73c87546eef05c66790 (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.c10
-rw-r--r--drivers/usb/core/hub.c22
-rw-r--r--drivers/usb/core/message.c48
-rw-r--r--drivers/usb/core/sysfs.c36
-rw-r--r--drivers/usb/core/usb.h1
-rw-r--r--include/linux/usb.h10
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
1207static 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 */
798char *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}
265static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL); 259static 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} \
304static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); 292static 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
538static inline void usb_create_intf_ep_files(struct usb_interface *intf) 526static 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
549static inline void usb_remove_intf_ep_files(struct usb_interface *intf) 538static 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
559void usb_create_sysfs_intf_files (struct usb_interface *intf) 548void 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
568void usb_remove_sysfs_intf_files (struct usb_interface *intf) 562void 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
14extern int usb_get_device_descriptor(struct usb_device *dev, 14extern int usb_get_device_descriptor(struct usb_device *dev,
15 unsigned int size); 15 unsigned int size);
16extern char *usb_cache_string(struct usb_device *udev, int index);
16extern int usb_set_configuration(struct usb_device *dev, int configuration); 17extern int usb_set_configuration(struct usb_device *dev, int configuration);
17 18
18extern void usb_lock_all_devices(void); 19extern 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 {
231struct usb_host_config { 231struct 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 */