usb: gadget: printer: add req_match for printer function
authorAndrzej Pietrasiewicz <andrzej.p@samsung.com>
Tue, 3 Mar 2015 09:52:25 +0000 (10:52 +0100)
committerFelipe Balbi <balbi@ti.com>
Tue, 10 Mar 2015 20:33:39 +0000 (15:33 -0500)
Verify that a given usb_ctrlrequest is meant for printer function.
The following parts of the request are tested:

- bmRequestType:Data transfer direction
- bmRequestType:Type
- bmRequestType:Recipient
- bRequest
- wValue for bRequest 1 and 2
- wLength

Additionally, the request is considered meant for this function
iff the decoded interface number matches dev->interface.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/gadget/legacy/printer.c

index 78f515413e3bb44f1a2acf00f31f8abb7b604217..c059af1aa454fb9c8ec20d520fe0f938f6fc9f97 100644 (file)
@@ -974,6 +974,41 @@ static void printer_soft_reset(struct printer_dev *dev)
 
 /*-------------------------------------------------------------------------*/
 
+static bool gprinter_req_match(struct usb_function *f,
+                              const struct usb_ctrlrequest *ctrl)
+{
+       struct printer_dev      *dev = func_to_printer(f);
+       u16                     w_index = le16_to_cpu(ctrl->wIndex);
+       u16                     w_value = le16_to_cpu(ctrl->wValue);
+       u16                     w_length = le16_to_cpu(ctrl->wLength);
+
+       if ((ctrl->bRequestType & USB_RECIP_MASK) != USB_RECIP_INTERFACE ||
+           (ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS)
+               return false;
+
+       switch (ctrl->bRequest) {
+       case GET_DEVICE_ID:
+               w_index >>= 8;
+               if (w_length <= PNP_STRING_LEN &&
+                   (USB_DIR_IN & ctrl->bRequestType))
+                       break;
+               return false;
+       case GET_PORT_STATUS:
+               if (!w_value && w_length == 1 &&
+                   (USB_DIR_IN & ctrl->bRequestType))
+                       break;
+               return false;
+       case SOFT_RESET:
+               if (!w_value && !w_length &&
+                  (USB_DIR_OUT & ctrl->bRequestType))
+                       break;
+               /* fall through */
+       default:
+               return false;
+       }
+       return w_index == dev->interface;
+}
+
 /*
  * The setup() callback implements all the ep0 functionality that's not
  * handled lower down.
@@ -1251,6 +1286,7 @@ static int f_printer_bind_config(struct usb_configuration *c, char *pnp_str,
        dev->function.unbind = printer_func_unbind;
        dev->function.set_alt = printer_func_set_alt;
        dev->function.disable = printer_func_disable;
+       dev->function.req_match = gprinter_req_match;
        INIT_LIST_HEAD(&dev->tx_reqs);
        INIT_LIST_HEAD(&dev->rx_reqs);
        INIT_LIST_HEAD(&dev->rx_buffers);