mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-22 17:01:14 +00:00
usb: gadget: f_fs: fix the redundant ep files problem
Up to now, when endpoint addresses in descriptors were non-consecutive, there were created redundant files, which could cause problems in kernel, when user tried to read/write to them. It was result of fact that maximum endpoint address was taken as total number of endpoints in function. This patch adds endpoint descriptors counting and storing their addresses in eps_addrmap to verify their cohesion in each speed. Endpoint address map would be also useful for further features, just like vitual endpoint address mapping. Signed-off-by: Robert Baldyga <r.baldyga@samsung.com> Acked-by: Michal Nazarewicz <mina86@mina86.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
parent
2743e7f90d
commit
6d5c1c77bb
2 changed files with 57 additions and 11 deletions
|
@ -155,6 +155,12 @@ struct ffs_io_data {
|
|||
struct usb_request *req;
|
||||
};
|
||||
|
||||
struct ffs_desc_helper {
|
||||
struct ffs_data *ffs;
|
||||
unsigned interfaces_count;
|
||||
unsigned eps_count;
|
||||
};
|
||||
|
||||
static int __must_check ffs_epfiles_create(struct ffs_data *ffs);
|
||||
static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count);
|
||||
|
||||
|
@ -1830,7 +1836,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
|
|||
u8 *valuep, struct usb_descriptor_header *desc,
|
||||
void *priv)
|
||||
{
|
||||
struct ffs_data *ffs = priv;
|
||||
struct ffs_desc_helper *helper = priv;
|
||||
struct usb_endpoint_descriptor *d;
|
||||
|
||||
ENTER();
|
||||
|
||||
|
@ -1844,8 +1851,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
|
|||
* encountered interface "n" then there are at least
|
||||
* "n+1" interfaces.
|
||||
*/
|
||||
if (*valuep >= ffs->interfaces_count)
|
||||
ffs->interfaces_count = *valuep + 1;
|
||||
if (*valuep >= helper->interfaces_count)
|
||||
helper->interfaces_count = *valuep + 1;
|
||||
break;
|
||||
|
||||
case FFS_STRING:
|
||||
|
@ -1853,14 +1860,22 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
|
|||
* Strings are indexed from 1 (0 is magic ;) reserved
|
||||
* for languages list or some such)
|
||||
*/
|
||||
if (*valuep > ffs->strings_count)
|
||||
ffs->strings_count = *valuep;
|
||||
if (*valuep > helper->ffs->strings_count)
|
||||
helper->ffs->strings_count = *valuep;
|
||||
break;
|
||||
|
||||
case FFS_ENDPOINT:
|
||||
/* Endpoints are indexed from 1 as well. */
|
||||
if ((*valuep & USB_ENDPOINT_NUMBER_MASK) > ffs->eps_count)
|
||||
ffs->eps_count = (*valuep & USB_ENDPOINT_NUMBER_MASK);
|
||||
d = (void *)desc;
|
||||
helper->eps_count++;
|
||||
if (helper->eps_count >= 15)
|
||||
return -EINVAL;
|
||||
/* Check if descriptors for any speed were already parsed */
|
||||
if (!helper->ffs->eps_count && !helper->ffs->interfaces_count)
|
||||
helper->ffs->eps_addrmap[helper->eps_count] =
|
||||
d->bEndpointAddress;
|
||||
else if (helper->ffs->eps_addrmap[helper->eps_count] !=
|
||||
d->bEndpointAddress)
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2053,6 +2068,7 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
|
|||
char *data = _data, *raw_descs;
|
||||
unsigned os_descs_count = 0, counts[3], flags;
|
||||
int ret = -EINVAL, i;
|
||||
struct ffs_desc_helper helper;
|
||||
|
||||
ENTER();
|
||||
|
||||
|
@ -2101,13 +2117,29 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
|
|||
|
||||
/* Read descriptors */
|
||||
raw_descs = data;
|
||||
helper.ffs = ffs;
|
||||
for (i = 0; i < 3; ++i) {
|
||||
if (!counts[i])
|
||||
continue;
|
||||
helper.interfaces_count = 0;
|
||||
helper.eps_count = 0;
|
||||
ret = ffs_do_descs(counts[i], data, len,
|
||||
__ffs_data_do_entity, ffs);
|
||||
__ffs_data_do_entity, &helper);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
if (!ffs->eps_count && !ffs->interfaces_count) {
|
||||
ffs->eps_count = helper.eps_count;
|
||||
ffs->interfaces_count = helper.interfaces_count;
|
||||
} else {
|
||||
if (ffs->eps_count != helper.eps_count) {
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
if (ffs->interfaces_count != helper.interfaces_count) {
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
data += ret;
|
||||
len -= ret;
|
||||
}
|
||||
|
@ -2342,9 +2374,18 @@ static void ffs_event_add(struct ffs_data *ffs,
|
|||
spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags);
|
||||
}
|
||||
|
||||
|
||||
/* Bind/unbind USB function hooks *******************************************/
|
||||
|
||||
static int ffs_ep_addr2idx(struct ffs_data *ffs, u8 endpoint_address)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i < ARRAY_SIZE(ffs->eps_addrmap); ++i)
|
||||
if (ffs->eps_addrmap[i] == endpoint_address)
|
||||
return i;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
|
||||
struct usb_descriptor_header *desc,
|
||||
void *priv)
|
||||
|
@ -2378,7 +2419,10 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
|
|||
if (!desc || desc->bDescriptorType != USB_DT_ENDPOINT)
|
||||
return 0;
|
||||
|
||||
idx = (ds->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) - 1;
|
||||
idx = ffs_ep_addr2idx(func->ffs, ds->bEndpointAddress) - 1;
|
||||
if (idx < 0)
|
||||
return idx;
|
||||
|
||||
ffs_ep = func->eps + idx;
|
||||
|
||||
if (unlikely(ffs_ep->descs[ep_desc_id])) {
|
||||
|
|
|
@ -224,6 +224,8 @@ struct ffs_data {
|
|||
void *ms_os_descs_ext_prop_name_avail;
|
||||
void *ms_os_descs_ext_prop_data_avail;
|
||||
|
||||
u8 eps_addrmap[15];
|
||||
|
||||
unsigned short strings_count;
|
||||
unsigned short interfaces_count;
|
||||
unsigned short eps_count;
|
||||
|
|
Loading…
Reference in a new issue