diff options
| author | Felix Hädicke <felixhaedicke@web.de> | 2016-06-21 19:12:07 -0400 |
|---|---|---|
| committer | Felipe Balbi <felipe.balbi@linux.intel.com> | 2016-08-25 05:13:17 -0400 |
| commit | 54dfce6d07b0391e23d006579bba488de4f7d6aa (patch) | |
| tree | 434992c766d701fea355d0493592ef4a82e563b3 /drivers/usb/gadget/function | |
| parent | ed6fe1f50f0c0fdea674dfa739af50011034bdfa (diff) | |
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/gadget/function')
| -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); | |||
| 98 | static void ffs_func_disable(struct usb_function *); | 98 | static void ffs_func_disable(struct usb_function *); |
| 99 | static int ffs_func_setup(struct usb_function *, | 99 | static int ffs_func_setup(struct usb_function *, |
| 100 | const struct usb_ctrlrequest *); | 100 | const struct usb_ctrlrequest *); |
| 101 | static bool ffs_func_req_match(struct usb_function *, | ||
| 102 | const struct usb_ctrlrequest *); | ||
| 101 | static void ffs_func_suspend(struct usb_function *); | 103 | static void ffs_func_suspend(struct usb_function *); |
| 102 | static void ffs_func_resume(struct usb_function *); | 104 | static void ffs_func_resume(struct usb_function *); |
| 103 | 105 | ||
| @@ -2243,7 +2245,8 @@ static int __ffs_data_got_descs(struct ffs_data *ffs, | |||
| 2243 | FUNCTIONFS_HAS_SS_DESC | | 2245 | FUNCTIONFS_HAS_SS_DESC | |
| 2244 | FUNCTIONFS_HAS_MS_OS_DESC | | 2246 | FUNCTIONFS_HAS_MS_OS_DESC | |
| 2245 | FUNCTIONFS_VIRTUAL_ADDR | | 2247 | FUNCTIONFS_VIRTUAL_ADDR | |
| 2246 | FUNCTIONFS_EVENTFD)) { | 2248 | FUNCTIONFS_EVENTFD | |
| 2249 | FUNCTIONFS_ALL_CTRL_RECIP)) { | ||
| 2247 | ret = -ENOSYS; | 2250 | ret = -ENOSYS; |
| 2248 | goto error; | 2251 | goto error; |
| 2249 | } | 2252 | } |
| @@ -3094,8 +3097,9 @@ static int ffs_func_setup(struct usb_function *f, | |||
| 3094 | * handle them. All other either handled by composite or | 3097 | * handle them. All other either handled by composite or |
| 3095 | * passed to usb_configuration->setup() (if one is set). No | 3098 | * passed to usb_configuration->setup() (if one is set). No |
| 3096 | * matter, we will handle requests directed to endpoint here | 3099 | * matter, we will handle requests directed to endpoint here |
| 3097 | * as well (as it's straightforward) but what to do with any | 3100 | * as well (as it's straightforward). Other request recipient |
| 3098 | * other request? | 3101 | * types are only handled when the user flag FUNCTIONFS_ALL_CTRL_RECIP |
| 3102 | * is being used. | ||
| 3099 | */ | 3103 | */ |
| 3100 | if (ffs->state != FFS_ACTIVE) | 3104 | if (ffs->state != FFS_ACTIVE) |
| 3101 | return -ENODEV; | 3105 | return -ENODEV; |
| @@ -3116,7 +3120,10 @@ static int ffs_func_setup(struct usb_function *f, | |||
| 3116 | break; | 3120 | break; |
| 3117 | 3121 | ||
| 3118 | default: | 3122 | default: |
| 3119 | return -EOPNOTSUPP; | 3123 | if (func->ffs->user_flags & FUNCTIONFS_ALL_CTRL_RECIP) |
| 3124 | ret = le16_to_cpu(creq->wIndex); | ||
| 3125 | else | ||
| 3126 | return -EOPNOTSUPP; | ||
| 3120 | } | 3127 | } |
| 3121 | 3128 | ||
| 3122 | spin_lock_irqsave(&ffs->ev.waitq.lock, flags); | 3129 | spin_lock_irqsave(&ffs->ev.waitq.lock, flags); |
| @@ -3128,6 +3135,24 @@ static int ffs_func_setup(struct usb_function *f, | |||
| 3128 | return 0; | 3135 | return 0; |
| 3129 | } | 3136 | } |
| 3130 | 3137 | ||
| 3138 | static bool ffs_func_req_match(struct usb_function *f, | ||
| 3139 | const struct usb_ctrlrequest *creq) | ||
| 3140 | { | ||
| 3141 | struct ffs_function *func = ffs_func_from_usb(f); | ||
| 3142 | |||
| 3143 | switch (creq->bRequestType & USB_RECIP_MASK) { | ||
| 3144 | case USB_RECIP_INTERFACE: | ||
| 3145 | return ffs_func_revmap_intf(func, | ||
| 3146 | le16_to_cpu(creq->wIndex) >= 0); | ||
| 3147 | case USB_RECIP_ENDPOINT: | ||
| 3148 | return ffs_func_revmap_ep(func, | ||
| 3149 | le16_to_cpu(creq->wIndex) >= 0); | ||
| 3150 | default: | ||
| 3151 | return (bool) (func->ffs->user_flags & | ||
| 3152 | FUNCTIONFS_ALL_CTRL_RECIP); | ||
| 3153 | } | ||
| 3154 | } | ||
| 3155 | |||
| 3131 | static void ffs_func_suspend(struct usb_function *f) | 3156 | static void ffs_func_suspend(struct usb_function *f) |
| 3132 | { | 3157 | { |
| 3133 | ENTER(); | 3158 | ENTER(); |
| @@ -3378,6 +3403,7 @@ static struct usb_function *ffs_alloc(struct usb_function_instance *fi) | |||
| 3378 | func->function.set_alt = ffs_func_set_alt; | 3403 | func->function.set_alt = ffs_func_set_alt; |
| 3379 | func->function.disable = ffs_func_disable; | 3404 | func->function.disable = ffs_func_disable; |
| 3380 | func->function.setup = ffs_func_setup; | 3405 | func->function.setup = ffs_func_setup; |
| 3406 | func->function.req_match = ffs_func_req_match; | ||
| 3381 | func->function.suspend = ffs_func_suspend; | 3407 | func->function.suspend = ffs_func_suspend; |
| 3382 | func->function.resume = ffs_func_resume; | 3408 | func->function.resume = ffs_func_resume; |
| 3383 | func->function.free_func = ffs_free; | 3409 | func->function.free_func = ffs_free; |
