|
@@ -1557,7 +1557,10 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
|
|
|
epfile->ffs = ffs;
|
|
|
mutex_init(&epfile->mutex);
|
|
|
init_waitqueue_head(&epfile->wait);
|
|
|
- sprintf(epfiles->name, "ep%u", i);
|
|
|
+ if (ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
|
|
|
+ sprintf(epfiles->name, "ep%02x", ffs->eps_addrmap[i]);
|
|
|
+ else
|
|
|
+ sprintf(epfiles->name, "ep%u", i);
|
|
|
if (!unlikely(ffs_sb_create_file(ffs->sb, epfiles->name, epfile,
|
|
|
&ffs_epfile_operations,
|
|
|
&epfile->dentry))) {
|
|
@@ -2106,10 +2109,12 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
|
|
|
break;
|
|
|
case FUNCTIONFS_DESCRIPTORS_MAGIC_V2:
|
|
|
flags = get_unaligned_le32(data + 8);
|
|
|
+ ffs->user_flags = flags;
|
|
|
if (flags & ~(FUNCTIONFS_HAS_FS_DESC |
|
|
|
FUNCTIONFS_HAS_HS_DESC |
|
|
|
FUNCTIONFS_HAS_SS_DESC |
|
|
|
- FUNCTIONFS_HAS_MS_OS_DESC)) {
|
|
|
+ FUNCTIONFS_HAS_MS_OS_DESC |
|
|
|
+ FUNCTIONFS_VIRTUAL_ADDR)) {
|
|
|
ret = -ENOSYS;
|
|
|
goto error;
|
|
|
}
|
|
@@ -2466,7 +2471,13 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
|
|
|
} else {
|
|
|
struct usb_request *req;
|
|
|
struct usb_ep *ep;
|
|
|
+ u8 bEndpointAddress;
|
|
|
|
|
|
+ /*
|
|
|
+ * We back up bEndpointAddress because autoconfig overwrites
|
|
|
+ * it with physical endpoint address.
|
|
|
+ */
|
|
|
+ bEndpointAddress = ds->bEndpointAddress;
|
|
|
pr_vdebug("autoconfig\n");
|
|
|
ep = usb_ep_autoconfig(func->gadget, ds);
|
|
|
if (unlikely(!ep))
|
|
@@ -2481,6 +2492,12 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
|
|
|
ffs_ep->req = req;
|
|
|
func->eps_revmap[ds->bEndpointAddress &
|
|
|
USB_ENDPOINT_NUMBER_MASK] = idx + 1;
|
|
|
+ /*
|
|
|
+ * If we use virtual address mapping, we restore
|
|
|
+ * original bEndpointAddress value.
|
|
|
+ */
|
|
|
+ if (func->ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
|
|
|
+ ds->bEndpointAddress = bEndpointAddress;
|
|
|
}
|
|
|
ffs_dump_mem(": Rewritten ep desc", ds, ds->bLength);
|
|
|
|
|
@@ -2925,6 +2942,8 @@ static int ffs_func_setup(struct usb_function *f,
|
|
|
ret = ffs_func_revmap_ep(func, le16_to_cpu(creq->wIndex));
|
|
|
if (unlikely(ret < 0))
|
|
|
return ret;
|
|
|
+ if (func->ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
|
|
|
+ ret = func->ffs->eps_addrmap[ret];
|
|
|
break;
|
|
|
|
|
|
default:
|