From patchwork Tue Mar 5 00:23:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elbert Mai X-Patchwork-Id: 13581378 Received: from sendmail.purelymail.com (sendmail.purelymail.com [34.202.193.197]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B54EDEDE for ; Tue, 5 Mar 2024 00:24:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=34.202.193.197 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709598244; cv=none; b=nD2fjqsLpvBmIDZEubYXGyAu6qEmWkfvKvuBXuZKiwS/+LayAkSWj+tjDmBSLJ9LQghgLyOZ5iAXLbCWol0bnNn2UEIrDjTF8W9DuFiyVy3pLnMOKVXuutkRUxLUNZhwsSuxsTBjag/E/LRPUo5fevwBzXZbSGJEX50UDyrZSYs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709598244; c=relaxed/simple; bh=2HIV57sf1HLLLdhagTk1qNW0ej68RudT31B3zhms368=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version:Content-Type; b=QVULKMDrdZQZrWepArPq9CM/32N46hjf8d3WnTj3IQoF2GUMGF1Mf3PnzvJGF+/KVTD5pvU8Hbu1xbOa7t+nqp3n+hoIQI1lG+3wQiiqFNXSPsPOlpiVjZM2+8LfDsjrr2rO4aX3v/ncijeIrzyBdWpWjtfWPi/7ubumufZLgiA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=elbertmai.com; spf=pass smtp.mailfrom=elbertmai.com; dkim=pass (2048-bit key) header.d=elbertmai.com header.i=@elbertmai.com header.b=wVPo0b2m; dkim=pass (2048-bit key) header.d=purelymail.com header.i=@purelymail.com header.b=CFylA4Mu; arc=none smtp.client-ip=34.202.193.197 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=elbertmai.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=elbertmai.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=elbertmai.com header.i=@elbertmai.com header.b="wVPo0b2m"; dkim=pass (2048-bit key) header.d=purelymail.com header.i=@purelymail.com header.b="CFylA4Mu" Authentication-Results: purelymail.com; auth=pass DKIM-Signature: a=rsa-sha256; b=wVPo0b2mctEKgxoIAmhmDG6e4uZorR6Ab9hRKSUuOjRb1n53V3RM1tlm4s0jYs8uGbN2Dqe6Fkz6RfaMjVlgn4PlIMWcadWWQgrB6HXg4UHRtviHSseNCHiT+oGfXDBtGQqs4q96oT9x6KX5HAoPdHopXJFNahzSDbVaxMCWH5ts0GWMTsQL4ylQrPjmeey/zSiyt75L8x2Fo/stpxpe8v7SpXcgaNcTBDsmldc3P5DI2ngbwtewSYu4/8BZ3pohbcBqgX56O/69l2BKAYswlV59pfxzHUdqarpcfrGYoGa7KWOvqxOHoRjxgd7loUorx6HAjOFa6UgpYgVOZ9AotQ==; s=purelymail2; d=elbertmai.com; v=1; bh=2HIV57sf1HLLLdhagTk1qNW0ej68RudT31B3zhms368=; h=Received:From:To:Subject; DKIM-Signature: a=rsa-sha256; b=CFylA4MuSkFWNhsb7zv9C4JGGU5pxkssVVwow2GTbI44zktm/4oRdAI66p1Tuq7k7ig9HOvFFkcapH5ZAJyBuiNMm2ZYGAwj8TzWPe/KbhF4RmEIRQL9/1sediIz0jzLfRre4Z7+JCv3mZsoroCQ9jZHMEHqLswd2KkCPUollUypw3BLcYsJCMvIg2jo5SuPd+1t56dlyOKwaYP5hBnwif9FKwZIJiCtUFGdwUX3yAvOs0DyGTYydW1YTcS/TwQlFp/BIX6yTJPiehtN0/6SBFoZlJhZpdl0ZRCpge05PRSmAgOSmNhSyYuY9/VLMCTmirCJtBPLVoi5MucwyzVfPA==; s=purelymail2; d=purelymail.com; v=1; bh=2HIV57sf1HLLLdhagTk1qNW0ej68RudT31B3zhms368=; h=Feedback-ID:Received:From:To:Subject; Feedback-ID: 5995:1482:null:purelymail X-Pm-Original-To: linux-usb@vger.kernel.org Received: by smtp.purelymail.com (Purelymail SMTP) with ESMTPSA id 1986472728; (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384); Tue, 05 Mar 2024 00:23:47 +0000 (UTC) From: Elbert Mai To: gregkh@linuxfoundation.org Cc: linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, Elbert Mai Subject: [PATCH v2] usb: Export BOS descriptor to sysfs Date: Mon, 4 Mar 2024 16:23:01 -0800 Message-Id: <20240305002301.95323-1-code@elbertmai.com> X-Mailer: git-send-email 2.34.1 Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MIME-Autoconverted: from 8bit to quoted-printable by Purelymail Motivation ---------- The binary device object store (BOS) of a USB device consists of the BOS descriptor followed by a set of device capability descriptors. One that is of interest to users is the platform descriptor. This contains a 128-bit UUID and arbitrary data, and it allows parties outside of USB-IF to add additional metadata about a USB device in a standards-compliant manner. Notable examples include the WebUSB and Microsoft OS 2.0 descriptors. The kernel already retrieves and caches the BOS from USB devices if its bcdUSB is >= 0x0201. Because the BOS is flexible and extensible, we export the entire BOS to sysfs so users can retrieve whatever device capabilities they desire, without requiring USB I/O or elevated permissions. Implementation -------------- Add bos_descriptors attribute to sysfs. This is a binary file and it works the same way as the existing descriptors attribute. The file exists only if the BOS is present in the USB device. Also create a binary attribute group, so the driver core can handle the creation of both the descriptors and bos_descriptors attributes in sysfs. Signed-off-by: Elbert Mai --- Changes in v2: - Rename to bos_descriptors (plural) since the attribute contains the entire BOS, not just the first descriptor in it. - Use binary attribute groups to let driver core handle attribute creation for both descriptors and bos_descriptors. - The attribute is visible in sysfs only if the BOS is present in the USB device. Documentation/ABI/testing/sysfs-bus-usb | 10 ++++ drivers/usb/core/sysfs.c | 78 +++++++++++++++++++------ 2 files changed, 71 insertions(+), 17 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index 614d216dff1d..102ee4215e48 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb @@ -293,3 +293,13 @@ Description: USB 3.2 adds Dual-lane support, 2 rx and 2 tx -lanes over Type-C. Inter-Chip SSIC devices support asymmetric lanes up to 4 lanes per direction. Devices before USB 3.2 are single lane (tx_lanes = 1) + +What: /sys/bus/usb/devices/.../bos_descriptors +Date: March 2024 +Contact: Elbert Mai +Description: + Binary file containing the cached binary device object store (BOS) + of the device. This consists of the BOS descriptor followed by the + set of device capability descriptors. All descriptors read from + this file are in bus-endian format. Note that the kernel will not + request the BOS from a device if its bcdUSB is less than 0x0201. diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index a2ca38e25e0c..a50b6f496eb6 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -870,16 +870,10 @@ static struct attribute_group dev_string_attr_grp = { .is_visible = dev_string_attrs_are_visible, }; -const struct attribute_group *usb_device_groups[] = { - &dev_attr_grp, - &dev_string_attr_grp, - NULL -}; - /* Binary descriptors */ static ssize_t -read_descriptors(struct file *filp, struct kobject *kobj, +descriptors_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { @@ -901,7 +895,7 @@ read_descriptors(struct file *filp, struct kobject *kobj, srclen = sizeof(struct usb_device_descriptor); } else { src = udev->rawdescriptors[cfgno]; - srclen = __le16_to_cpu(udev->config[cfgno].desc. + srclen = le16_to_cpu(udev->config[cfgno].desc. wTotalLength); } if (off < srclen) { @@ -916,11 +910,66 @@ read_descriptors(struct file *filp, struct kobject *kobj, } return count - nleft; } +static BIN_ATTR_RO(descriptors, 18 + 65535); /* dev descr + max-size raw descriptor */ + +static ssize_t +bos_descriptors_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct device *dev = kobj_to_dev(kobj); + struct usb_device *udev = to_usb_device(dev); + struct usb_host_bos *bos = udev->bos; + struct usb_bos_descriptor *desc; + size_t desclen, n = 0; + + if (bos) { + desc = bos->desc; + desclen = le16_to_cpu(desc->wTotalLength); + if (off < desclen) { + n = min(count, desclen - (size_t) off); + memcpy(buf, (void *) desc + off, n); + } + } + return n; +} +static BIN_ATTR_RO(bos_descriptors, 65535); /* max-size BOS */ -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 */ +/* When modifying this list, be sure to modify dev_bin_attrs_are_visible() + * accordingly. + */ +static struct bin_attribute *dev_bin_attrs[] = { + &bin_attr_descriptors, + &bin_attr_bos_descriptors, + NULL +}; + +static umode_t dev_bin_attrs_are_visible(struct kobject *kobj, + struct bin_attribute *a, int n) +{ + struct device *dev = kobj_to_dev(kobj); + struct usb_device *udev = to_usb_device(dev); + + /* All USB devices have a device descriptor, so the descriptors + * attribute always exists. No need to check for its visibility. + */ + if (a == &bin_attr_bos_descriptors) { + if (udev->bos == NULL) + return 0; + } + return a->attr.mode; +} + +static const struct attribute_group dev_bin_attr_grp = { + .bin_attrs = dev_bin_attrs, + .is_bin_visible = dev_bin_attrs_are_visible, +}; + +const struct attribute_group *usb_device_groups[] = { + &dev_attr_grp, + &dev_string_attr_grp, + &dev_bin_attr_grp, + NULL }; /* @@ -1038,10 +1087,6 @@ int usb_create_sysfs_dev_files(struct usb_device *udev) struct device *dev = &udev->dev; int retval; - retval = device_create_bin_file(dev, &dev_bin_attr_descriptors); - if (retval) - goto error; - retval = add_persist_attributes(dev); if (retval) goto error; @@ -1071,7 +1116,6 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev) remove_power_attributes(dev); remove_persist_attributes(dev); - device_remove_bin_file(dev, &dev_bin_attr_descriptors); } /* Interface Association Descriptor fields */