diff options
author | Andrzej Pietrasiewicz <andrzej.p@samsung.com> | 2015-03-03 10:52:25 +0100 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2015-03-10 21:33:39 +0100 |
commit | 636bc0ed271d996e18365345e9c00fc712edc610 (patch) | |
tree | e1f3e81a0266dbb7de5b1643674211c1b465de17 /drivers/usb/gadget/legacy/printer.c | |
parent | usb: gadget: printer: name class specific requests (diff) | |
download | linux-636bc0ed271d996e18365345e9c00fc712edc610.tar.xz linux-636bc0ed271d996e18365345e9c00fc712edc610.zip |
usb: gadget: printer: add req_match for printer function
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>
Diffstat (limited to 'drivers/usb/gadget/legacy/printer.c')
-rw-r--r-- | drivers/usb/gadget/legacy/printer.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/usb/gadget/legacy/printer.c b/drivers/usb/gadget/legacy/printer.c index 78f515413e3b..c059af1aa454 100644 --- a/drivers/usb/gadget/legacy/printer.c +++ b/drivers/usb/gadget/legacy/printer.c @@ -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); |