/*
* drivers/usb/core/sysfs.c
*
* (C) Copyright 2002 David Brownell
* (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 <linux/kernel.h>
#include <linux/string.h>
#include <linux/usb.h>
#include <linux/usb/quirks.h>
#include "usb.h"
/* Active configuration fields */
#define usb_actconfig_show(field, format_string) \
static ssize_t field##_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct usb_device *udev; \
struct usb_host_config *actconfig; \
ssize_t rc = 0; \
\
udev = to_usb_device(dev); \
usb_lock_device(udev); \
actconfig = udev->actconfig; \
if (actconfig) \
rc = sprintf(buf, format_string, \
actconfig->desc.field); \
usb_unlock_device(udev); \
return rc; \
} \
#define usb_actconfig_attr(field, format_string) \
usb_actconfig_show(field, format_string) \
static DEVICE_ATTR_RO(field)
usb_actconfig_attr(bNumInterfaces, "%2d\n");
usb_actconfig_attr(bmAttributes, "%2x\n");
static ssize_t bMaxPower_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_device *udev;
struct usb_host_config *actconfig;
ssize_t rc = 0;
udev = to_usb_device(dev);
usb_lock_device(udev);
actconfig = udev->actconfig;
if (actconfig)
rc = sprintf(buf, "%dmA\n", usb_get_max_power(udev, actconfig));
usb_unlock_device(udev);
return rc;
}
static DEVICE_ATTR_RO(bMaxPower);
static ssize_t configuration_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_device *udev;
struct usb_host_config *actconfig;
ssize_t rc = 0;
udev = to_usb_device(dev);
usb_lock_device(udev);
actconfig = udev->actconfig;
if (actconfig && actconfig->string)
rc = sprintf(buf, "%s\n", actconfig->string);
usb_unlock_device(udev);
return rc;
}
static DEVICE_ATTR_RO(configuration);
/* configuration value is always present, and r/w */
usb_actconfig_show(bConfigurationValue, "%u\n");
static ssize_t bConfigurationValue_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct usb_device *udev = to_usb_device(dev);
int config, value;
if (sscanf(buf, "%d", &config) != 1 || config < -1 || config > 255)
return -EINVAL;
usb_lock_device(udev);
value = usb_set_configuration(udev, config);
usb_unlock_device(udev);
return (value < 0) ? value : count;
}
static DEVICE_ATTR_IGNORE_LOCKDEP(bConfigurationValue, S_IRUGO | S_IWUSR,
bConfigurationValue_show, bConfigurationValue_store);
/* String fields */
#define usb_string_attr(name) \
static ssize_t name##_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct usb_device *udev; \
int retval; \
\
udev = to_usb_device(dev); \
usb_lock_device(udev); \
retval = sprintf(buf, "%s\n", udev->name); \
usb_unlock_device(udev); \
return retval; \
} \
static DEVICE_ATTR_RO(name)
usb_string_attr(product);
usb_string_attr(manufacturer);
usb_string_attr(serial);
static ssize_t speed_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct usb_device *udev;
char *speed;
udev = to_usb_device(dev);
switch (udev->speed) {
case USB_SPEED_LOW:
speed = "1.5";
break;
case USB_SPEED_UNKNOWN:
case USB_SPEED_FULL:
speed = "12";
break;
case USB_SPEED_HIGH:
speed = "480";
break;
case USB_SPEED_WIRELESS:
speed = "480";
break;
case USB_SPEED_SUPER:
speed = "5000";
break;
default:
speed = "unknown";
}
return sprintf(buf, "%s\n", speed);
}
static DEVICE_ATTR_RO(speed);
static ssize_t busnum_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct usb_device *udev;
udev = to_usb_device(dev);
return sprintf(buf, "%d\n", udev->bus->busnum);
}
static DEVICE_ATTR_RO(busnum);
static ssize_t devnum_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct usb_device *udev;
udev = to_usb_device(dev);
return sprintf(buf, "%d\n", udev->devnum