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

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

 



On Thu, Jul 14, 2011 at 6:58 PM, Sebastian Andrzej Siewior
<bigeasy@xxxxxxxxxxxxx> wrote:
> * 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.
>

OK. I'll fix it.

>>+      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?
>

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?
>

OK. But if this field is wrong, the value is meaningless. Can't imaging
a different type of descriptor is inserted to BOS descriptor set.

>>+                      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

Yes, this patch will not check the retval, because BOS descriptor set
is an extensive descriptor and the failure should not prevent the device
from normal initialization. The retval will be used when the driver wants
to check certain capabilities from the BOS descriptor set.

Thanks,
Andiry
--
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