summaryrefslogtreecommitdiff
path: root/drivers/staging/greybus/usb.c
diff options
context:
space:
mode:
authorJohan Hovold <johan@hovoldconsulting.com>2015-07-30 18:30:40 (GMT)
committerGreg Kroah-Hartman <gregkh@google.com>2015-07-30 20:49:49 (GMT)
commita422ecd28eb03eca86d2445d8d690402e183838b (patch)
treed375154b3cc09b0ad2b5065fc0ff407da4d15cf3 /drivers/staging/greybus/usb.c
parentb1e4a1f8519aebfbf99bee8b3839498f6645e2d7 (diff)
downloadlinux-a422ecd28eb03eca86d2445d8d690402e183838b.tar.xz
greybus: usb: implement hub_control callback
Implement the hub_control callback. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus/usb.c')
-rw-r--r--drivers/staging/greybus/usb.c44
1 files changed, 32 insertions, 12 deletions
diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c
index 151e49f..17a5d7a 100644
--- a/drivers/staging/greybus/usb.c
+++ b/drivers/staging/greybus/usb.c
@@ -110,21 +110,41 @@ static int hub_status_data(struct usb_hcd *hcd, char *buf)
static int hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
char *buf, u16 wLength)
{
- struct gb_usb_hub_control_request request;
struct gb_usb_device *dev = to_gb_usb_device(hcd);
+ struct gb_operation *operation;
+ struct gb_usb_hub_control_request *request;
+ struct gb_usb_hub_control_response *response;
+ size_t response_size;
int ret;
- request.typeReq = cpu_to_le16(typeReq);
- request.wValue = cpu_to_le16(wValue);
- request.wIndex = cpu_to_le16(wIndex);
- request.wLength = cpu_to_le16(wLength);
-
- // FIXME - buf needs to come back in struct gb_usb_hub_control_response
- // for some types of requests, depending on typeReq. Do we do this in a
- // "generic" way, or only ask for a response for the ones we "know" need
- // a response (a small subset of all valid typeReq, thankfully.)
- ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HUB_CONTROL,
- &request, sizeof(request), NULL, 0);
+ /* FIXME: handle unspecified lengths */
+ response_size = sizeof(*response) + wLength;
+
+ operation = gb_operation_create(dev->connection,
+ GB_USB_TYPE_HUB_CONTROL,
+ sizeof(*request),
+ response_size,
+ GFP_KERNEL);
+ if (!operation)
+ return -ENOMEM;
+
+ request = operation->request->payload;
+ request->typeReq = cpu_to_le16(typeReq);
+ request->wValue = cpu_to_le16(wValue);
+ request->wIndex = cpu_to_le16(wIndex);
+ request->wLength = cpu_to_le16(wLength);
+
+ ret = gb_operation_request_send_sync(operation);
+ if (ret)
+ goto out;
+
+ if (wLength) {
+ /* Greybus core has verified response size */
+ response = operation->response->payload;
+ memcpy(buf, response->buf, wLength);
+ }
+out:
+ gb_operation_put(operation);
return ret;
}