Hubs have a flag to indicate whether a given port carries removable devices or not. We can use this to give a hint to userspace as to the device visibility. This is not strictly accurate in that some built-in devices will be flagged as visible, but followup patches will make use of platform data to make this more reliable. Signed-off-by: Matthew Garrett <mjg@xxxxxxxxxx> --- drivers/usb/core/hub.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 48 insertions(+), 0 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a428aa0..e8e470e 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1838,6 +1838,46 @@ fail: return err; } +/** + * usb_probe_device_visibility - determine a device's visibility + * @udev: pointer to device whose visibility should be probed + * + * Examines a hub's DeviceRemovable descriptor to determine whether a given + * device is externally visible or not. This is likely to flag many + * built-in devices as visible, but can be overridden by platform-specific + * data sources. + */ +static void usb_set_device_visibility(struct usb_device *udev) +{ + struct usb_device *hdev = udev->parent; + struct usb_hub *hub; + u8 port = udev->portnum; + u16 wHubCharacteristics; + bool visible = true; + + if (!hdev) + return; + + hub = hdev_to_hub(udev->parent); + + wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); + + if (!wHubCharacteristics & HUB_CHAR_COMPOUND) + return; + + if (hub_is_superspeed(hdev)) { + if (hub->descriptor->u.ss.DeviceRemovable & (1 << port)) + visible = false; + } else { + if (hub->descriptor->u.hs.DeviceRemovable[port / 8] & (1 << (port % 8))) + visible = false; + } + + if (visible) + udev->visible = USB_DEVICE_VISIBILITY_VISIBLE; + else + udev->visible = USB_DEVICE_VISIBILITY_HIDDEN; +} /** * usb_new_device - perform initial device setup (usbcore-internal) @@ -1896,6 +1936,14 @@ int usb_new_device(struct usb_device *udev) announce_device(udev); device_enable_async_suspend(&udev->dev); + + /* Check whether the hub marks this port as non-removable. Do + * it now so that platform-specific data can override it in + * device_add() + */ + if (udev->parent) + usb_set_device_visibility(udev); + /* Register the device. The device driver is responsible * for configuring the device and invoking the add-device * notifier chain (used by usbfs and possibly others). -- 1.7.6.4 -- 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