aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrzej Pietrasiewicz <andrzej.p@samsung.com>2014-07-09 06:20:08 -0400
committerFelipe Balbi <balbi@ti.com>2014-07-10 09:36:52 -0400
commitf0175ab51993d2dc2728e7b22a16ffb0c8f4cfa0 (patch)
tree03931c91c52bcccf6ea95ffb382c45a72839c281
parent7ea4f088c810dab3ba3ab4c7a3879238f790e1fd (diff)
usb: gadget: f_fs: OS descriptors support
Add support for OS descriptors. The new format of descriptors is used, because the "flags" field is required for extensions. os_count gives the number of OSDesc[] elements. The format of descriptors is given in include/uapi/linux/usb/functionfs.h. For extended properties descriptor the usb_ext_prop_desc structure covers only a part of a descriptor, because the wPropertyNameLength is unknown up front. Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com> Acked-by: Michal Nazarewicz <mina86@mina86.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r--drivers/usb/gadget/f_fs.c341
-rw-r--r--drivers/usb/gadget/u_fs.h7
-rw-r--r--include/uapi/linux/usb/functionfs.h81
3 files changed, 419 insertions, 10 deletions
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index e1b2ddd7964a..fe45060e0a7a 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -34,6 +34,7 @@
34 34
35#include "u_fs.h" 35#include "u_fs.h"
36#include "u_f.h" 36#include "u_f.h"
37#include "u_os_desc.h"
37#include "configfs.h" 38#include "configfs.h"
38 39
39#define FUNCTIONFS_MAGIC 0xa647361 /* Chosen by a honest dice roll ;) */ 40#define FUNCTIONFS_MAGIC 0xa647361 /* Chosen by a honest dice roll ;) */
@@ -1644,11 +1645,19 @@ enum ffs_entity_type {
1644 FFS_DESCRIPTOR, FFS_INTERFACE, FFS_STRING, FFS_ENDPOINT 1645 FFS_DESCRIPTOR, FFS_INTERFACE, FFS_STRING, FFS_ENDPOINT
1645}; 1646};
1646 1647
1648enum ffs_os_desc_type {
1649 FFS_OS_DESC, FFS_OS_DESC_EXT_COMPAT, FFS_OS_DESC_EXT_PROP
1650};
1651
1647typedef int (*ffs_entity_callback)(enum ffs_entity_type entity, 1652typedef int (*ffs_entity_callback)(enum ffs_entity_type entity,
1648 u8 *valuep, 1653 u8 *valuep,
1649 struct usb_descriptor_header *desc, 1654 struct usb_descriptor_header *desc,
1650 void *priv); 1655 void *priv);
1651 1656
1657typedef int (*ffs_os_desc_callback)(enum ffs_os_desc_type entity,
1658 struct usb_os_desc_header *h, void *data,
1659 unsigned len, void *priv);
1660
1652static int __must_check ffs_do_single_desc(char *data, unsigned len, 1661static int __must_check ffs_do_single_desc(char *data, unsigned len,
1653 ffs_entity_callback entity, 1662 ffs_entity_callback entity,
1654 void *priv) 1663 void *priv)
@@ -1856,11 +1865,191 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
1856 return 0; 1865 return 0;
1857} 1866}
1858 1867
1868static int __ffs_do_os_desc_header(enum ffs_os_desc_type *next_type,
1869 struct usb_os_desc_header *desc)
1870{
1871 u16 bcd_version = le16_to_cpu(desc->bcdVersion);
1872 u16 w_index = le16_to_cpu(desc->wIndex);
1873
1874 if (bcd_version != 1) {
1875 pr_vdebug("unsupported os descriptors version: %d",
1876 bcd_version);
1877 return -EINVAL;
1878 }
1879 switch (w_index) {
1880 case 0x4:
1881 *next_type = FFS_OS_DESC_EXT_COMPAT;
1882 break;
1883 case 0x5:
1884 *next_type = FFS_OS_DESC_EXT_PROP;
1885 break;
1886 default:
1887 pr_vdebug("unsupported os descriptor type: %d", w_index);
1888 return -EINVAL;
1889 }
1890
1891 return sizeof(*desc);
1892}
1893
1894/*
1895 * Process all extended compatibility/extended property descriptors
1896 * of a feature descriptor
1897 */
1898static int __must_check ffs_do_single_os_desc(char *data, unsigned len,
1899 enum ffs_os_desc_type type,
1900 u16 feature_count,
1901 ffs_os_desc_callback entity,
1902 void *priv,
1903 struct usb_os_desc_header *h)
1904{
1905 int ret;
1906 const unsigned _len = len;
1907
1908 ENTER();
1909
1910 /* loop over all ext compat/ext prop descriptors */
1911 while (feature_count--) {
1912 ret = entity(type, h, data, len, priv);
1913 if (unlikely(ret < 0)) {
1914 pr_debug("bad OS descriptor, type: %d\n", type);
1915 return ret;
1916 }
1917 data += ret;
1918 len -= ret;
1919 }
1920 return _len - len;
1921}
1922
1923/* Process a number of complete Feature Descriptors (Ext Compat or Ext Prop) */
1924static int __must_check ffs_do_os_descs(unsigned count,
1925 char *data, unsigned len,
1926 ffs_os_desc_callback entity, void *priv)
1927{
1928 const unsigned _len = len;
1929 unsigned long num = 0;
1930
1931 ENTER();
1932
1933 for (num = 0; num < count; ++num) {
1934 int ret;
1935 enum ffs_os_desc_type type;
1936 u16 feature_count;
1937 struct usb_os_desc_header *desc = (void *)data;
1938
1939 if (len < sizeof(*desc))
1940 return -EINVAL;
1941
1942 /*
1943 * Record "descriptor" entity.
1944 * Process dwLength, bcdVersion, wIndex, get b/wCount.
1945 * Move the data pointer to the beginning of extended
1946 * compatibilities proper or extended properties proper
1947 * portions of the data
1948 */
1949 if (le32_to_cpu(desc->dwLength) > len)
1950 return -EINVAL;
1951
1952 ret = __ffs_do_os_desc_header(&type, desc);
1953 if (unlikely(ret < 0)) {
1954 pr_debug("entity OS_DESCRIPTOR(%02lx); ret = %d\n",
1955 num, ret);
1956 return ret;
1957 }
1958 /*
1959 * 16-bit hex "?? 00" Little Endian looks like 8-bit hex "??"
1960 */
1961 feature_count = le16_to_cpu(desc->wCount);
1962 if (type == FFS_OS_DESC_EXT_COMPAT &&
1963 (feature_count > 255 || desc->Reserved))
1964 return -EINVAL;
1965 len -= ret;
1966 data += ret;
1967
1968 /*
1969 * Process all function/property descriptors
1970 * of this Feature Descriptor
1971 */
1972 ret = ffs_do_single_os_desc(data, len, type,
1973 feature_count, entity, priv, desc);
1974 if (unlikely(ret < 0)) {
1975 pr_debug("%s returns %d\n", __func__, ret);
1976 return ret;
1977 }
1978
1979 len -= ret;
1980 data += ret;
1981 }
1982 return _len - len;
1983}
1984
1985/**
1986 * Validate contents of the buffer from userspace related to OS descriptors.
1987 */
1988static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
1989 struct usb_os_desc_header *h, void *data,
1990 unsigned len, void *priv)
1991{
1992 struct ffs_data *ffs = priv;
1993 u8 length;
1994
1995 ENTER();
1996
1997 switch (type) {
1998 case FFS_OS_DESC_EXT_COMPAT: {
1999 struct usb_ext_compat_desc *d = data;
2000 int i;
2001
2002 if (len < sizeof(*d) ||
2003 d->bFirstInterfaceNumber >= ffs->interfaces_count ||
2004 d->Reserved1)
2005 return -EINVAL;
2006 for (i = 0; i < ARRAY_SIZE(d->Reserved2); ++i)
2007 if (d->Reserved2[i])
2008 return -EINVAL;
2009
2010 length = sizeof(struct usb_ext_compat_desc);
2011 }
2012 break;
2013 case FFS_OS_DESC_EXT_PROP: {
2014 struct usb_ext_prop_desc *d = data;
2015 u32 type, pdl;
2016 u16 pnl;
2017
2018 if (len < sizeof(*d) || h->interface >= ffs->interfaces_count)
2019 return -EINVAL;
2020 length = le32_to_cpu(d->dwSize);
2021 type = le32_to_cpu(d->dwPropertyDataType);
2022 if (type < USB_EXT_PROP_UNICODE ||
2023 type > USB_EXT_PROP_UNICODE_MULTI) {
2024 pr_vdebug("unsupported os descriptor property type: %d",
2025 type);
2026 return -EINVAL;
2027 }
2028 pnl = le16_to_cpu(d->wPropertyNameLength);
2029 pdl = le32_to_cpu(*(u32 *)((u8 *)data + 10 + pnl));
2030 if (length != 14 + pnl + pdl) {
2031 pr_vdebug("invalid os descriptor length: %d pnl:%d pdl:%d (descriptor %d)\n",
2032 length, pnl, pdl, type);
2033 return -EINVAL;
2034 }
2035 ++ffs->ms_os_descs_ext_prop_count;
2036 /* property name reported to the host as "WCHAR"s */
2037 ffs->ms_os_descs_ext_prop_name_len += pnl * 2;
2038 ffs->ms_os_descs_ext_prop_data_len += pdl;
2039 }
2040 break;
2041 default:
2042 pr_vdebug("unknown descriptor: %d\n", type);
2043 return -EINVAL;
2044 }
2045 return length;
2046}
2047
1859static int __ffs_data_got_descs(struct ffs_data *ffs, 2048static int __ffs_data_got_descs(struct ffs_data *ffs,
1860 char *const _data, size_t len) 2049 char *const _data, size_t len)
1861{ 2050{
1862 char *data = _data, *raw_descs; 2051 char *data = _data, *raw_descs;
1863 unsigned counts[3], flags; 2052 unsigned os_descs_count = 0, counts[3], flags;
1864 int ret = -EINVAL, i; 2053 int ret = -EINVAL, i;
1865 2054
1866 ENTER(); 2055 ENTER();
@@ -1878,7 +2067,8 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
1878 flags = get_unaligned_le32(data + 8); 2067 flags = get_unaligned_le32(data + 8);
1879 if (flags & ~(FUNCTIONFS_HAS_FS_DESC | 2068 if (flags & ~(FUNCTIONFS_HAS_FS_DESC |
1880 FUNCTIONFS_HAS_HS_DESC | 2069 FUNCTIONFS_HAS_HS_DESC |
1881 FUNCTIONFS_HAS_SS_DESC)) { 2070 FUNCTIONFS_HAS_SS_DESC |
2071 FUNCTIONFS_HAS_MS_OS_DESC)) {
1882 ret = -ENOSYS; 2072 ret = -ENOSYS;
1883 goto error; 2073 goto error;
1884 } 2074 }
@@ -1901,6 +2091,11 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
1901 len -= 4; 2091 len -= 4;
1902 } 2092 }
1903 } 2093 }
2094 if (flags & (1 << i)) {
2095 os_descs_count = get_unaligned_le32(data);
2096 data += 4;
2097 len -= 4;
2098 };
1904 2099
1905 /* Read descriptors */ 2100 /* Read descriptors */
1906 raw_descs = data; 2101 raw_descs = data;
@@ -1914,6 +2109,14 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
1914 data += ret; 2109 data += ret;
1915 len -= ret; 2110 len -= ret;
1916 } 2111 }
2112 if (os_descs_count) {
2113 ret = ffs_do_os_descs(os_descs_count, data, len,
2114 __ffs_data_do_os_desc, ffs);
2115 if (ret < 0)
2116 goto error;
2117 data += ret;
2118 len -= ret;
2119 }
1917 2120
1918 if (raw_descs == data || len) { 2121 if (raw_descs == data || len) {
1919 ret = -EINVAL; 2122 ret = -EINVAL;
@@ -1926,6 +2129,7 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
1926 ffs->fs_descs_count = counts[0]; 2129 ffs->fs_descs_count = counts[0];
1927 ffs->hs_descs_count = counts[1]; 2130 ffs->hs_descs_count = counts[1];
1928 ffs->ss_descs_count = counts[2]; 2131 ffs->ss_descs_count = counts[2];
2132 ffs->ms_os_descs_count = os_descs_count;
1929 2133
1930 return 0; 2134 return 0;
1931 2135
@@ -2267,6 +2471,85 @@ static int __ffs_func_bind_do_nums(enum ffs_entity_type type, u8 *valuep,
2267 return 0; 2471 return 0;
2268} 2472}
2269 2473
2474static int __ffs_func_bind_do_os_desc(enum ffs_os_desc_type type,
2475 struct usb_os_desc_header *h, void *data,
2476 unsigned len, void *priv)
2477{
2478 struct ffs_function *func = priv;
2479 u8 length = 0;
2480
2481 switch (type) {
2482 case FFS_OS_DESC_EXT_COMPAT: {
2483 struct usb_ext_compat_desc *desc = data;
2484 struct usb_os_desc_table *t;
2485
2486 t = &func->function.os_desc_table[desc->bFirstInterfaceNumber];
2487 t->if_id = func->interfaces_nums[desc->bFirstInterfaceNumber];
2488 memcpy(t->os_desc->ext_compat_id, &desc->CompatibleID,
2489 ARRAY_SIZE(desc->CompatibleID) +
2490 ARRAY_SIZE(desc->SubCompatibleID));
2491 length = sizeof(*desc);
2492 }
2493 break;
2494 case FFS_OS_DESC_EXT_PROP: {
2495 struct usb_ext_prop_desc *desc = data;
2496 struct usb_os_desc_table *t;
2497 struct usb_os_desc_ext_prop *ext_prop;
2498 char *ext_prop_name;
2499 char *ext_prop_data;
2500
2501 t = &func->function.os_desc_table[h->interface];
2502 t->if_id = func->interfaces_nums[h->interface];
2503
2504 ext_prop = func->ffs->ms_os_descs_ext_prop_avail;
2505 func->ffs->ms_os_descs_ext_prop_avail += sizeof(*ext_prop);
2506
2507 ext_prop->type = le32_to_cpu(desc->dwPropertyDataType);
2508 ext_prop->name_len = le16_to_cpu(desc->wPropertyNameLength);
2509 ext_prop->data_len = le32_to_cpu(*(u32 *)
2510 usb_ext_prop_data_len_ptr(data, ext_prop->name_len));
2511 length = ext_prop->name_len + ext_prop->data_len + 14;
2512
2513 ext_prop_name = func->ffs->ms_os_descs_ext_prop_name_avail;
2514 func->ffs->ms_os_descs_ext_prop_name_avail +=
2515 ext_prop->name_len;
2516
2517 ext_prop_data = func->ffs->ms_os_descs_ext_prop_data_avail;
2518 func->ffs->ms_os_descs_ext_prop_data_avail +=
2519 ext_prop->data_len;
2520 memcpy(ext_prop_data,
2521 usb_ext_prop_data_ptr(data, ext_prop->name_len),
2522 ext_prop->data_len);
2523 /* unicode data reported to the host as "WCHAR"s */
2524 switch (ext_prop->type) {
2525 case USB_EXT_PROP_UNICODE:
2526 case USB_EXT_PROP_UNICODE_ENV:
2527 case USB_EXT_PROP_UNICODE_LINK:
2528 case USB_EXT_PROP_UNICODE_MULTI:
2529 ext_prop->data_len *= 2;
2530 break;
2531 }
2532 ext_prop->data = ext_prop_data;
2533
2534 memcpy(ext_prop_name, usb_ext_prop_name_ptr(data),
2535 ext_prop->name_len);
2536 /* property name reported to the host as "WCHAR"s */
2537 ext_prop->name_len *= 2;
2538 ext_prop->name = ext_prop_name;
2539
2540 t->os_desc->ext_prop_len +=
2541 ext_prop->name_len + ext_prop->data_len + 14;
2542 ++t->os_desc->ext_prop_count;
2543 list_add_tail(&ext_prop->entry, &t->os_desc->ext_prop);
2544 }
2545 break;
2546 default:
2547 pr_vdebug("unknown descriptor: %d\n", type);
2548 }
2549
2550 return length;
2551}
2552
2270static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f, 2553static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f,
2271 struct usb_configuration *c) 2554 struct usb_configuration *c)
2272{ 2555{
@@ -2328,7 +2611,7 @@ static int _ffs_func_bind(struct usb_configuration *c,
2328 const int super = gadget_is_superspeed(func->gadget) && 2611 const int super = gadget_is_superspeed(func->gadget) &&
2329 func->ffs->ss_descs_count; 2612 func->ffs->ss_descs_count;
2330 2613
2331 int fs_len, hs_len, ret; 2614 int fs_len, hs_len, ss_len, ret, i;
2332 2615
2333 /* Make it a single chunk, less management later on */ 2616 /* Make it a single chunk, less management later on */
2334 vla_group(d); 2617 vla_group(d);
@@ -2340,6 +2623,18 @@ static int _ffs_func_bind(struct usb_configuration *c,
2340 vla_item_with_sz(d, struct usb_descriptor_header *, ss_descs, 2623 vla_item_with_sz(d, struct usb_descriptor_header *, ss_descs,
2341 super ? ffs->ss_descs_count + 1 : 0); 2624 super ? ffs->ss_descs_count + 1 : 0);
2342 vla_item_with_sz(d, short, inums, ffs->interfaces_count); 2625 vla_item_with_sz(d, short, inums, ffs->interfaces_count);
2626 vla_item_with_sz(d, struct usb_os_desc_table, os_desc_table,
2627 c->cdev->use_os_string ? ffs->interfaces_count : 0);
2628 vla_item_with_sz(d, char[16], ext_compat,
2629 c->cdev->use_os_string ? ffs->interfaces_count : 0);
2630 vla_item_with_sz(d, struct usb_os_desc, os_desc,
2631 c->cdev->use_os_string ? ffs->interfaces_count : 0);
2632 vla_item_with_sz(d, struct usb_os_desc_ext_prop, ext_prop,
2633 ffs->ms_os_descs_ext_prop_count);
2634 vla_item_with_sz(d, char, ext_prop_name,
2635 ffs->ms_os_descs_ext_prop_name_len);
2636 vla_item_with_sz(d, char, ext_prop_data,
2637 ffs->ms_os_descs_ext_prop_data_len);
2343 vla_item_with_sz(d, char, raw_descs, ffs->raw_descs_length); 2638 vla_item_with_sz(d, char, raw_descs, ffs->raw_descs_length);
2344 char *vlabuf; 2639 char *vlabuf;
2345 2640
@@ -2350,12 +2645,16 @@ static int _ffs_func_bind(struct usb_configuration *c,
2350 return -ENOTSUPP; 2645 return -ENOTSUPP;
2351 2646
2352 /* Allocate a single chunk, less management later on */ 2647 /* Allocate a single chunk, less management later on */
2353 vlabuf = kmalloc(vla_group_size(d), GFP_KERNEL); 2648 vlabuf = kzalloc(vla_group_size(d), GFP_KERNEL);
2354 if (unlikely(!vlabuf)) 2649 if (unlikely(!vlabuf))
2355 return -ENOMEM; 2650 return -ENOMEM;
2356 2651
2357 /* Zero */ 2652 ffs->ms_os_descs_ext_prop_avail = vla_ptr(vlabuf, d, ext_prop);
2358 memset(vla_ptr(vlabuf, d, eps), 0, d_eps__sz); 2653 ffs->ms_os_descs_ext_prop_name_avail =
2654 vla_ptr(vlabuf, d, ext_prop_name);
2655 ffs->ms_os_descs_ext_prop_data_avail =
2656 vla_ptr(vlabuf, d, ext_prop_data);
2657
2359 /* Copy descriptors */ 2658 /* Copy descriptors */
2360 memcpy(vla_ptr(vlabuf, d, raw_descs), ffs->raw_descs, 2659 memcpy(vla_ptr(vlabuf, d, raw_descs), ffs->raw_descs,
2361 ffs->raw_descs_length); 2660 ffs->raw_descs_length);
@@ -2409,12 +2708,16 @@ static int _ffs_func_bind(struct usb_configuration *c,
2409 2708
2410 if (likely(super)) { 2709 if (likely(super)) {
2411 func->function.ss_descriptors = vla_ptr(vlabuf, d, ss_descs); 2710 func->function.ss_descriptors = vla_ptr(vlabuf, d, ss_descs);
2412 ret = ffs_do_descs(ffs->ss_descs_count, 2711 ss_len = ffs_do_descs(ffs->ss_descs_count,
2413 vla_ptr(vlabuf, d, raw_descs) + fs_len + hs_len, 2712 vla_ptr(vlabuf, d, raw_descs) + fs_len + hs_len,
2414 d_raw_descs__sz - fs_len - hs_len, 2713 d_raw_descs__sz - fs_len - hs_len,
2415 __ffs_func_bind_do_descs, func); 2714 __ffs_func_bind_do_descs, func);
2416 if (unlikely(ret < 0)) 2715 if (unlikely(ss_len < 0)) {
2716 ret = ss_len;
2417 goto error; 2717 goto error;
2718 }
2719 } else {
2720 ss_len = 0;
2418 } 2721 }
2419 2722
2420 /* 2723 /*
@@ -2430,6 +2733,28 @@ static int _ffs_func_bind(struct usb_configuration *c,
2430 if (unlikely(ret < 0)) 2733 if (unlikely(ret < 0))
2431 goto error; 2734 goto error;
2432 2735
2736 func->function.os_desc_table = vla_ptr(vlabuf, d, os_desc_table);
2737 if (c->cdev->use_os_string)
2738 for (i = 0; i < ffs->interfaces_count; ++i) {
2739 struct usb_os_desc *desc;
2740
2741 desc = func->function.os_desc_table[i].os_desc =
2742 vla_ptr(vlabuf, d, os_desc) +
2743 i * sizeof(struct usb_os_desc);
2744 desc->ext_compat_id =
2745 vla_ptr(vlabuf, d, ext_compat) + i * 16;
2746 INIT_LIST_HEAD(&desc->ext_prop);
2747 }
2748 ret = ffs_do_os_descs(ffs->ms_os_descs_count,
2749 vla_ptr(vlabuf, d, raw_descs) +
2750 fs_len + hs_len + ss_len,
2751 d_raw_descs__sz - fs_len - hs_len - ss_len,
2752 __ffs_func_bind_do_os_desc, func);
2753 if (unlikely(ret < 0))
2754 goto error;
2755 func->function.os_desc_n =
2756 c->cdev->use_os_string ? ffs->interfaces_count : 0;
2757
2433 /* And we're done */ 2758 /* And we're done */
2434 ffs_event_add(ffs, FUNCTIONFS_BIND); 2759 ffs_event_add(ffs, FUNCTIONFS_BIND);
2435 return 0; 2760 return 0;
diff --git a/drivers/usb/gadget/u_fs.h b/drivers/usb/gadget/u_fs.h
index bf0ba375d459..63d6e71569c1 100644
--- a/drivers/usb/gadget/u_fs.h
+++ b/drivers/usb/gadget/u_fs.h
@@ -216,6 +216,13 @@ struct ffs_data {
216 unsigned fs_descs_count; 216 unsigned fs_descs_count;
217 unsigned hs_descs_count; 217 unsigned hs_descs_count;
218 unsigned ss_descs_count; 218 unsigned ss_descs_count;
219 unsigned ms_os_descs_count;
220 unsigned ms_os_descs_ext_prop_count;
221 unsigned ms_os_descs_ext_prop_name_len;
222 unsigned ms_os_descs_ext_prop_data_len;
223 void *ms_os_descs_ext_prop_avail;
224 void *ms_os_descs_ext_prop_name_avail;
225 void *ms_os_descs_ext_prop_data_avail;
219 226
220 unsigned short strings_count; 227 unsigned short strings_count;
221 unsigned short interfaces_count; 228 unsigned short interfaces_count;
diff --git a/include/uapi/linux/usb/functionfs.h b/include/uapi/linux/usb/functionfs.h
index 2a4b4a72a4f9..b66fae77c08c 100644
--- a/include/uapi/linux/usb/functionfs.h
+++ b/include/uapi/linux/usb/functionfs.h
@@ -18,10 +18,9 @@ enum functionfs_flags {
18 FUNCTIONFS_HAS_FS_DESC = 1, 18 FUNCTIONFS_HAS_FS_DESC = 1,
19 FUNCTIONFS_HAS_HS_DESC = 2, 19 FUNCTIONFS_HAS_HS_DESC = 2,
20 FUNCTIONFS_HAS_SS_DESC = 4, 20 FUNCTIONFS_HAS_SS_DESC = 4,
21 FUNCTIONFS_HAS_MS_OS_DESC = 8,
21}; 22};
22 23
23#ifndef __KERNEL__
24
25/* Descriptor of an non-audio endpoint */ 24/* Descriptor of an non-audio endpoint */
26struct usb_endpoint_descriptor_no_audio { 25struct usb_endpoint_descriptor_no_audio {
27 __u8 bLength; 26 __u8 bLength;
@@ -33,6 +32,36 @@ struct usb_endpoint_descriptor_no_audio {
33 __u8 bInterval; 32 __u8 bInterval;
34} __attribute__((packed)); 33} __attribute__((packed));
35 34
35/* MS OS Descriptor header */
36struct usb_os_desc_header {
37 __u8 interface;
38 __le32 dwLength;
39 __le16 bcdVersion;
40 __le16 wIndex;
41 union {
42 struct {
43 __u8 bCount;
44 __u8 Reserved;
45 };
46 __le16 wCount;
47 };
48} __attribute__((packed));
49
50struct usb_ext_compat_desc {
51 __u8 bFirstInterfaceNumber;
52 __u8 Reserved1;
53 __u8 CompatibleID[8];
54 __u8 SubCompatibleID[8];
55 __u8 Reserved2[6];
56};
57
58struct usb_ext_prop_desc {
59 __le32 dwSize;
60 __le32 dwPropertyDataType;
61 __le16 wPropertyNameLength;
62} __attribute__((packed));
63
64#ifndef __KERNEL__
36 65
37/* 66/*
38 * Descriptors format: 67 * Descriptors format:
@@ -45,9 +74,11 @@ struct usb_endpoint_descriptor_no_audio {
45 * | | fs_count | LE32 | number of full-speed descriptors | 74 * | | fs_count | LE32 | number of full-speed descriptors |
46 * | | hs_count | LE32 | number of high-speed descriptors | 75 * | | hs_count | LE32 | number of high-speed descriptors |
47 * | | ss_count | LE32 | number of super-speed descriptors | 76 * | | ss_count | LE32 | number of super-speed descriptors |
77 * | | os_count | LE32 | number of MS OS descriptors |
48 * | | fs_descrs | Descriptor[] | list of full-speed descriptors | 78 * | | fs_descrs | Descriptor[] | list of full-speed descriptors |
49 * | | hs_descrs | Descriptor[] | list of high-speed descriptors | 79 * | | hs_descrs | Descriptor[] | list of high-speed descriptors |
50 * | | ss_descrs | Descriptor[] | list of super-speed descriptors | 80 * | | ss_descrs | Descriptor[] | list of super-speed descriptors |
81 * | | os_descrs | OSDesc[] | list of MS OS descriptors |
51 * 82 *
52 * Depending on which flags are set, various fields may be missing in the 83 * Depending on which flags are set, various fields may be missing in the
53 * structure. Any flags that are not recognised cause the whole block to be 84 * structure. Any flags that are not recognised cause the whole block to be
@@ -74,6 +105,52 @@ struct usb_endpoint_descriptor_no_audio {
74 * | 0 | bLength | U8 | length of the descriptor | 105 * | 0 | bLength | U8 | length of the descriptor |
75 * | 1 | bDescriptorType | U8 | descriptor type | 106 * | 1 | bDescriptorType | U8 | descriptor type |
76 * | 2 | payload | | descriptor's payload | 107 * | 2 | payload | | descriptor's payload |
108 *
109 * OSDesc[] is an array of valid MS OS Feature Descriptors which have one of
110 * the following formats:
111 *
112 * | off | name | type | description |
113 * |-----+-----------------+------+--------------------------|
114 * | 0 | inteface | U8 | related interface number |
115 * | 1 | dwLength | U32 | length of the descriptor |
116 * | 5 | bcdVersion | U16 | currently supported: 1 |
117 * | 7 | wIndex | U16 | currently supported: 4 |
118 * | 9 | bCount | U8 | number of ext. compat. |
119 * | 10 | Reserved | U8 | 0 |
120 * | 11 | ExtCompat[] | | list of ext. compat. d. |
121 *
122 * | off | name | type | description |
123 * |-----+-----------------+------+--------------------------|
124 * | 0 | inteface | U8 | related interface number |
125 * | 1 | dwLength | U32 | length of the descriptor |
126 * | 5 | bcdVersion | U16 | currently supported: 1 |
127 * | 7 | wIndex | U16 | currently supported: 5 |
128 * | 9 | wCount | U16 | number of ext. compat. |
129 * | 11 | ExtProp[] | | list of ext. prop. d. |
130 *
131 * ExtCompat[] is an array of valid Extended Compatiblity descriptors
132 * which have the following format:
133 *
134 * | off | name | type | description |
135 * |-----+-----------------------+------+-------------------------------------|
136 * | 0 | bFirstInterfaceNumber | U8 | index of the interface or of the 1st|
137 * | | | | interface in an IAD group |
138 * | 1 | Reserved | U8 | 0 |
139 * | 2 | CompatibleID | U8[8]| compatible ID string |
140 * | 10 | SubCompatibleID | U8[8]| subcompatible ID string |
141 * | 18 | Reserved | U8[6]| 0 |
142 *
143 * ExtProp[] is an array of valid Extended Properties descriptors
144 * which have the following format:
145 *
146 * | off | name | type | description |
147 * |-----+-----------------------+------+-------------------------------------|
148 * | 0 | dwSize | U32 | length of the descriptor |
149 * | 4 | dwPropertyDataType | U32 | 1..7 |
150 * | 8 | wPropertyNameLength | U16 | bPropertyName length (NL) |
151 * | 10 | bPropertyName |U8[NL]| name of this property |
152 * |10+NL| dwPropertyDataLength | U32 | bPropertyData length (DL) |
153 * |14+NL| bProperty |U8[DL]| payload of this property |
77 */ 154 */
78 155
79struct usb_functionfs_strings_head { 156struct usb_functionfs_strings_head {