|
@@ -441,6 +441,54 @@ static struct attribute_group dev_attr_grp = {
|
|
.attrs = dev_attrs,
|
|
.attrs = dev_attrs,
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+/* Binary descriptors */
|
|
|
|
+
|
|
|
|
+static ssize_t
|
|
|
|
+read_descriptors(struct kobject *kobj, struct bin_attribute *attr,
|
|
|
|
+ char *buf, loff_t off, size_t count)
|
|
|
|
+{
|
|
|
|
+ struct usb_device *udev = to_usb_device(
|
|
|
|
+ container_of(kobj, struct device, kobj));
|
|
|
|
+ size_t nleft = count;
|
|
|
|
+ size_t srclen, n;
|
|
|
|
+
|
|
|
|
+ usb_lock_device(udev);
|
|
|
|
+
|
|
|
|
+ /* The binary attribute begins with the device descriptor */
|
|
|
|
+ srclen = sizeof(struct usb_device_descriptor);
|
|
|
|
+ if (off < srclen) {
|
|
|
|
+ n = min_t(size_t, nleft, srclen - off);
|
|
|
|
+ memcpy(buf, off + (char *) &udev->descriptor, n);
|
|
|
|
+ nleft -= n;
|
|
|
|
+ buf += n;
|
|
|
|
+ off = 0;
|
|
|
|
+ } else {
|
|
|
|
+ off -= srclen;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Then follows the raw descriptor entry for the current
|
|
|
|
+ * configuration (config plus subsidiary descriptors).
|
|
|
|
+ */
|
|
|
|
+ if (udev->actconfig) {
|
|
|
|
+ int cfgno = udev->actconfig - udev->config;
|
|
|
|
+
|
|
|
|
+ srclen = __le16_to_cpu(udev->actconfig->desc.wTotalLength);
|
|
|
|
+ if (off < srclen) {
|
|
|
|
+ n = min_t(size_t, nleft, srclen - off);
|
|
|
|
+ memcpy(buf, off + udev->rawdescriptors[cfgno], n);
|
|
|
|
+ nleft -= n;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ usb_unlock_device(udev);
|
|
|
|
+ return count - nleft;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static struct bin_attribute dev_bin_attr_descriptors = {
|
|
|
|
+ .attr = {.name = "descriptors", .mode = 0444},
|
|
|
|
+ .read = read_descriptors,
|
|
|
|
+ .size = 18 + 65535, /* dev descr + max-size raw descriptor */
|
|
|
|
+};
|
|
|
|
+
|
|
int usb_create_sysfs_dev_files(struct usb_device *udev)
|
|
int usb_create_sysfs_dev_files(struct usb_device *udev)
|
|
{
|
|
{
|
|
struct device *dev = &udev->dev;
|
|
struct device *dev = &udev->dev;
|
|
@@ -450,6 +498,10 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
|
|
if (retval)
|
|
if (retval)
|
|
return retval;
|
|
return retval;
|
|
|
|
|
|
|
|
+ retval = device_create_bin_file(dev, &dev_bin_attr_descriptors);
|
|
|
|
+ if (retval)
|
|
|
|
+ goto error;
|
|
|
|
+
|
|
retval = add_persist_attributes(dev);
|
|
retval = add_persist_attributes(dev);
|
|
if (retval)
|
|
if (retval)
|
|
goto error;
|
|
goto error;
|
|
@@ -492,6 +544,7 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
|
|
device_remove_file(dev, &dev_attr_serial);
|
|
device_remove_file(dev, &dev_attr_serial);
|
|
remove_power_attributes(dev);
|
|
remove_power_attributes(dev);
|
|
remove_persist_attributes(dev);
|
|
remove_persist_attributes(dev);
|
|
|
|
+ device_remove_bin_file(dev, &dev_bin_attr_descriptors);
|
|
sysfs_remove_group(&dev->kobj, &dev_attr_grp);
|
|
sysfs_remove_group(&dev->kobj, &dev_attr_grp);
|
|
}
|
|
}
|
|
|
|
|