Example of using OS Descriptors in a legacy gadget.

Signed-off-by: Andrzej Pietrasiewicz <andrze...@samsung.com>
---
 drivers/usb/gadget/ether.c | 58 ++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 53 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index c1c113e..2c06f1f 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -24,6 +24,7 @@
 #endif
 
 #include "u_ether.h"
+#include "u_os_desc.h"
 
 
 /*
@@ -316,6 +317,11 @@ static struct usb_configuration eth_config_driver = {
        .bmAttributes           = USB_CONFIG_ATT_SELFPOWER,
 };
 
+static struct usb_os_desc_ext_prop icon_prop;
+static struct usb_os_desc_ext_prop label_prop;
+static const char *os_string = "MSFT100";
+static const char *rndis_label = "RNDIS";
+
 /*-------------------------------------------------------------------------*/
 
 static int __init eth_bind(struct usb_composite_dev *cdev)
@@ -324,6 +330,7 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
        struct f_eem_opts       *eem_opts = NULL;
        struct f_ecm_opts       *ecm_opts = NULL;
        struct f_gether_opts    *geth_opts = NULL;
+       struct f_rndis_opts     *rndis_opts = NULL;
        struct net_device       *net;
        int                     status;
 
@@ -416,18 +423,53 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
        device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
        device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
 
+       status = usb_add_config(cdev, &eth_config_driver, eth_do_config);
+       if (status < 0)
+               goto fail1;
+
        /* register our configuration(s); RNDIS first, if it's used */
        if (has_rndis()) {
+               rndis_opts = container_of(fi_rndis, struct f_rndis_opts,
+                                         func_inst);
+               cdev->use_os_string = true;
+               cdev->b_vendor_code = 0xCA;
+               status = utf8s_to_utf16s(os_string, strlen(os_string),
+                       UTF16_LITTLE_ENDIAN, (wchar_t *) &cdev->qw_sign[0],
+                       OS_STRING_QW_SIGN_LEN);
+               if (status < 0)
+                       goto fail1;
+
+               list_add_tail(&icon_prop.entry,
+                               &rndis_opts->rndis_os_desc.ext_prop);
+               list_add_tail(&label_prop.entry,
+                               &rndis_opts->rndis_os_desc.ext_prop);
+
+               cdev->os_desc_config = &rndis_config_driver;
+               memcpy(&rndis_opts->rndis_os_desc.ext_compat_id[0],
+                       rndis_label, 5);
+
+               icon_prop.type = USB_EXT_PROP_UNICODE_ENV;
+               icon_prop.name = "Icons";
+               icon_prop.name_len = 2 * strlen(icon_prop.name) + 2;
+               icon_prop.data = "%SystemRoot%\\system32\\shell32.dll,-233";
+               icon_prop.data_len = 2 * strlen(icon_prop.data) + 2;
+
+               label_prop.type = USB_EXT_PROP_UNICODE;
+               label_prop.name = "Label";
+               label_prop.name_len = 2 * strlen(label_prop.name) + 2;
+               label_prop.data = "XYZ Device";
+               label_prop.data_len = 2 * strlen(label_prop.data) + 2;
+
+               rndis_opts->rndis_os_desc.ext_prop_len =
+                       icon_prop.name_len + icon_prop.data_len + 14 +
+                       label_prop.name_len + label_prop.data_len + 14;
+               rndis_opts->rndis_os_desc.ext_prop_count = 2;
                status = usb_add_config(cdev, &rndis_config_driver,
                                rndis_do_config);
                if (status < 0)
                        goto fail1;
        }
 
-       status = usb_add_config(cdev, &eth_config_driver, eth_do_config);
-       if (status < 0)
-               goto fail1;
-
        usb_composite_overwrite_options(cdev, &coverwrite);
        dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
                        DRIVER_DESC);
@@ -435,8 +477,11 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
        return 0;
 
 fail1:
-       if (has_rndis())
+       if (has_rndis()) {
+               label_prop.data = NULL;
+               icon_prop.data = NULL;
                usb_put_function_instance(fi_rndis);
+       }
 fail:
        if (use_eem)
                usb_put_function_instance(fi_eem);
@@ -449,7 +494,10 @@ fail:
 
 static int __exit eth_unbind(struct usb_composite_dev *cdev)
 {
+
        if (has_rndis()) {
+               label_prop.data = NULL;
+               icon_prop.data = NULL;
                usb_put_function(f_rndis);
                usb_put_function_instance(fi_rndis);
        }
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to