aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
authorRobert Baldyga <r.baldyga@samsung.com>2014-09-09 02:23:17 -0400
committerFelipe Balbi <balbi@ti.com>2014-09-16 10:58:21 -0400
commit1b0bf88fd8b845aef4300c7c0feca774265dd1c4 (patch)
tree1433df7c2cb619b2eea9c50f834aeed0fc1a55bd /drivers/usb/gadget
parent4cd41ffd27b6b775445ecfdb72b592b71d6b4a32 (diff)
usb: gadget: f_fs: virtual endpoint address mapping
This patch introduces virtual endpoint address mapping. It separates function logic form physical endpoint addresses making it more hardware independent. Following modifications changes user space API, so to enable them user have to switch on the FUNCTIONFS_VIRTUAL_ADDR flag in descriptors. Endpoints are now refered using virtual endpoint addresses chosen by user in endpoint descpriptors. This applies to each context when endpoint address can be used: - when accessing endpoint files in FunctionFS filesystemi (in file name), - in setup requests directed to specific endpoint (in wIndex field), - in descriptors returned by FUNCTIONFS_ENDPOINT_DESC ioctl. In endpoint file names the endpoint address number is formatted as double-digit hexadecimal value ("ep%02x") which has few advantages - it is easy to parse, allows to easly recognize endpoint direction basing on its name (IN endpoint number starts with digit 8, and OUT with 0) which can be useful for debugging purpose, and it makes easier to introduce further features allowing to use each endpoint number in both directions to have more endpoints available for function if hardware supports this (for example we could have ep01 which is endpoint 1 with OUT direction, and ep81 which is endpoint 1 with IN direction). Physical endpoint address can be still obtained using ioctl named FUNCTIONFS_ENDPOINT_REVMAP, but now it's not neccesary to handle USB transactions properly. Signed-off-by: Robert Baldyga <r.baldyga@samsung.com> Acked-by: Michal Nazarewicz <mina86@mina86.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/function/f_fs.c23
-rw-r--r--drivers/usb/gadget/function/u_fs.h2
2 files changed, 23 insertions, 2 deletions
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index e4afe8df5553..4ad11e03cf54 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -1557,7 +1557,10 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
1557 epfile->ffs = ffs; 1557 epfile->ffs = ffs;
1558 mutex_init(&epfile->mutex); 1558 mutex_init(&epfile->mutex);
1559 init_waitqueue_head(&epfile->wait); 1559 init_waitqueue_head(&epfile->wait);
1560 sprintf(epfiles->name, "ep%u", i); 1560 if (ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
1561 sprintf(epfiles->name, "ep%02x", ffs->eps_addrmap[i]);
1562 else
1563 sprintf(epfiles->name, "ep%u", i);
1561 if (!unlikely(ffs_sb_create_file(ffs->sb, epfiles->name, epfile, 1564 if (!unlikely(ffs_sb_create_file(ffs->sb, epfiles->name, epfile,
1562 &ffs_epfile_operations, 1565 &ffs_epfile_operations,
1563 &epfile->dentry))) { 1566 &epfile->dentry))) {
@@ -2106,10 +2109,12 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
2106 break; 2109 break;
2107 case FUNCTIONFS_DESCRIPTORS_MAGIC_V2: 2110 case FUNCTIONFS_DESCRIPTORS_MAGIC_V2:
2108 flags = get_unaligned_le32(data + 8); 2111 flags = get_unaligned_le32(data + 8);
2112 ffs->user_flags = flags;
2109 if (flags & ~(FUNCTIONFS_HAS_FS_DESC | 2113 if (flags & ~(FUNCTIONFS_HAS_FS_DESC |
2110 FUNCTIONFS_HAS_HS_DESC | 2114 FUNCTIONFS_HAS_HS_DESC |
2111 FUNCTIONFS_HAS_SS_DESC | 2115 FUNCTIONFS_HAS_SS_DESC |
2112 FUNCTIONFS_HAS_MS_OS_DESC)) { 2116 FUNCTIONFS_HAS_MS_OS_DESC |
2117 FUNCTIONFS_VIRTUAL_ADDR)) {
2113 ret = -ENOSYS; 2118 ret = -ENOSYS;
2114 goto error; 2119 goto error;
2115 } 2120 }
@@ -2466,7 +2471,13 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
2466 } else { 2471 } else {
2467 struct usb_request *req; 2472 struct usb_request *req;
2468 struct usb_ep *ep; 2473 struct usb_ep *ep;
2474 u8 bEndpointAddress;
2469 2475
2476 /*
2477 * We back up bEndpointAddress because autoconfig overwrites
2478 * it with physical endpoint address.
2479 */
2480 bEndpointAddress = ds->bEndpointAddress;
2470 pr_vdebug("autoconfig\n"); 2481 pr_vdebug("autoconfig\n");
2471 ep = usb_ep_autoconfig(func->gadget, ds); 2482 ep = usb_ep_autoconfig(func->gadget, ds);
2472 if (unlikely(!ep)) 2483 if (unlikely(!ep))
@@ -2481,6 +2492,12 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
2481 ffs_ep->req = req; 2492 ffs_ep->req = req;
2482 func->eps_revmap[ds->bEndpointAddress & 2493 func->eps_revmap[ds->bEndpointAddress &
2483 USB_ENDPOINT_NUMBER_MASK] = idx + 1; 2494 USB_ENDPOINT_NUMBER_MASK] = idx + 1;
2495 /*
2496 * If we use virtual address mapping, we restore
2497 * original bEndpointAddress value.
2498 */
2499 if (func->ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
2500 ds->bEndpointAddress = bEndpointAddress;
2484 } 2501 }
2485 ffs_dump_mem(": Rewritten ep desc", ds, ds->bLength); 2502 ffs_dump_mem(": Rewritten ep desc", ds, ds->bLength);
2486 2503
@@ -2925,6 +2942,8 @@ static int ffs_func_setup(struct usb_function *f,
2925 ret = ffs_func_revmap_ep(func, le16_to_cpu(creq->wIndex)); 2942 ret = ffs_func_revmap_ep(func, le16_to_cpu(creq->wIndex));
2926 if (unlikely(ret < 0)) 2943 if (unlikely(ret < 0))
2927 return ret; 2944 return ret;
2945 if (func->ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
2946 ret = func->ffs->eps_addrmap[ret];
2928 break; 2947 break;
2929 2948
2930 default: 2949 default:
diff --git a/drivers/usb/gadget/function/u_fs.h b/drivers/usb/gadget/function/u_fs.h
index d48897e8ffeb..cd128e31f808 100644
--- a/drivers/usb/gadget/function/u_fs.h
+++ b/drivers/usb/gadget/function/u_fs.h
@@ -224,6 +224,8 @@ struct ffs_data {
224 void *ms_os_descs_ext_prop_name_avail; 224 void *ms_os_descs_ext_prop_name_avail;
225 void *ms_os_descs_ext_prop_data_avail; 225 void *ms_os_descs_ext_prop_data_avail;
226 226
227 unsigned user_flags;
228
227 u8 eps_addrmap[15]; 229 u8 eps_addrmap[15];
228 230
229 unsigned short strings_count; 231 unsigned short strings_count;