diff options
author | Felix Hädicke <felixhaedicke@web.de> | 2016-06-22 01:12:07 +0200 |
---|---|---|
committer | Felipe Balbi <felipe.balbi@linux.intel.com> | 2016-08-25 12:13:17 +0300 |
commit | 54dfce6d07b0391e23d006579bba488de4f7d6aa (patch) | |
tree | 434992c766d701fea355d0493592ef4a82e563b3 /drivers/usb | |
parent | ed6fe1f50f0c0fdea674dfa739af50011034bdfa (diff) | |
download | linux-stable-54dfce6d07b0391e23d006579bba488de4f7d6aa.tar.gz linux-stable-54dfce6d07b0391e23d006579bba488de4f7d6aa.tar.bz2 linux-stable-54dfce6d07b0391e23d006579bba488de4f7d6aa.zip |
usb: gadget: f_fs: handle control requests not directed to interface or endpoint
Introduces a new FunctionFS descriptor flag named
FUNCTIONFS_ALL_CTRL_RECIP. When this flag is enabled, control requests,
which are not explicitly directed to an interface or endpoint, can be
handled.
This allows FunctionFS userspace drivers to process non-standard
control requests.
Signed-off-by: Felix Hädicke <felixhaedicke@web.de>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/gadget/function/f_fs.c | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 5c8429f23a89..d7acab873836 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -98,6 +98,8 @@ static int ffs_func_set_alt(struct usb_function *, unsigned, unsigned); static void ffs_func_disable(struct usb_function *); static int ffs_func_setup(struct usb_function *, const struct usb_ctrlrequest *); +static bool ffs_func_req_match(struct usb_function *, + const struct usb_ctrlrequest *); static void ffs_func_suspend(struct usb_function *); static void ffs_func_resume(struct usb_function *); @@ -2243,7 +2245,8 @@ static int __ffs_data_got_descs(struct ffs_data *ffs, FUNCTIONFS_HAS_SS_DESC | FUNCTIONFS_HAS_MS_OS_DESC | FUNCTIONFS_VIRTUAL_ADDR | - FUNCTIONFS_EVENTFD)) { + FUNCTIONFS_EVENTFD | + FUNCTIONFS_ALL_CTRL_RECIP)) { ret = -ENOSYS; goto error; } @@ -3094,8 +3097,9 @@ static int ffs_func_setup(struct usb_function *f, * handle them. All other either handled by composite or * passed to usb_configuration->setup() (if one is set). No * matter, we will handle requests directed to endpoint here - * as well (as it's straightforward) but what to do with any - * other request? + * as well (as it's straightforward). Other request recipient + * types are only handled when the user flag FUNCTIONFS_ALL_CTRL_RECIP + * is being used. */ if (ffs->state != FFS_ACTIVE) return -ENODEV; @@ -3116,7 +3120,10 @@ static int ffs_func_setup(struct usb_function *f, break; default: - return -EOPNOTSUPP; + if (func->ffs->user_flags & FUNCTIONFS_ALL_CTRL_RECIP) + ret = le16_to_cpu(creq->wIndex); + else + return -EOPNOTSUPP; } spin_lock_irqsave(&ffs->ev.waitq.lock, flags); @@ -3128,6 +3135,24 @@ static int ffs_func_setup(struct usb_function *f, return 0; } +static bool ffs_func_req_match(struct usb_function *f, + const struct usb_ctrlrequest *creq) +{ + struct ffs_function *func = ffs_func_from_usb(f); + + switch (creq->bRequestType & USB_RECIP_MASK) { + case USB_RECIP_INTERFACE: + return ffs_func_revmap_intf(func, + le16_to_cpu(creq->wIndex) >= 0); + case USB_RECIP_ENDPOINT: + return ffs_func_revmap_ep(func, + le16_to_cpu(creq->wIndex) >= 0); + default: + return (bool) (func->ffs->user_flags & + FUNCTIONFS_ALL_CTRL_RECIP); + } +} + static void ffs_func_suspend(struct usb_function *f) { ENTER(); @@ -3378,6 +3403,7 @@ static struct usb_function *ffs_alloc(struct usb_function_instance *fi) func->function.set_alt = ffs_func_set_alt; func->function.disable = ffs_func_disable; func->function.setup = ffs_func_setup; + func->function.req_match = ffs_func_req_match; func->function.suspend = ffs_func_suspend; func->function.resume = ffs_func_resume; func->function.free_func = ffs_free; |