at v2.6.21 457 lines 12 kB view raw
1/* 2 * drivers/usb/core/sysfs.c 3 * 4 * (C) Copyright 2002 David Brownell 5 * (C) Copyright 2002,2004 Greg Kroah-Hartman 6 * (C) Copyright 2002,2004 IBM Corp. 7 * 8 * All of the sysfs file attributes for usb devices and interfaces. 9 * 10 */ 11 12 13#include <linux/kernel.h> 14#include <linux/usb.h> 15#include "usb.h" 16 17/* Active configuration fields */ 18#define usb_actconfig_show(field, multiplier, format_string) \ 19static ssize_t show_##field(struct device *dev, \ 20 struct device_attribute *attr, char *buf) \ 21{ \ 22 struct usb_device *udev; \ 23 struct usb_host_config *actconfig; \ 24 \ 25 udev = to_usb_device(dev); \ 26 actconfig = udev->actconfig; \ 27 if (actconfig) \ 28 return sprintf(buf, format_string, \ 29 actconfig->desc.field * multiplier); \ 30 else \ 31 return 0; \ 32} \ 33 34#define usb_actconfig_attr(field, multiplier, format_string) \ 35usb_actconfig_show(field, multiplier, format_string) \ 36static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL); 37 38usb_actconfig_attr(bNumInterfaces, 1, "%2d\n") 39usb_actconfig_attr(bmAttributes, 1, "%2x\n") 40usb_actconfig_attr(bMaxPower, 2, "%3dmA\n") 41 42static ssize_t show_configuration_string(struct device *dev, 43 struct device_attribute *attr, char *buf) 44{ 45 struct usb_device *udev; 46 struct usb_host_config *actconfig; 47 48 udev = to_usb_device(dev); 49 actconfig = udev->actconfig; 50 if ((!actconfig) || (!actconfig->string)) 51 return 0; 52 return sprintf(buf, "%s\n", actconfig->string); 53} 54static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL); 55 56/* configuration value is always present, and r/w */ 57usb_actconfig_show(bConfigurationValue, 1, "%u\n"); 58 59static ssize_t 60set_bConfigurationValue(struct device *dev, struct device_attribute *attr, 61 const char *buf, size_t count) 62{ 63 struct usb_device *udev = to_usb_device(dev); 64 int config, value; 65 66 if (sscanf(buf, "%d", &config) != 1 || config < -1 || config > 255) 67 return -EINVAL; 68 usb_lock_device(udev); 69 value = usb_set_configuration(udev, config); 70 usb_unlock_device(udev); 71 return (value < 0) ? value : count; 72} 73 74static DEVICE_ATTR(bConfigurationValue, S_IRUGO | S_IWUSR, 75 show_bConfigurationValue, set_bConfigurationValue); 76 77/* String fields */ 78#define usb_string_attr(name) \ 79static ssize_t show_##name(struct device *dev, \ 80 struct device_attribute *attr, char *buf) \ 81{ \ 82 struct usb_device *udev; \ 83 \ 84 udev = to_usb_device(dev); \ 85 return sprintf(buf, "%s\n", udev->name); \ 86} \ 87static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); 88 89usb_string_attr(product); 90usb_string_attr(manufacturer); 91usb_string_attr(serial); 92 93static ssize_t 94show_speed(struct device *dev, struct device_attribute *attr, char *buf) 95{ 96 struct usb_device *udev; 97 char *speed; 98 99 udev = to_usb_device(dev); 100 101 switch (udev->speed) { 102 case USB_SPEED_LOW: 103 speed = "1.5"; 104 break; 105 case USB_SPEED_UNKNOWN: 106 case USB_SPEED_FULL: 107 speed = "12"; 108 break; 109 case USB_SPEED_HIGH: 110 speed = "480"; 111 break; 112 default: 113 speed = "unknown"; 114 } 115 return sprintf(buf, "%s\n", speed); 116} 117static DEVICE_ATTR(speed, S_IRUGO, show_speed, NULL); 118 119static ssize_t 120show_devnum(struct device *dev, struct device_attribute *attr, char *buf) 121{ 122 struct usb_device *udev; 123 124 udev = to_usb_device(dev); 125 return sprintf(buf, "%d\n", udev->devnum); 126} 127static DEVICE_ATTR(devnum, S_IRUGO, show_devnum, NULL); 128 129static ssize_t 130show_version(struct device *dev, struct device_attribute *attr, char *buf) 131{ 132 struct usb_device *udev; 133 u16 bcdUSB; 134 135 udev = to_usb_device(dev); 136 bcdUSB = le16_to_cpu(udev->descriptor.bcdUSB); 137 return sprintf(buf, "%2x.%02x\n", bcdUSB >> 8, bcdUSB & 0xff); 138} 139static DEVICE_ATTR(version, S_IRUGO, show_version, NULL); 140 141static ssize_t 142show_maxchild(struct device *dev, struct device_attribute *attr, char *buf) 143{ 144 struct usb_device *udev; 145 146 udev = to_usb_device(dev); 147 return sprintf(buf, "%d\n", udev->maxchild); 148} 149static DEVICE_ATTR(maxchild, S_IRUGO, show_maxchild, NULL); 150 151static ssize_t 152show_quirks(struct device *dev, struct device_attribute *attr, char *buf) 153{ 154 struct usb_device *udev; 155 156 udev = to_usb_device(dev); 157 return sprintf(buf, "0x%x\n", udev->quirks); 158} 159static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL); 160 161#ifdef CONFIG_USB_SUSPEND 162 163static ssize_t 164show_autosuspend(struct device *dev, struct device_attribute *attr, char *buf) 165{ 166 struct usb_device *udev = to_usb_device(dev); 167 168 return sprintf(buf, "%u\n", udev->autosuspend_delay / HZ); 169} 170 171static ssize_t 172set_autosuspend(struct device *dev, struct device_attribute *attr, 173 const char *buf, size_t count) 174{ 175 struct usb_device *udev = to_usb_device(dev); 176 unsigned value, old; 177 178 if (sscanf(buf, "%u", &value) != 1 || value >= INT_MAX/HZ) 179 return -EINVAL; 180 value *= HZ; 181 182 old = udev->autosuspend_delay; 183 udev->autosuspend_delay = value; 184 if (value > 0 && old == 0) 185 usb_try_autosuspend_device(udev); 186 187 return count; 188} 189 190static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR, 191 show_autosuspend, set_autosuspend); 192 193static char power_group[] = "power"; 194 195static int add_power_attributes(struct device *dev) 196{ 197 int rc = 0; 198 199 if (is_usb_device(dev)) 200 rc = sysfs_add_file_to_group(&dev->kobj, 201 &dev_attr_autosuspend.attr, 202 power_group); 203 return rc; 204} 205 206static void remove_power_attributes(struct device *dev) 207{ 208 sysfs_remove_file_from_group(&dev->kobj, 209 &dev_attr_autosuspend.attr, 210 power_group); 211} 212 213#else 214 215#define add_power_attributes(dev) 0 216#define remove_power_attributes(dev) do {} while (0) 217 218#endif /* CONFIG_USB_SUSPEND */ 219 220/* Descriptor fields */ 221#define usb_descriptor_attr_le16(field, format_string) \ 222static ssize_t \ 223show_##field(struct device *dev, struct device_attribute *attr, \ 224 char *buf) \ 225{ \ 226 struct usb_device *udev; \ 227 \ 228 udev = to_usb_device(dev); \ 229 return sprintf(buf, format_string, \ 230 le16_to_cpu(udev->descriptor.field)); \ 231} \ 232static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL); 233 234usb_descriptor_attr_le16(idVendor, "%04x\n") 235usb_descriptor_attr_le16(idProduct, "%04x\n") 236usb_descriptor_attr_le16(bcdDevice, "%04x\n") 237 238#define usb_descriptor_attr(field, format_string) \ 239static ssize_t \ 240show_##field(struct device *dev, struct device_attribute *attr, \ 241 char *buf) \ 242{ \ 243 struct usb_device *udev; \ 244 \ 245 udev = to_usb_device(dev); \ 246 return sprintf(buf, format_string, udev->descriptor.field); \ 247} \ 248static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL); 249 250usb_descriptor_attr(bDeviceClass, "%02x\n") 251usb_descriptor_attr(bDeviceSubClass, "%02x\n") 252usb_descriptor_attr(bDeviceProtocol, "%02x\n") 253usb_descriptor_attr(bNumConfigurations, "%d\n") 254usb_descriptor_attr(bMaxPacketSize0, "%d\n") 255 256static struct attribute *dev_attrs[] = { 257 /* current configuration's attributes */ 258 &dev_attr_configuration.attr, 259 &dev_attr_bNumInterfaces.attr, 260 &dev_attr_bConfigurationValue.attr, 261 &dev_attr_bmAttributes.attr, 262 &dev_attr_bMaxPower.attr, 263 /* device attributes */ 264 &dev_attr_idVendor.attr, 265 &dev_attr_idProduct.attr, 266 &dev_attr_bcdDevice.attr, 267 &dev_attr_bDeviceClass.attr, 268 &dev_attr_bDeviceSubClass.attr, 269 &dev_attr_bDeviceProtocol.attr, 270 &dev_attr_bNumConfigurations.attr, 271 &dev_attr_bMaxPacketSize0.attr, 272 &dev_attr_speed.attr, 273 &dev_attr_devnum.attr, 274 &dev_attr_version.attr, 275 &dev_attr_maxchild.attr, 276 &dev_attr_quirks.attr, 277 NULL, 278}; 279static struct attribute_group dev_attr_grp = { 280 .attrs = dev_attrs, 281}; 282 283int usb_create_sysfs_dev_files(struct usb_device *udev) 284{ 285 struct device *dev = &udev->dev; 286 int retval; 287 288 retval = sysfs_create_group(&dev->kobj, &dev_attr_grp); 289 if (retval) 290 return retval; 291 292 retval = add_power_attributes(dev); 293 if (retval) 294 goto error; 295 296 if (udev->manufacturer) { 297 retval = device_create_file(dev, &dev_attr_manufacturer); 298 if (retval) 299 goto error; 300 } 301 if (udev->product) { 302 retval = device_create_file(dev, &dev_attr_product); 303 if (retval) 304 goto error; 305 } 306 if (udev->serial) { 307 retval = device_create_file(dev, &dev_attr_serial); 308 if (retval) 309 goto error; 310 } 311 retval = usb_create_ep_files(dev, &udev->ep0, udev); 312 if (retval) 313 goto error; 314 return 0; 315error: 316 usb_remove_sysfs_dev_files(udev); 317 return retval; 318} 319 320void usb_remove_sysfs_dev_files(struct usb_device *udev) 321{ 322 struct device *dev = &udev->dev; 323 324 usb_remove_ep_files(&udev->ep0); 325 device_remove_file(dev, &dev_attr_manufacturer); 326 device_remove_file(dev, &dev_attr_product); 327 device_remove_file(dev, &dev_attr_serial); 328 remove_power_attributes(dev); 329 sysfs_remove_group(&dev->kobj, &dev_attr_grp); 330} 331 332/* Interface fields */ 333#define usb_intf_attr(field, format_string) \ 334static ssize_t \ 335show_##field(struct device *dev, struct device_attribute *attr, \ 336 char *buf) \ 337{ \ 338 struct usb_interface *intf = to_usb_interface(dev); \ 339 \ 340 return sprintf(buf, format_string, \ 341 intf->cur_altsetting->desc.field); \ 342} \ 343static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL); 344 345usb_intf_attr(bInterfaceNumber, "%02x\n") 346usb_intf_attr(bAlternateSetting, "%2d\n") 347usb_intf_attr(bNumEndpoints, "%02x\n") 348usb_intf_attr(bInterfaceClass, "%02x\n") 349usb_intf_attr(bInterfaceSubClass, "%02x\n") 350usb_intf_attr(bInterfaceProtocol, "%02x\n") 351 352static ssize_t show_interface_string(struct device *dev, 353 struct device_attribute *attr, char *buf) 354{ 355 struct usb_interface *intf; 356 struct usb_device *udev; 357 int len; 358 359 intf = to_usb_interface(dev); 360 udev = interface_to_usbdev(intf); 361 len = snprintf(buf, 256, "%s", intf->cur_altsetting->string); 362 if (len < 0) 363 return 0; 364 buf[len] = '\n'; 365 buf[len+1] = 0; 366 return len+1; 367} 368static DEVICE_ATTR(interface, S_IRUGO, show_interface_string, NULL); 369 370static ssize_t show_modalias(struct device *dev, 371 struct device_attribute *attr, char *buf) 372{ 373 struct usb_interface *intf; 374 struct usb_device *udev; 375 struct usb_host_interface *alt; 376 377 intf = to_usb_interface(dev); 378 udev = interface_to_usbdev(intf); 379 alt = intf->cur_altsetting; 380 381 return sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X" 382 "ic%02Xisc%02Xip%02X\n", 383 le16_to_cpu(udev->descriptor.idVendor), 384 le16_to_cpu(udev->descriptor.idProduct), 385 le16_to_cpu(udev->descriptor.bcdDevice), 386 udev->descriptor.bDeviceClass, 387 udev->descriptor.bDeviceSubClass, 388 udev->descriptor.bDeviceProtocol, 389 alt->desc.bInterfaceClass, 390 alt->desc.bInterfaceSubClass, 391 alt->desc.bInterfaceProtocol); 392} 393static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); 394 395static struct attribute *intf_attrs[] = { 396 &dev_attr_bInterfaceNumber.attr, 397 &dev_attr_bAlternateSetting.attr, 398 &dev_attr_bNumEndpoints.attr, 399 &dev_attr_bInterfaceClass.attr, 400 &dev_attr_bInterfaceSubClass.attr, 401 &dev_attr_bInterfaceProtocol.attr, 402 &dev_attr_modalias.attr, 403 NULL, 404}; 405static struct attribute_group intf_attr_grp = { 406 .attrs = intf_attrs, 407}; 408 409static inline void usb_create_intf_ep_files(struct usb_interface *intf, 410 struct usb_device *udev) 411{ 412 struct usb_host_interface *iface_desc; 413 int i; 414 415 iface_desc = intf->cur_altsetting; 416 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) 417 usb_create_ep_files(&intf->dev, &iface_desc->endpoint[i], 418 udev); 419} 420 421static inline void usb_remove_intf_ep_files(struct usb_interface *intf) 422{ 423 struct usb_host_interface *iface_desc; 424 int i; 425 426 iface_desc = intf->cur_altsetting; 427 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) 428 usb_remove_ep_files(&iface_desc->endpoint[i]); 429} 430 431int usb_create_sysfs_intf_files(struct usb_interface *intf) 432{ 433 struct device *dev = &intf->dev; 434 struct usb_device *udev = interface_to_usbdev(intf); 435 struct usb_host_interface *alt = intf->cur_altsetting; 436 int retval; 437 438 retval = sysfs_create_group(&dev->kobj, &intf_attr_grp); 439 if (retval) 440 return retval; 441 442 if (alt->string == NULL) 443 alt->string = usb_cache_string(udev, alt->desc.iInterface); 444 if (alt->string) 445 retval = device_create_file(dev, &dev_attr_interface); 446 usb_create_intf_ep_files(intf, udev); 447 return 0; 448} 449 450void usb_remove_sysfs_intf_files(struct usb_interface *intf) 451{ 452 struct device *dev = &intf->dev; 453 454 usb_remove_intf_ep_files(intf); 455 device_remove_file(dev, &dev_attr_interface); 456 sysfs_remove_group(&dev->kobj, &intf_attr_grp); 457}