Commit 8e8f500e authored by Alex Kanavin's avatar Alex Kanavin Committed by Greg Kroah-Hartman

[PATCH] USB: export inteface and configuration strings to sysfs

 this patch adds exporting of configuration and interface strings to sysfs.

 both configuration and interface strings are present on my Nokia
 7610 phone, which can be connected via USB, and I thought it would be a
 good idea to make them easily accessible via sysfs:

 [root@cs181035096 usb1]# cat 1-1/manufacturer 1-1/product
 Nokia
 7610
 [root@cs181035096 usb1]# grep "" `find . -name configuration`
 ./1-1/configuration:First and Last and Always
 [root@cs181035096 usb1]# grep "" `find . -name interface`
 ./1-1/1-1:1.6/interface:CDC Data Interface
 ./1-1/1-1:1.5/interface:CDC Comms Interface
 ./1-1/1-1:1.3/interface:PC Suite Services
 ./1-1/1-1:1.1/interface:SYNCML-SYNC

 The first two interfaces are for accessing the GPRS modem, they are
 recognized and supported perfectly by the cdc_acm driver. The last two
 are CDC OBEX interfaces, for which there is no driver currently, but I plan to
 write one. This would allow userspace to do really nifty things, for
 example accessing the phone filesystem, and exchanging contacts and
 calendar entries via SyncML. Pretty much the same thing that Nokia PC
 Suite does. But the software needs to distinguish between the two OBEX
 interfaces (which is syncml and which is file transfer? the only way to
 know is to read the strings), and that"s why this patch was written.
Signed-off-by: default avatarAlex Kanavin <ak@sensi.org>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent c1e15eeb
......@@ -27,11 +27,13 @@
static ssize_t show_##field (struct device *dev, 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,6 +46,28 @@ usb_actconfig_attr (bNumInterfaces, 1, "%2d\n")
usb_actconfig_attr (bmAttributes, 1, "%2x\n")
usb_actconfig_attr (bMaxPower, 2, "%3dmA\n")
#define usb_actconfig_str(name, field) \
static ssize_t show_##name(struct device *dev, char *buf) \
{ \
struct usb_device *udev; \
struct usb_host_config *actconfig; \
int len; \
\
udev = to_usb_device (dev); \
actconfig = udev->actconfig; \
if (!actconfig) \
return 0; \
len = usb_string(udev, actconfig->desc.field, buf, PAGE_SIZE); \
if (len < 0) \
return 0; \
buf[len] = '\n'; \
buf[len+1] = 0; \
return len+1; \
} \
static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
usb_actconfig_str (configuration, iConfiguration)
/* configuration value is always present, and r/w */
usb_actconfig_show(bConfigurationValue, 1, "%u\n");
......@@ -198,6 +222,7 @@ void usb_create_sysfs_dev_files (struct usb_device *udev)
device_create_file (dev, &dev_attr_product);
if (udev->descriptor.iSerialNumber)
device_create_file (dev, &dev_attr_serial);
device_create_file (dev, &dev_attr_configuration);
}
void usb_remove_sysfs_dev_files (struct usb_device *udev)
......@@ -212,6 +237,7 @@ void usb_remove_sysfs_dev_files (struct usb_device *udev)
device_remove_file(dev, &dev_attr_product);
if (udev->descriptor.iSerialNumber)
device_remove_file(dev, &dev_attr_serial);
device_remove_file (dev, &dev_attr_configuration);
}
/* Interface fields */
......@@ -231,7 +257,26 @@ 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")
#define usb_intf_str(name, field) \
static ssize_t show_##name(struct device *dev, char *buf) \
{ \
struct usb_interface *intf; \
struct usb_device *udev; \
int len; \
\
intf = to_usb_interface (dev); \
udev = interface_to_usbdev (intf); \
len = usb_string(udev, intf->cur_altsetting->desc.field, buf, PAGE_SIZE);\
if (len < 0) \
return 0; \
buf[len] = '\n'; \
buf[len+1] = 0; \
return len+1; \
} \
static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
usb_intf_str (interface, iInterface);
static struct attribute *intf_attrs[] = {
&dev_attr_bInterfaceNumber.attr,
......@@ -240,7 +285,6 @@ static struct attribute *intf_attrs[] = {
&dev_attr_bInterfaceClass.attr,
&dev_attr_bInterfaceSubClass.attr,
&dev_attr_bInterfaceProtocol.attr,
&dev_attr_iInterface.attr,
NULL,
};
static struct attribute_group intf_attr_grp = {
......@@ -250,9 +294,17 @@ static struct attribute_group intf_attr_grp = {
void usb_create_sysfs_intf_files (struct usb_interface *intf)
{
sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
if (intf->cur_altsetting->desc.iInterface)
device_create_file(&intf->dev, &dev_attr_interface);
}
void usb_remove_sysfs_intf_files (struct usb_interface *intf)
{
sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
if (intf->cur_altsetting->desc.iInterface)
device_remove_file(&intf->dev, &dev_attr_interface);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment