linux/drivers/usb/gadget/u_os_desc.h
Andrzej Pietrasiewicz 37a3a53342 usb: gadget: OS Feature Descriptors support
There is a custom (non-USB IF) extension to the USB standard:

http://msdn.microsoft.com/library/windows/hardware/gg463182

They grant permission to use the specification - there is
"Microsoft OS Descriptor Specification License Agreement"
under the link mentioned above, and its Section 2 "Grant
of License", letter (b) reads:

"Patent license. Microsoft hereby grants to You a nonexclusive,
royalty-free, nontransferable, worldwide license under Microsoft’s
patents embodied solely within the Specification and that are owned
or licensable by Microsoft to make, use, import, offer to sell,
sell and distribute directly or indirectly to Your Licensees Your
Implementation. You may sublicense this patent license to Your
Licensees under the same terms and conditions."

The said extension is maintained by Microsoft for Microsoft.

Yet it is fairly common for various devices to use it, and a
popular proprietary operating system expects devices to provide
"OS descriptors", so Linux-based USB gadgets whishing to be able
to talk to a variety of operating systems should be able to provide
the "OS descriptors".

This patch adds optional support for gadgets whishing to expose
the so called "OS Feature Descriptors", that is "Extended Compatibility ID"
and "Extended Properties".

Hosts which do request "OS descriptors" from gadgets do so during
the enumeration phase and before the configuration is set with
SET_CONFIGURATION. What is more, those hosts never ask for configurations
at indices other than 0. Therefore, gadgets whishing to provide
"OS descriptors" must designate one configuration to be used with
this kind of hosts - this is what os_desc_config is added for in
struct usb_composite_dev. There is an additional advantage to it:
if a gadget provides "OS descriptors" and designates one configuration
to be used with such non-USB-compliant hosts it can invoke
"usb_add_config" in any order because the designated configuration
will be reported to be at index 0 anyway.

This patch also adds handling vendor-specific requests addressed
at device or interface and related to handling "OS descriptors".

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Acked-by: Michal Nazarewicz <mina86@mina86.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
2014-05-14 09:38:16 -05:00

91 lines
2.4 KiB
C

/*
* u_os_desc.h
*
* Utility definitions for "OS Descriptors" support
*
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __U_OS_DESC_H__
#define __U_OS_DESC_H__
#include <asm/unaligned.h>
#include <linux/nls.h>
#define USB_EXT_PROP_DW_SIZE 0
#define USB_EXT_PROP_DW_PROPERTY_DATA_TYPE 4
#define USB_EXT_PROP_W_PROPERTY_NAME_LENGTH 8
#define USB_EXT_PROP_B_PROPERTY_NAME 10
#define USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH 10
#define USB_EXT_PROP_B_PROPERTY_DATA 14
#define USB_EXT_PROP_RESERVED 0
#define USB_EXT_PROP_UNICODE 1
#define USB_EXT_PROP_UNICODE_ENV 2
#define USB_EXT_PROP_BINARY 3
#define USB_EXT_PROP_LE32 4
#define USB_EXT_PROP_BE32 5
#define USB_EXT_PROP_UNICODE_LINK 6
#define USB_EXT_PROP_UNICODE_MULTI 7
static inline void usb_ext_prop_put_size(u8 *buf, int dw_size)
{
put_unaligned_le32(dw_size, &buf[USB_EXT_PROP_DW_SIZE]);
}
static inline void usb_ext_prop_put_type(u8 *buf, int type)
{
put_unaligned_le32(type, &buf[USB_EXT_PROP_DW_PROPERTY_DATA_TYPE]);
}
static inline int usb_ext_prop_put_name(u8 *buf, const char *name, int pnl)
{
int result;
put_unaligned_le16(pnl, &buf[USB_EXT_PROP_W_PROPERTY_NAME_LENGTH]);
result = utf8s_to_utf16s(name, strlen(name), UTF16_LITTLE_ENDIAN,
(wchar_t *) &buf[USB_EXT_PROP_B_PROPERTY_NAME], pnl - 2);
if (result < 0)
return result;
put_unaligned_le16(0, &buf[USB_EXT_PROP_B_PROPERTY_NAME + pnl]);
return pnl;
}
static inline void usb_ext_prop_put_binary(u8 *buf, int pnl, const u8 *data,
int data_len)
{
put_unaligned_le32(data_len,
&buf[USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + pnl]);
memcpy(&buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl], data, data_len);
}
static inline int usb_ext_prop_put_unicode(u8 *buf, int pnl, const char *string,
int data_len)
{
int result;
put_unaligned_le32(data_len,
&buf[USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + pnl]);
result = utf8s_to_utf16s(string, data_len >> 1, UTF16_LITTLE_ENDIAN,
(wchar_t *) &buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl],
data_len - 2);
if (result < 0)
return result;
put_unaligned_le16(0,
&buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl + data_len]);
return data_len;
}
#endif /* __U_OS_DESC_H__ */