Re: [PATCH v3] usbcore: get BOS descriptor set

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



* Andiry Xu | 2011-07-14 16:27:06 [+0800]:

>This commit gets BOS(Binary Device Object Store) descriptor set for Super
>Speed devices and High Speed devices which support BOS descriptor.
>
>BOS descriptor is used to report additional USB device-level capabilities
>that are not reported via the Device descriptor. By getting BOS descriptor
>set, driver can check device's device-level capability such as LPM
>capability.
>
>Signed-off-by: Andiry Xu <andiry.xu@xxxxxxx>
>---
> drivers/usb/core/config.c |  102 +++++++++++++++++++++++++++++++++++++++++++++
> drivers/usb/core/hub.c    |    3 +
> drivers/usb/core/usb.c    |    1 +
> drivers/usb/core/usb.h    |    2 +
> include/linux/usb.h       |   12 +++++
> 5 files changed, 120 insertions(+), 0 deletions(-)
>
>diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
>index c962608..da7ccbf 100644
>--- a/drivers/usb/core/config.c
>+++ b/drivers/usb/core/config.c
>@@ -754,3 +754,105 @@ err2:
> 		dev_err(ddev, "out of memory\n");
> 	return result;
> }
>+
>+void usb_release_bos_descriptor(struct usb_device *dev)
>+{
>+	if (dev->bos) {
>+		kfree(dev->bos->desc);
>+		kfree(dev->bos);
>+		dev->bos = NULL;
>+	}
>+}
>+
>+/* Get BOS descriptor set */
>+int usb_get_bos_descriptor(struct usb_device *dev)
>+{
>+	struct device *ddev = &dev->dev;
>+	struct usb_bos_descriptor *bos;
>+	struct usb_dev_cap_header *cap;
>+	unsigned char *buffer, *header;
>+	int length, total_len, num, i;
>+	int ret;
>+
>+	bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_KERNEL);
>+	if (!bos)
>+		return -ENOMEM;
>+
>+	/* Get BOS descriptor */
>+	ret = usb_get_descriptor(dev, USB_DT_BOS, 0, bos, USB_DT_BOS_SIZE);
>+	if (ret < USB_DT_BOS_SIZE) {
>+		dev_err(ddev, "unable to get BOS descriptor\n");
>+		if (ret >= 0)
>+			ret = -ENOMSG;
>+		kfree(bos);
>+		return ret;
>+	}
>+
>+	length = (int)le16_to_cpu(bos->bLength);
the by in blength stands for byte so no need for le16 here.

>+	total_len = (int)le16_to_cpu(bos->wTotalLength);
this is fine but the cast is ugly.

>+	num = (int)le16_to_cpu(bos->bNumDeviceCaps);
also a byte

>+	kfree(bos);
>+
>+	dev->bos = kzalloc(sizeof(struct usb_host_bos), GFP_KERNEL);
>+	if (!dev->bos)
>+		return -ENOMEM;
>+
>+	/* Now let's get the whole BOS descriptor set */
>+	buffer = kzalloc(total_len, GFP_KERNEL);
>+	if (!buffer) {
>+		ret = -ENOMEM;
>+		goto err;
>+	}
>+	dev->bos->desc = (struct usb_bos_descriptor *)buffer;
>+
>+	ret = usb_get_descriptor(dev, USB_DT_BOS, 0, buffer, total_len);
>+	if (ret < total_len) {
>+		dev_err(ddev, "unable to get BOS descriptor set\n");
>+		if (ret >= 0)
>+			ret = -ENOMSG;
>+		goto err;
>+	}
>+	header = buffer;
>+
>+	for (i = 0; i < num; i++) {
>+		if (total_len < length)
isn't this an error case? The descriptor looks kinda broken or do we try
to make the best out of it?

>+			break;
>+		total_len -= length;
>+
>+		header += length;
>+		cap = (struct usb_dev_cap_header *)header;
>+		length = (int)le16_to_cpu(cap->bLength);
byte

>+
>+		if (le16_to_cpu(cap->bDescriptorType)
>+				!= USB_DT_DEVICE_CAPABILITY) {
also a byte

>+			dev_warn(ddev, "descriptor type invalid, skip\n");
mind dumping the type that has been identified as invalid?

>+			continue;
>+		}
>+
>+		switch (le16_to_cpu(cap->bDevCapabilityType)) {
another byte

>+		case USB_CAP_TYPE_WIRELESS_USB:
>+			/* Wireless USB cap descriptor is handled by wusb */
>+			break;
>+		case USB_CAP_TYPE_EXT:
>+			dev->bos->ext_cap =
>+				(struct usb_ext_cap_descriptor *)header;
>+			break;
>+		case USB_SS_CAP_TYPE:
>+			dev->bos->ss_cap =
>+				(struct usb_ss_cap_descriptor *)header;
>+			break;
>+		case CONTAINER_ID_TYPE:
>+			dev->bos->ss_id =
>+				(struct usb_ss_container_id_descriptor *)header;
>+			break;
>+		default:
>+			break;
>+		}
>+	}
>+
>+	return 0;
>+
>+err:
>+	usb_release_bos_descriptor(dev);
>+	return ret;
>+}
>diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
>index 90ae175..4ca6bb2 100644
>--- a/drivers/usb/core/hub.c
>+++ b/drivers/usb/core/hub.c
>@@ -3041,6 +3041,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
> 		goto fail;
> 	}
> 
>+	if (udev->wusb == 0 && udev->descriptor.bcdUSB >= 0x0210)
>+		retval = usb_get_bos_descriptor(udev);
>+
> 	retval = 0;
so retval is overwritten

> 	/* notify HCD that we have a device connected and addressed */
> 	if (hcd->driver->update_device)

Sebastian
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux