This new 'type' parameter will allows interested drivers to request for PTM status or Standard status. Signed-off-by: Felipe Balbi <felipe.balbi@xxxxxxxxxxxxxxx> --- drivers/staging/wlan-ng/hfa384x_usb.c | 8 +++--- drivers/usb/core/driver.c | 3 ++- drivers/usb/core/hub.c | 13 ++++++---- drivers/usb/core/message.c | 47 +++++++++++++++++++++++++++++------ drivers/usb/misc/usbtest.c | 10 +++++--- include/linux/usb.h | 2 +- 6 files changed, 62 insertions(+), 21 deletions(-) diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index d1e8218f96fb..18f825705646 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -2459,8 +2459,8 @@ int hfa384x_drvr_start(struct hfa384x *hw) * badly if a clear_halt is called when the endpoint is already * ok */ - result = - usb_get_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_in, &status); + result = usb_get_status(hw->usb, USB_RECIP_ENDPOINT, USB_STATUS_TYPE_STANDARD, + hw->endp_in, &status); if (result < 0) { netdev_err(hw->wlandev->netdev, "Cannot get bulk in endpoint status.\n"); goto done; @@ -2468,8 +2468,8 @@ int hfa384x_drvr_start(struct hfa384x *hw) if ((status == 1) && usb_clear_halt(hw->usb, hw->endp_in)) netdev_err(hw->wlandev->netdev, "Failed to reset bulk in endpoint.\n"); - result = - usb_get_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_out, &status); + result = usb_get_status(hw->usb, USB_RECIP_ENDPOINT, USB_STATUS_TYPE_STANDARD, + hw->endp_out, &status); if (result < 0) { netdev_err(hw->wlandev->netdev, "Cannot get bulk out endpoint status.\n"); goto done; diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index eb87a259d55c..5b4f74febdf3 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1340,7 +1340,8 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) int err; u16 devstat; - err = usb_get_status(udev, USB_RECIP_DEVICE, 0, + err = usb_get_status(udev, USB_RECIP_DEVICE, + USB_STATUS_TYPE_STANDARD, 0, &devstat); if (err) { dev_err(&udev->dev, diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index e9ce6bb0b22d..c49a8524c6b9 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1482,7 +1482,8 @@ static int hub_configure(struct usb_hub *hub, /* power budgeting mostly matters with bus-powered hubs, * and battery-powered root hubs (may provide just 8 mA). */ - ret = usb_get_status(hdev, USB_RECIP_DEVICE, 0, &hubstatus); + ret = usb_get_status(hdev, USB_RECIP_DEVICE, USB_STATUS_TYPE_STANDARD, + 0, &hubstatus); if (ret) { message = "can't get hub status"; goto fail; @@ -3279,7 +3280,8 @@ static int finish_port_resume(struct usb_device *udev) */ if (status == 0) { devstatus = 0; - status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus); + status = usb_get_status(udev, USB_RECIP_DEVICE, + USB_STATUS_TYPE_STANDARD, 0, &devstatus); /* If a normal resume failed, try doing a reset-resume */ if (status && !udev->reset_resume && udev->persist_enabled) { @@ -3303,7 +3305,8 @@ static int finish_port_resume(struct usb_device *udev) if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) status = usb_disable_remote_wakeup(udev); } else { - status = usb_get_status(udev, USB_RECIP_INTERFACE, 0, + status = usb_get_status(udev, USB_RECIP_INTERFACE, + USB_STATUS_TYPE_STANDARD, 0, &devstatus); if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP | USB_INTRF_STAT_FUNC_RW)) @@ -4853,8 +4856,8 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, && udev->bus_mA <= unit_load) { u16 devstat; - status = usb_get_status(udev, USB_RECIP_DEVICE, 0, - &devstat); + status = usb_get_status(udev, USB_RECIP_DEVICE, + USB_STATUS_TYPE_STANDARD, 0, &devstat); if (status) { dev_dbg(&udev->dev, "get status %d ?\n", status); goto loop_disable; diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index dea2d0a110b3..0a9d0fd51388 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -919,6 +919,7 @@ int usb_get_device_descriptor(struct usb_device *dev, unsigned int size) * usb_get_status - issues a GET_STATUS call * @dev: the device whose status is being checked * @recip: USB_RECIP_*; for device, interface, or endpoint + * @type: USB_STATUS_TYPE_*; for standard or PTM status types * @target: zero (for device), else interface or endpoint number * @data: pointer to two bytes of bitmap data * Context: !in_interrupt () @@ -937,24 +938,56 @@ int usb_get_device_descriptor(struct usb_device *dev, unsigned int size) * Returns 0 and the status value in *@data (in host byte order) on success, * or else the status code from the underlying usb_control_msg() call. */ -int usb_get_status(struct usb_device *dev, int recip, int target, void *data) +int usb_get_status(struct usb_device *dev, int recip, int type, int target, + void *data) { int ret; - __le16 *status = kmalloc(sizeof(*status), GFP_KERNEL); + void *status; + int length; + + switch (type) { + case USB_STATUS_TYPE_STANDARD: + if (recip != USB_RECIP_DEVICE) + return -EINVAL; + + length = 2; + break; + case USB_STATUS_TYPE_PTM: + length = 4; + break; + default: + return -EINVAL; + } + status = kmalloc(length, GFP_KERNEL); if (!status) return -ENOMEM; ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_STATUS, USB_DIR_IN | recip, USB_STATUS_TYPE_STANDARD, - target, status, sizeof(*status), USB_CTRL_GET_TIMEOUT); + target, status, length, USB_CTRL_GET_TIMEOUT); + + switch (ret) { + case 4: + if (type != USB_STATUS_TYPE_PTM) { + ret = -EIO; + break; + } + + *(u32 *) data = le32_to_cpu(*(__le32 *) status); + break; + case 2: + if (type != USB_STATUS_TYPE_STANDARD) { + ret = -EIO; + break; + } - if (ret == 2) { - *(u16 *) data = le16_to_cpu(*status); - ret = 0; - } else if (ret >= 0) { + *(u16 *) data = le16_to_cpu(*(__le16 *) status); + break; + default: ret = -EIO; } + kfree(status); return ret; } diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index b3fc602b2e24..edfc37bfdd6b 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -1015,7 +1015,8 @@ static int ch9_postconfig(struct usbtest_dev *dev) /* FIXME fetch strings from at least the device descriptor */ /* [9.4.5] get_status always works */ - retval = usb_get_status(udev, USB_RECIP_DEVICE, 0, dev->buf); + retval = usb_get_status(udev, USB_RECIP_DEVICE, + USB_STATUS_TYPE_STANDARD, 0, dev->buf); if (retval) { dev_err(&iface->dev, "get dev status --> %d\n", retval); return retval; @@ -1026,6 +1027,7 @@ static int ch9_postconfig(struct usbtest_dev *dev) */ retval = usb_get_status(udev, USB_RECIP_INTERFACE, + USB_STATUS_TYPE_STANDARD, iface->altsetting[0].desc.bInterfaceNumber, dev->buf); if (retval) { dev_err(&iface->dev, "get interface status --> %d\n", retval); @@ -1614,7 +1616,8 @@ static int verify_not_halted(struct usbtest_dev *tdev, int ep, struct urb *urb) u16 status; /* shouldn't look or act halted */ - retval = usb_get_status(urb->dev, USB_RECIP_ENDPOINT, ep, &status); + retval = usb_get_status(urb->dev, USB_RECIP_ENDPOINT, + USB_STATUS_TYPE_STANDARD, ep, &status); if (retval < 0) { ERROR(tdev, "ep %02x couldn't get no-halt status, %d\n", ep, retval); @@ -1636,7 +1639,8 @@ static int verify_halted(struct usbtest_dev *tdev, int ep, struct urb *urb) u16 status; /* should look and act halted */ - retval = usb_get_status(urb->dev, USB_RECIP_ENDPOINT, ep, &status); + retval = usb_get_status(urb->dev, USB_RECIP_ENDPOINT, + USB_STATUS_TYPE_STANDARD, ep, &status); if (retval < 0) { ERROR(tdev, "ep %02x couldn't get halt status, %d\n", ep, retval); diff --git a/include/linux/usb.h b/include/linux/usb.h index 2e2c1d40081b..3e1b5d0dba66 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1766,7 +1766,7 @@ extern int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, extern int usb_get_descriptor(struct usb_device *dev, unsigned char desctype, unsigned char descindex, void *buf, int size); extern int usb_get_status(struct usb_device *dev, - int recip, int target, void *data); + int recip, int type, int target, void *data); extern int usb_string(struct usb_device *dev, int index, char *buf, size_t size); -- 2.14.2.642.g20fed7cad4 -- 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