mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-11-07 04:09:21 +00:00
[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>
This commit is contained in:
parent
16f16d117c
commit
4f62efe67f
6 changed files with 62 additions and 65 deletions
|
@ -112,8 +112,12 @@ void usb_release_interface_cache(struct kref *ref)
|
||||||
struct usb_interface_cache *intfc = ref_to_usb_interface_cache(ref);
|
struct usb_interface_cache *intfc = ref_to_usb_interface_cache(ref);
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
for (j = 0; j < intfc->num_altsetting; j++)
|
for (j = 0; j < intfc->num_altsetting; j++) {
|
||||||
kfree(intfc->altsetting[j].endpoint);
|
struct usb_host_interface *alt = &intfc->altsetting[j];
|
||||||
|
|
||||||
|
kfree(alt->endpoint);
|
||||||
|
kfree(alt->string);
|
||||||
|
}
|
||||||
kfree(intfc);
|
kfree(intfc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,8 +424,6 @@ void usb_destroy_configuration(struct usb_device *dev)
|
||||||
struct usb_host_config *cf = &dev->config[c];
|
struct usb_host_config *cf = &dev->config[c];
|
||||||
|
|
||||||
kfree(cf->string);
|
kfree(cf->string);
|
||||||
cf->string = NULL;
|
|
||||||
|
|
||||||
for (i = 0; i < cf->desc.bNumInterfaces; i++) {
|
for (i = 0; i < cf->desc.bNumInterfaces; i++) {
|
||||||
if (cf->intf_cache[i])
|
if (cf->intf_cache[i])
|
||||||
kref_put(&cf->intf_cache[i]->ref,
|
kref_put(&cf->intf_cache[i]->ref,
|
||||||
|
|
|
@ -1204,21 +1204,6 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
|
||||||
{}
|
{}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void get_string(struct usb_device *udev, char **string, int index)
|
|
||||||
{
|
|
||||||
char *buf;
|
|
||||||
|
|
||||||
if (!index)
|
|
||||||
return;
|
|
||||||
buf = kmalloc(256, GFP_KERNEL);
|
|
||||||
if (!buf)
|
|
||||||
return;
|
|
||||||
if (usb_string(udev, index, buf, 256) > 0)
|
|
||||||
*string = buf;
|
|
||||||
else
|
|
||||||
kfree(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_USB_OTG
|
#ifdef CONFIG_USB_OTG
|
||||||
#include "otg_whitelist.h"
|
#include "otg_whitelist.h"
|
||||||
|
@ -1257,9 +1242,10 @@ int usb_new_device(struct usb_device *udev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read the standard strings and cache them if present */
|
/* read the standard strings and cache them if present */
|
||||||
get_string(udev, &udev->product, udev->descriptor.iProduct);
|
udev->product = usb_cache_string(udev, udev->descriptor.iProduct);
|
||||||
get_string(udev, &udev->manufacturer, udev->descriptor.iManufacturer);
|
udev->manufacturer = usb_cache_string(udev,
|
||||||
get_string(udev, &udev->serial, udev->descriptor.iSerialNumber);
|
udev->descriptor.iManufacturer);
|
||||||
|
udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);
|
||||||
|
|
||||||
/* Tell the world! */
|
/* Tell the world! */
|
||||||
dev_dbg(&udev->dev, "new device strings: Mfr=%d, Product=%d, "
|
dev_dbg(&udev->dev, "new device strings: Mfr=%d, Product=%d, "
|
||||||
|
|
|
@ -787,6 +787,31 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* usb_cache_string - read a string descriptor and cache it for later use
|
||||||
|
* @udev: the device whose string descriptor is being read
|
||||||
|
* @index: the descriptor index
|
||||||
|
*
|
||||||
|
* Returns a pointer to a kmalloc'ed buffer containing the descriptor string,
|
||||||
|
* or NULL if the index is 0 or the string could not be read.
|
||||||
|
*/
|
||||||
|
char *usb_cache_string(struct usb_device *udev, int index)
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
char *smallbuf = NULL;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (index > 0 && (buf = kmalloc(256, GFP_KERNEL)) != NULL) {
|
||||||
|
if ((len = usb_string(udev, index, buf, 256)) > 0) {
|
||||||
|
if ((smallbuf = kmalloc(++len, GFP_KERNEL)) == NULL)
|
||||||
|
return buf;
|
||||||
|
memcpy(smallbuf, buf, len);
|
||||||
|
}
|
||||||
|
kfree(buf);
|
||||||
|
}
|
||||||
|
return smallbuf;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* usb_get_device_descriptor - (re)reads the device descriptor (usbcore)
|
* usb_get_device_descriptor - (re)reads the device descriptor (usbcore)
|
||||||
* @dev: the device whose device descriptor is being updated
|
* @dev: the device whose device descriptor is being updated
|
||||||
|
@ -1008,8 +1033,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
|
||||||
dev_dbg (&dev->dev, "unregistering interface %s\n",
|
dev_dbg (&dev->dev, "unregistering interface %s\n",
|
||||||
interface->dev.bus_id);
|
interface->dev.bus_id);
|
||||||
usb_remove_sysfs_intf_files(interface);
|
usb_remove_sysfs_intf_files(interface);
|
||||||
kfree(interface->cur_altsetting->string);
|
|
||||||
interface->cur_altsetting->string = NULL;
|
|
||||||
device_del (&interface->dev);
|
device_del (&interface->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1422,12 +1445,9 @@ free_interfaces:
|
||||||
}
|
}
|
||||||
kfree(new_interfaces);
|
kfree(new_interfaces);
|
||||||
|
|
||||||
if ((cp->desc.iConfiguration) &&
|
if (cp->string == NULL)
|
||||||
(cp->string == NULL)) {
|
cp->string = usb_cache_string(dev,
|
||||||
cp->string = kmalloc(256, GFP_KERNEL);
|
cp->desc.iConfiguration);
|
||||||
if (cp->string)
|
|
||||||
usb_string(dev, cp->desc.iConfiguration, cp->string, 256);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now that all the interfaces are set up, register them
|
/* Now that all the interfaces are set up, register them
|
||||||
* to trigger binding of drivers to interfaces. probe()
|
* to trigger binding of drivers to interfaces. probe()
|
||||||
|
@ -1437,13 +1457,12 @@ free_interfaces:
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < nintf; ++i) {
|
for (i = 0; i < nintf; ++i) {
|
||||||
struct usb_interface *intf = cp->interface[i];
|
struct usb_interface *intf = cp->interface[i];
|
||||||
struct usb_interface_descriptor *desc;
|
struct usb_host_interface *alt = intf->cur_altsetting;
|
||||||
|
|
||||||
desc = &intf->altsetting [0].desc;
|
|
||||||
dev_dbg (&dev->dev,
|
dev_dbg (&dev->dev,
|
||||||
"adding %s (config #%d, interface %d)\n",
|
"adding %s (config #%d, interface %d)\n",
|
||||||
intf->dev.bus_id, configuration,
|
intf->dev.bus_id, configuration,
|
||||||
desc->bInterfaceNumber);
|
alt->desc.bInterfaceNumber);
|
||||||
ret = device_add (&intf->dev);
|
ret = device_add (&intf->dev);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
dev_err(&dev->dev,
|
dev_err(&dev->dev,
|
||||||
|
@ -1452,13 +1471,6 @@ free_interfaces:
|
||||||
ret);
|
ret);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((intf->cur_altsetting->desc.iInterface) &&
|
|
||||||
(intf->cur_altsetting->string == NULL)) {
|
|
||||||
intf->cur_altsetting->string = kmalloc(256, GFP_KERNEL);
|
|
||||||
if (intf->cur_altsetting->string)
|
|
||||||
usb_string(dev, intf->cur_altsetting->desc.iInterface,
|
|
||||||
intf->cur_altsetting->string, 256);
|
|
||||||
}
|
|
||||||
usb_create_sysfs_intf_files (intf);
|
usb_create_sysfs_intf_files (intf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -249,18 +249,12 @@ static ssize_t show_configuration_string(struct device *dev,
|
||||||
{
|
{
|
||||||
struct usb_device *udev;
|
struct usb_device *udev;
|
||||||
struct usb_host_config *actconfig;
|
struct usb_host_config *actconfig;
|
||||||
int len;
|
|
||||||
|
|
||||||
udev = to_usb_device (dev);
|
udev = to_usb_device (dev);
|
||||||
actconfig = udev->actconfig;
|
actconfig = udev->actconfig;
|
||||||
if ((!actconfig) || (!actconfig->string))
|
if ((!actconfig) || (!actconfig->string))
|
||||||
return 0;
|
return 0;
|
||||||
len = sprintf(buf, actconfig->string, PAGE_SIZE);
|
return sprintf(buf, "%s\n", actconfig->string);
|
||||||
if (len < 0)
|
|
||||||
return 0;
|
|
||||||
buf[len] = '\n';
|
|
||||||
buf[len+1] = 0;
|
|
||||||
return len+1;
|
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL);
|
static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL);
|
||||||
|
|
||||||
|
@ -291,15 +285,9 @@ static ssize_t show_##name(struct device *dev, \
|
||||||
struct device_attribute *attr, char *buf) \
|
struct device_attribute *attr, char *buf) \
|
||||||
{ \
|
{ \
|
||||||
struct usb_device *udev; \
|
struct usb_device *udev; \
|
||||||
int len; \
|
|
||||||
\
|
\
|
||||||
udev = to_usb_device (dev); \
|
udev = to_usb_device (dev); \
|
||||||
len = snprintf(buf, 256, "%s", udev->name); \
|
return sprintf(buf, "%s\n", udev->name); \
|
||||||
if (len < 0) \
|
|
||||||
return 0; \
|
|
||||||
buf[len] = '\n'; \
|
|
||||||
buf[len+1] = 0; \
|
|
||||||
return len+1; \
|
|
||||||
} \
|
} \
|
||||||
static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
|
static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
|
||||||
|
|
||||||
|
@ -449,11 +437,11 @@ void usb_remove_sysfs_dev_files (struct usb_device *udev)
|
||||||
usb_remove_ep_files(&udev->ep0);
|
usb_remove_ep_files(&udev->ep0);
|
||||||
sysfs_remove_group(&dev->kobj, &dev_attr_grp);
|
sysfs_remove_group(&dev->kobj, &dev_attr_grp);
|
||||||
|
|
||||||
if (udev->descriptor.iManufacturer)
|
if (udev->manufacturer)
|
||||||
device_remove_file(dev, &dev_attr_manufacturer);
|
device_remove_file(dev, &dev_attr_manufacturer);
|
||||||
if (udev->descriptor.iProduct)
|
if (udev->product)
|
||||||
device_remove_file(dev, &dev_attr_product);
|
device_remove_file(dev, &dev_attr_product);
|
||||||
if (udev->descriptor.iSerialNumber)
|
if (udev->serial)
|
||||||
device_remove_file(dev, &dev_attr_serial);
|
device_remove_file(dev, &dev_attr_serial);
|
||||||
device_remove_file (dev, &dev_attr_configuration);
|
device_remove_file (dev, &dev_attr_configuration);
|
||||||
}
|
}
|
||||||
|
@ -535,7 +523,8 @@ static struct attribute_group intf_attr_grp = {
|
||||||
.attrs = intf_attrs,
|
.attrs = intf_attrs,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void usb_create_intf_ep_files(struct usb_interface *intf)
|
static inline void usb_create_intf_ep_files(struct usb_interface *intf,
|
||||||
|
struct usb_device *udev)
|
||||||
{
|
{
|
||||||
struct usb_host_interface *iface_desc;
|
struct usb_host_interface *iface_desc;
|
||||||
int i;
|
int i;
|
||||||
|
@ -543,7 +532,7 @@ static inline void usb_create_intf_ep_files(struct usb_interface *intf)
|
||||||
iface_desc = intf->cur_altsetting;
|
iface_desc = intf->cur_altsetting;
|
||||||
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
|
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
|
||||||
usb_create_ep_files(&intf->dev.kobj, &iface_desc->endpoint[i],
|
usb_create_ep_files(&intf->dev.kobj, &iface_desc->endpoint[i],
|
||||||
interface_to_usbdev(intf));
|
udev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void usb_remove_intf_ep_files(struct usb_interface *intf)
|
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)
|
||||||
|
|
||||||
void usb_create_sysfs_intf_files (struct usb_interface *intf)
|
void usb_create_sysfs_intf_files (struct usb_interface *intf)
|
||||||
{
|
{
|
||||||
|
struct usb_device *udev = interface_to_usbdev(intf);
|
||||||
|
struct usb_host_interface *alt = intf->cur_altsetting;
|
||||||
|
|
||||||
sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
|
sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
|
||||||
|
|
||||||
if (intf->cur_altsetting->string)
|
if (alt->string == NULL)
|
||||||
|
alt->string = usb_cache_string(udev, alt->desc.iInterface);
|
||||||
|
if (alt->string)
|
||||||
device_create_file(&intf->dev, &dev_attr_interface);
|
device_create_file(&intf->dev, &dev_attr_interface);
|
||||||
usb_create_intf_ep_files(intf);
|
usb_create_intf_ep_files(intf, udev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_remove_sysfs_intf_files (struct usb_interface *intf)
|
void usb_remove_sysfs_intf_files (struct usb_interface *intf)
|
||||||
|
|
|
@ -13,6 +13,7 @@ extern void usb_disable_device (struct usb_device *dev, int skip_ep0);
|
||||||
|
|
||||||
extern int usb_get_device_descriptor(struct usb_device *dev,
|
extern int usb_get_device_descriptor(struct usb_device *dev,
|
||||||
unsigned int size);
|
unsigned int size);
|
||||||
|
extern char *usb_cache_string(struct usb_device *udev, int index);
|
||||||
extern int usb_set_configuration(struct usb_device *dev, int configuration);
|
extern int usb_set_configuration(struct usb_device *dev, int configuration);
|
||||||
|
|
||||||
extern void usb_lock_all_devices(void);
|
extern void usb_lock_all_devices(void);
|
||||||
|
|
|
@ -231,7 +231,7 @@ struct usb_interface_cache {
|
||||||
struct usb_host_config {
|
struct usb_host_config {
|
||||||
struct usb_config_descriptor desc;
|
struct usb_config_descriptor desc;
|
||||||
|
|
||||||
char *string;
|
char *string; /* iConfiguration string, if present */
|
||||||
/* the interfaces associated with this configuration,
|
/* the interfaces associated with this configuration,
|
||||||
* stored in no particular order */
|
* stored in no particular order */
|
||||||
struct usb_interface *interface[USB_MAXINTERFACES];
|
struct usb_interface *interface[USB_MAXINTERFACES];
|
||||||
|
@ -351,9 +351,11 @@ struct usb_device {
|
||||||
int have_langid; /* whether string_langid is valid */
|
int have_langid; /* whether string_langid is valid */
|
||||||
int string_langid; /* language ID for strings */
|
int string_langid; /* language ID for strings */
|
||||||
|
|
||||||
char *product;
|
/* static strings from the device */
|
||||||
char *manufacturer;
|
char *product; /* iProduct string, if present */
|
||||||
char *serial; /* static strings from the device */
|
char *manufacturer; /* iManufacturer string, if present */
|
||||||
|
char *serial; /* iSerialNumber string, if present */
|
||||||
|
|
||||||
struct list_head filelist;
|
struct list_head filelist;
|
||||||
struct class_device *class_dev;
|
struct class_device *class_dev;
|
||||||
struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */
|
struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */
|
||||||
|
|
Loading…
Reference in a new issue