X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Fcore%2Fsysfs.c;h=55d8f575206d6b1dcbfb0338e48a79b735a7ef9d;hb=refs%2Fremotes%2Fvserver;hp=38c64f656cf7a39887ec5f0ad540a448b8fece48;hpb=e812ccbe0c915857ebea6a632bfadc631f7504a9;p=linux-2.6.git diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 38c64f656..55d8f5752 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -2,36 +2,31 @@ * drivers/usb/core/sysfs.c * * (C) Copyright 2002 David Brownell - * (C) Copyright 2002 Greg Kroah-Hartman - * (C) Copyright 2002 IBM Corp. + * (C) Copyright 2002,2004 Greg Kroah-Hartman + * (C) Copyright 2002,2004 IBM Corp. * * All of the sysfs file attributes for usb devices and interfaces. * */ -#include #include - -#ifdef CONFIG_USB_DEBUG - #define DEBUG -#else - #undef DEBUG -#endif #include - #include "usb.h" /* Active configuration fields */ #define usb_actconfig_show(field, multiplier, format_string) \ -static ssize_t show_##field (struct device *dev, char *buf) \ +static ssize_t show_##field (struct device *dev, \ + struct device_attribute *attr, char *buf) \ { \ struct usb_device *udev; \ + struct usb_host_config *actconfig; \ \ udev = to_usb_device (dev); \ - if (udev->actconfig) \ + actconfig = udev->actconfig; \ + if (actconfig) \ return sprintf (buf, format_string, \ - udev->actconfig->desc.field * multiplier); \ + actconfig->desc.field * multiplier); \ else \ return 0; \ } \ @@ -44,20 +39,35 @@ usb_actconfig_attr (bNumInterfaces, 1, "%2d\n") usb_actconfig_attr (bmAttributes, 1, "%2x\n") usb_actconfig_attr (bMaxPower, 2, "%3dmA\n") +static ssize_t show_configuration_string(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_device *udev; + struct usb_host_config *actconfig; + + udev = to_usb_device (dev); + actconfig = udev->actconfig; + if ((!actconfig) || (!actconfig->string)) + return 0; + return sprintf(buf, "%s\n", actconfig->string); +} +static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL); + /* configuration value is always present, and r/w */ usb_actconfig_show(bConfigurationValue, 1, "%u\n"); static ssize_t -set_bConfigurationValue (struct device *dev, const char *buf, size_t count) +set_bConfigurationValue (struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { - struct usb_device *udev = udev = to_usb_device (dev); + struct usb_device *udev = to_usb_device (dev); int config, value; if (sscanf (buf, "%u", &config) != 1 || config > 255) return -EINVAL; - down(&udev->serialize); + usb_lock_device(udev); value = usb_set_configuration (udev, config); - up(&udev->serialize); + usb_unlock_device(udev); return (value < 0) ? value : count; } @@ -65,28 +75,23 @@ static DEVICE_ATTR(bConfigurationValue, S_IRUGO | S_IWUSR, show_bConfigurationValue, set_bConfigurationValue); /* String fields */ -#define usb_string_attr(name, field) \ -static ssize_t show_##name(struct device *dev, char *buf) \ +#define usb_string_attr(name) \ +static ssize_t show_##name(struct device *dev, \ + struct device_attribute *attr, char *buf) \ { \ struct usb_device *udev; \ - int len; \ \ udev = to_usb_device (dev); \ - len = usb_string(udev, udev->descriptor.field, buf, PAGE_SIZE); \ - if (len < 0) \ - return 0; \ - buf[len] = '\n'; \ - buf[len+1] = 0; \ - return len+1; \ + return sprintf(buf, "%s\n", udev->name); \ } \ static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); -usb_string_attr(product, iProduct); -usb_string_attr(manufacturer, iManufacturer); -usb_string_attr(serial, iSerialNumber); +usb_string_attr(product); +usb_string_attr(manufacturer); +usb_string_attr(serial); static ssize_t -show_speed (struct device *dev, char *buf) +show_speed (struct device *dev, struct device_attribute *attr, char *buf) { struct usb_device *udev; char *speed; @@ -112,7 +117,7 @@ show_speed (struct device *dev, char *buf) static DEVICE_ATTR(speed, S_IRUGO, show_speed, NULL); static ssize_t -show_devnum (struct device *dev, char *buf) +show_devnum (struct device *dev, struct device_attribute *attr, char *buf) { struct usb_device *udev; @@ -122,18 +127,19 @@ show_devnum (struct device *dev, char *buf) static DEVICE_ATTR(devnum, S_IRUGO, show_devnum, NULL); static ssize_t -show_version (struct device *dev, char *buf) +show_version (struct device *dev, struct device_attribute *attr, char *buf) { struct usb_device *udev; + u16 bcdUSB; - udev = to_usb_device (dev); - return sprintf (buf, "%2x.%02x\n", udev->descriptor.bcdUSB >> 8, - udev->descriptor.bcdUSB & 0xff); + udev = to_usb_device(dev); + bcdUSB = le16_to_cpu(udev->descriptor.bcdUSB); + return sprintf(buf, "%2x.%02x\n", bcdUSB >> 8, bcdUSB & 0xff); } static DEVICE_ATTR(version, S_IRUGO, show_version, NULL); static ssize_t -show_maxchild (struct device *dev, char *buf) +show_maxchild (struct device *dev, struct device_attribute *attr, char *buf) { struct usb_device *udev; @@ -143,9 +149,27 @@ show_maxchild (struct device *dev, char *buf) static DEVICE_ATTR(maxchild, S_IRUGO, show_maxchild, NULL); /* Descriptor fields */ +#define usb_descriptor_attr_le16(field, format_string) \ +static ssize_t \ +show_##field (struct device *dev, struct device_attribute *attr, \ + char *buf) \ +{ \ + struct usb_device *udev; \ + \ + udev = to_usb_device (dev); \ + return sprintf (buf, format_string, \ + le16_to_cpu(udev->descriptor.field)); \ +} \ +static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL); + +usb_descriptor_attr_le16(idVendor, "%04x\n") +usb_descriptor_attr_le16(idProduct, "%04x\n") +usb_descriptor_attr_le16(bcdDevice, "%04x\n") + #define usb_descriptor_attr(field, format_string) \ static ssize_t \ -show_##field (struct device *dev, char *buf) \ +show_##field (struct device *dev, struct device_attribute *attr, \ + char *buf) \ { \ struct usb_device *udev; \ \ @@ -154,58 +178,99 @@ show_##field (struct device *dev, char *buf) \ } \ static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL); -usb_descriptor_attr (idVendor, "%04x\n") -usb_descriptor_attr (idProduct, "%04x\n") -usb_descriptor_attr (bcdDevice, "%04x\n") usb_descriptor_attr (bDeviceClass, "%02x\n") usb_descriptor_attr (bDeviceSubClass, "%02x\n") usb_descriptor_attr (bDeviceProtocol, "%02x\n") usb_descriptor_attr (bNumConfigurations, "%d\n") +usb_descriptor_attr (bMaxPacketSize0, "%d\n") + +static struct attribute *dev_attrs[] = { + /* current configuration's attributes */ + &dev_attr_configuration.attr, + &dev_attr_bNumInterfaces.attr, + &dev_attr_bConfigurationValue.attr, + &dev_attr_bmAttributes.attr, + &dev_attr_bMaxPower.attr, + /* device attributes */ + &dev_attr_idVendor.attr, + &dev_attr_idProduct.attr, + &dev_attr_bcdDevice.attr, + &dev_attr_bDeviceClass.attr, + &dev_attr_bDeviceSubClass.attr, + &dev_attr_bDeviceProtocol.attr, + &dev_attr_bNumConfigurations.attr, + &dev_attr_bMaxPacketSize0.attr, + &dev_attr_speed.attr, + &dev_attr_devnum.attr, + &dev_attr_version.attr, + &dev_attr_maxchild.attr, + NULL, +}; +static struct attribute_group dev_attr_grp = { + .attrs = dev_attrs, +}; + +int usb_create_sysfs_dev_files(struct usb_device *udev) +{ + struct device *dev = &udev->dev; + int retval; + + retval = sysfs_create_group(&dev->kobj, &dev_attr_grp); + if (retval) + return retval; + if (udev->manufacturer) { + retval = device_create_file (dev, &dev_attr_manufacturer); + if (retval) + goto error; + } + if (udev->product) { + retval = device_create_file (dev, &dev_attr_product); + if (retval) + goto error; + } + if (udev->serial) { + retval = device_create_file (dev, &dev_attr_serial); + if (retval) + goto error; + } + retval = usb_create_ep_files(dev, &udev->ep0, udev); + if (retval) + goto error; + return 0; +error: + usb_remove_ep_files(&udev->ep0); + device_remove_file(dev, &dev_attr_manufacturer); + device_remove_file(dev, &dev_attr_product); + device_remove_file(dev, &dev_attr_serial); + return retval; +} -void usb_create_sysfs_dev_files (struct usb_device *udev) +void usb_remove_sysfs_dev_files (struct usb_device *udev) { struct device *dev = &udev->dev; - /* current configuration's attributes */ - device_create_file (dev, &dev_attr_bNumInterfaces); - device_create_file (dev, &dev_attr_bConfigurationValue); - device_create_file (dev, &dev_attr_bmAttributes); - device_create_file (dev, &dev_attr_bMaxPower); + usb_remove_ep_files(&udev->ep0); + sysfs_remove_group(&dev->kobj, &dev_attr_grp); - /* device attributes */ - device_create_file (dev, &dev_attr_idVendor); - device_create_file (dev, &dev_attr_idProduct); - device_create_file (dev, &dev_attr_bcdDevice); - device_create_file (dev, &dev_attr_bDeviceClass); - device_create_file (dev, &dev_attr_bDeviceSubClass); - device_create_file (dev, &dev_attr_bDeviceProtocol); - device_create_file (dev, &dev_attr_bNumConfigurations); - - /* speed varies depending on how you connect the device */ - device_create_file (dev, &dev_attr_speed); - // FIXME iff there are other speed configs, show how many - - if (udev->descriptor.iManufacturer) - device_create_file (dev, &dev_attr_manufacturer); - if (udev->descriptor.iProduct) - device_create_file (dev, &dev_attr_product); - if (udev->descriptor.iSerialNumber) - device_create_file (dev, &dev_attr_serial); - - device_create_file (dev, &dev_attr_devnum); - device_create_file (dev, &dev_attr_version); - device_create_file (dev, &dev_attr_maxchild); + if (udev->manufacturer) + device_remove_file(dev, &dev_attr_manufacturer); + if (udev->product) + device_remove_file(dev, &dev_attr_product); + if (udev->serial) + device_remove_file(dev, &dev_attr_serial); } /* Interface fields */ #define usb_intf_attr(field, format_string) \ static ssize_t \ -show_##field (struct device *dev, char *buf) \ +show_##field (struct device *dev, struct device_attribute *attr, \ + char *buf) \ { \ struct usb_interface *intf = to_usb_interface (dev); \ \ - return sprintf (buf, format_string, intf->cur_altsetting->desc.field); \ + return sprintf (buf, format_string, \ + intf->cur_altsetting->desc.field); \ } \ static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL); @@ -215,15 +280,115 @@ usb_intf_attr (bNumEndpoints, "%02x\n") usb_intf_attr (bInterfaceClass, "%02x\n") usb_intf_attr (bInterfaceSubClass, "%02x\n") usb_intf_attr (bInterfaceProtocol, "%02x\n") -usb_intf_attr (iInterface, "%02x\n") -void usb_create_sysfs_intf_files (struct usb_interface *intf) +static ssize_t show_interface_string(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_interface *intf; + struct usb_device *udev; + int len; + + intf = to_usb_interface (dev); + udev = interface_to_usbdev (intf); + len = snprintf(buf, 256, "%s", intf->cur_altsetting->string); + if (len < 0) + return 0; + buf[len] = '\n'; + buf[len+1] = 0; + return len+1; +} +static DEVICE_ATTR(interface, S_IRUGO, show_interface_string, NULL); + +static ssize_t show_modalias(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_interface *intf; + struct usb_device *udev; + struct usb_host_interface *alt; + + intf = to_usb_interface(dev); + udev = interface_to_usbdev(intf); + alt = intf->cur_altsetting; + + return sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X" + "ic%02Xisc%02Xip%02X\n", + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct), + le16_to_cpu(udev->descriptor.bcdDevice), + udev->descriptor.bDeviceClass, + udev->descriptor.bDeviceSubClass, + udev->descriptor.bDeviceProtocol, + alt->desc.bInterfaceClass, + alt->desc.bInterfaceSubClass, + alt->desc.bInterfaceProtocol); +} +static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); + +static struct attribute *intf_attrs[] = { + &dev_attr_bInterfaceNumber.attr, + &dev_attr_bAlternateSetting.attr, + &dev_attr_bNumEndpoints.attr, + &dev_attr_bInterfaceClass.attr, + &dev_attr_bInterfaceSubClass.attr, + &dev_attr_bInterfaceProtocol.attr, + &dev_attr_modalias.attr, + NULL, +}; +static struct attribute_group intf_attr_grp = { + .attrs = intf_attrs, +}; + +static inline void usb_create_intf_ep_files(struct usb_interface *intf, + struct usb_device *udev) { - device_create_file (&intf->dev, &dev_attr_bInterfaceNumber); - device_create_file (&intf->dev, &dev_attr_bAlternateSetting); - device_create_file (&intf->dev, &dev_attr_bNumEndpoints); - device_create_file (&intf->dev, &dev_attr_bInterfaceClass); - device_create_file (&intf->dev, &dev_attr_bInterfaceSubClass); - device_create_file (&intf->dev, &dev_attr_bInterfaceProtocol); - device_create_file (&intf->dev, &dev_attr_iInterface); + struct usb_host_interface *iface_desc; + int i; + + iface_desc = intf->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) + usb_create_ep_files(&intf->dev, &iface_desc->endpoint[i], + udev); +} + +static inline void usb_remove_intf_ep_files(struct usb_interface *intf) +{ + struct usb_host_interface *iface_desc; + int i; + + iface_desc = intf->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) + usb_remove_ep_files(&iface_desc->endpoint[i]); +} + +int 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; + int retval; + + retval = sysfs_create_group(&intf->dev.kobj, &intf_attr_grp); + if (retval) + goto error; + + if (alt->string == NULL) + alt->string = usb_cache_string(udev, alt->desc.iInterface); + if (alt->string) + retval = device_create_file(&intf->dev, &dev_attr_interface); + usb_create_intf_ep_files(intf, udev); + return 0; +error: + if (alt->string) + device_remove_file(&intf->dev, &dev_attr_interface); + sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp); + usb_remove_intf_ep_files(intf); + return retval; +} + +void usb_remove_sysfs_intf_files (struct usb_interface *intf) +{ + usb_remove_intf_ep_files(intf); + sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp); + + if (intf->cur_altsetting->string) + device_remove_file(&intf->dev, &dev_attr_interface); }