Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Robert Baldyga and committed by
Felipe Balbi
1b0bf88f 4cd41ffd

+24 -2
+21 -2
drivers/usb/gadget/function/f_fs.c
··· 1557 1557 epfile->ffs = ffs; 1558 1558 mutex_init(&epfile->mutex); 1559 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 1564 if (!unlikely(ffs_sb_create_file(ffs->sb, epfiles->name, epfile, 1562 1565 &ffs_epfile_operations, 1563 1566 &epfile->dentry))) { ··· 2109 2106 break; 2110 2107 case FUNCTIONFS_DESCRIPTORS_MAGIC_V2: 2111 2108 flags = get_unaligned_le32(data + 8); 2109 + ffs->user_flags = flags; 2112 2110 if (flags & ~(FUNCTIONFS_HAS_FS_DESC | 2113 2111 FUNCTIONFS_HAS_HS_DESC | 2114 2112 FUNCTIONFS_HAS_SS_DESC | 2115 - FUNCTIONFS_HAS_MS_OS_DESC)) { 2113 + FUNCTIONFS_HAS_MS_OS_DESC | 2114 + FUNCTIONFS_VIRTUAL_ADDR)) { 2116 2115 ret = -ENOSYS; 2117 2116 goto error; 2118 2117 } ··· 2471 2466 } else { 2472 2467 struct usb_request *req; 2473 2468 struct usb_ep *ep; 2469 + u8 bEndpointAddress; 2474 2470 2471 + /* 2472 + * We back up bEndpointAddress because autoconfig overwrites 2473 + * it with physical endpoint address. 2474 + */ 2475 + bEndpointAddress = ds->bEndpointAddress; 2475 2476 pr_vdebug("autoconfig\n"); 2476 2477 ep = usb_ep_autoconfig(func->gadget, ds); 2477 2478 if (unlikely(!ep)) ··· 2492 2481 ffs_ep->req = req; 2493 2482 func->eps_revmap[ds->bEndpointAddress & 2494 2483 USB_ENDPOINT_NUMBER_MASK] = idx + 1; 2484 + /* 2485 + * If we use virtual address mapping, we restore 2486 + * original bEndpointAddress value. 2487 + */ 2488 + if (func->ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR) 2489 + ds->bEndpointAddress = bEndpointAddress; 2495 2490 } 2496 2491 ffs_dump_mem(": Rewritten ep desc", ds, ds->bLength); 2497 2492 ··· 2942 2925 ret = ffs_func_revmap_ep(func, le16_to_cpu(creq->wIndex)); 2943 2926 if (unlikely(ret < 0)) 2944 2927 return ret; 2928 + if (func->ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR) 2929 + ret = func->ffs->eps_addrmap[ret]; 2945 2930 break; 2946 2931 2947 2932 default:
+2
drivers/usb/gadget/function/u_fs.h
··· 224 224 void *ms_os_descs_ext_prop_name_avail; 225 225 void *ms_os_descs_ext_prop_data_avail; 226 226 227 + unsigned user_flags; 228 + 227 229 u8 eps_addrmap[15]; 228 230 229 231 unsigned short strings_count;
+1
include/uapi/linux/usb/functionfs.h
··· 19 19 FUNCTIONFS_HAS_HS_DESC = 2, 20 20 FUNCTIONFS_HAS_SS_DESC = 4, 21 21 FUNCTIONFS_HAS_MS_OS_DESC = 8, 22 + FUNCTIONFS_VIRTUAL_ADDR = 16, 22 23 }; 23 24 24 25 /* Descriptor of an non-audio endpoint */