aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Baldyga <r.baldyga@samsung.com>2014-08-25 05:16:27 -0400
committerFelipe Balbi <balbi@ti.com>2014-09-03 10:15:59 -0400
commit6d5c1c77bbf98b2cc5373af02bb7b3b27584ee4a (patch)
tree7e1d8e417332a4a813b5c13814fc47e20896db18
parent2743e7f90dc08282d027dbc2f6486f5cb85aa493 (diff)
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>
-rw-r--r--drivers/usb/gadget/function/f_fs.c66
-rw-r--r--drivers/usb/gadget/function/u_fs.h2
2 files changed, 57 insertions, 11 deletions
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index dc30adf15a01..0dc3552d1360 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -155,6 +155,12 @@ struct ffs_io_data {
155 struct usb_request *req; 155 struct usb_request *req;
156}; 156};
157 157
158struct ffs_desc_helper {
159 struct ffs_data *ffs;
160 unsigned interfaces_count;
161 unsigned eps_count;
162};
163
158static int __must_check ffs_epfiles_create(struct ffs_data *ffs); 164static int __must_check ffs_epfiles_create(struct ffs_data *ffs);
159static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count); 165static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count);
160 166
@@ -1830,7 +1836,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
1830 u8 *valuep, struct usb_descriptor_header *desc, 1836 u8 *valuep, struct usb_descriptor_header *desc,
1831 void *priv) 1837 void *priv)
1832{ 1838{
1833 struct ffs_data *ffs = priv; 1839 struct ffs_desc_helper *helper = priv;
1840 struct usb_endpoint_descriptor *d;
1834 1841
1835 ENTER(); 1842 ENTER();
1836 1843
@@ -1844,8 +1851,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
1844 * encountered interface "n" then there are at least 1851 * encountered interface "n" then there are at least
1845 * "n+1" interfaces. 1852 * "n+1" interfaces.
1846 */ 1853 */
1847 if (*valuep >= ffs->interfaces_count) 1854 if (*valuep >= helper->interfaces_count)
1848 ffs->interfaces_count = *valuep + 1; 1855 helper->interfaces_count = *valuep + 1;
1849 break; 1856 break;
1850 1857
1851 case FFS_STRING: 1858 case FFS_STRING:
@@ -1853,14 +1860,22 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
1853 * Strings are indexed from 1 (0 is magic ;) reserved 1860 * Strings are indexed from 1 (0 is magic ;) reserved
1854 * for languages list or some such) 1861 * for languages list or some such)
1855 */ 1862 */
1856 if (*valuep > ffs->strings_count) 1863 if (*valuep > helper->ffs->strings_count)
1857 ffs->strings_count = *valuep; 1864 helper->ffs->strings_count = *valuep;
1858 break; 1865 break;
1859 1866
1860 case FFS_ENDPOINT: 1867 case FFS_ENDPOINT:
1861 /* Endpoints are indexed from 1 as well. */ 1868 d = (void *)desc;
1862 if ((*valuep & USB_ENDPOINT_NUMBER_MASK) > ffs->eps_count) 1869 helper->eps_count++;
1863 ffs->eps_count = (*valuep & USB_ENDPOINT_NUMBER_MASK); 1870 if (helper->eps_count >= 15)
1871 return -EINVAL;
1872 /* Check if descriptors for any speed were already parsed */
1873 if (!helper->ffs->eps_count && !helper->ffs->interfaces_count)
1874 helper->ffs->eps_addrmap[helper->eps_count] =
1875 d->bEndpointAddress;
1876 else if (helper->ffs->eps_addrmap[helper->eps_count] !=
1877 d->bEndpointAddress)
1878 return -EINVAL;
1864 break; 1879 break;
1865 } 1880 }
1866 1881
@@ -2053,6 +2068,7 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
2053 char *data = _data, *raw_descs; 2068 char *data = _data, *raw_descs;
2054 unsigned os_descs_count = 0, counts[3], flags; 2069 unsigned os_descs_count = 0, counts[3], flags;
2055 int ret = -EINVAL, i; 2070 int ret = -EINVAL, i;
2071 struct ffs_desc_helper helper;
2056 2072
2057 ENTER(); 2073 ENTER();
2058 2074
@@ -2101,13 +2117,29 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
2101 2117
2102 /* Read descriptors */ 2118 /* Read descriptors */
2103 raw_descs = data; 2119 raw_descs = data;
2120 helper.ffs = ffs;
2104 for (i = 0; i < 3; ++i) { 2121 for (i = 0; i < 3; ++i) {
2105 if (!counts[i]) 2122 if (!counts[i])
2106 continue; 2123 continue;
2124 helper.interfaces_count = 0;
2125 helper.eps_count = 0;
2107 ret = ffs_do_descs(counts[i], data, len, 2126 ret = ffs_do_descs(counts[i], data, len,
2108 __ffs_data_do_entity, ffs); 2127 __ffs_data_do_entity, &helper);
2109 if (ret < 0) 2128 if (ret < 0)
2110 goto error; 2129 goto error;
2130 if (!ffs->eps_count && !ffs->interfaces_count) {
2131 ffs->eps_count = helper.eps_count;
2132 ffs->interfaces_count = helper.interfaces_count;
2133 } else {
2134 if (ffs->eps_count != helper.eps_count) {
2135 ret = -EINVAL;
2136 goto error;
2137 }
2138 if (ffs->interfaces_count != helper.interfaces_count) {
2139 ret = -EINVAL;
2140 goto error;
2141 }
2142 }
2111 data += ret; 2143 data += ret;
2112 len -= ret; 2144 len -= ret;
2113 } 2145 }
@@ -2342,9 +2374,18 @@ static void ffs_event_add(struct ffs_data *ffs,
2342 spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags); 2374 spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags);
2343} 2375}
2344 2376
2345
2346/* Bind/unbind USB function hooks *******************************************/ 2377/* Bind/unbind USB function hooks *******************************************/
2347 2378
2379static int ffs_ep_addr2idx(struct ffs_data *ffs, u8 endpoint_address)
2380{
2381 int i;
2382
2383 for (i = 1; i < ARRAY_SIZE(ffs->eps_addrmap); ++i)
2384 if (ffs->eps_addrmap[i] == endpoint_address)
2385 return i;
2386 return -ENOENT;
2387}
2388
2348static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep, 2389static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
2349 struct usb_descriptor_header *desc, 2390 struct usb_descriptor_header *desc,
2350 void *priv) 2391 void *priv)
@@ -2378,7 +2419,10 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
2378 if (!desc || desc->bDescriptorType != USB_DT_ENDPOINT) 2419 if (!desc || desc->bDescriptorType != USB_DT_ENDPOINT)
2379 return 0; 2420 return 0;
2380 2421
2381 idx = (ds->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) - 1; 2422 idx = ffs_ep_addr2idx(func->ffs, ds->bEndpointAddress) - 1;
2423 if (idx < 0)
2424 return idx;
2425
2382 ffs_ep = func->eps + idx; 2426 ffs_ep = func->eps + idx;
2383 2427
2384 if (unlikely(ffs_ep->descs[ep_desc_id])) { 2428 if (unlikely(ffs_ep->descs[ep_desc_id])) {
diff --git a/drivers/usb/gadget/function/u_fs.h b/drivers/usb/gadget/function/u_fs.h
index 63d6e71569c1..d48897e8ffeb 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 u8 eps_addrmap[15];
228
227 unsigned short strings_count; 229 unsigned short strings_count;
228 unsigned short interfaces_count; 230 unsigned short interfaces_count;
229 unsigned short eps_count; 231 unsigned short eps_count;