greybus: usb: implement hub_control callback
authorJohan Hovold <johan@hovoldconsulting.com>
Thu, 30 Jul 2015 18:30:40 +0000 (20:30 +0200)
committerGreg Kroah-Hartman <gregkh@google.com>
Thu, 30 Jul 2015 20:49:49 +0000 (13:49 -0700)
Implement the hub_control callback.

Signed-off-by: Johan Hovold <johan@hovoldconsulting.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/usb.c

index 151e49f..17a5d7a 100644 (file)
@@ -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;
 }