aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/function
diff options
context:
space:
mode:
authorFelix Hädicke <felixhaedicke@web.de>2016-06-21 19:12:07 -0400
committerFelipe Balbi <felipe.balbi@linux.intel.com>2016-08-25 05:13:17 -0400
commit54dfce6d07b0391e23d006579bba488de4f7d6aa (patch)
tree434992c766d701fea355d0493592ef4a82e563b3 /drivers/usb/gadget/function
parented6fe1f50f0c0fdea674dfa739af50011034bdfa (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.c34
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);
98static void ffs_func_disable(struct usb_function *); 98static void ffs_func_disable(struct usb_function *);
99static int ffs_func_setup(struct usb_function *, 99static int ffs_func_setup(struct usb_function *,
100 const struct usb_ctrlrequest *); 100 const struct usb_ctrlrequest *);
101static bool ffs_func_req_match(struct usb_function *,
102 const struct usb_ctrlrequest *);
101static void ffs_func_suspend(struct usb_function *); 103static void ffs_func_suspend(struct usb_function *);
102static void ffs_func_resume(struct usb_function *); 104static 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
3138static 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
3131static void ffs_func_suspend(struct usb_function *f) 3156static 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;