xref: /linux/drivers/usb/gadget/u_os_desc.h (revision 7ec462100ef9142344ddbf86f2c3008b97acddbe)
15fd54aceSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
237a3a533SAndrzej Pietrasiewicz /*
337a3a533SAndrzej Pietrasiewicz  * u_os_desc.h
437a3a533SAndrzej Pietrasiewicz  *
537a3a533SAndrzej Pietrasiewicz  * Utility definitions for "OS Descriptors" support
637a3a533SAndrzej Pietrasiewicz  *
737a3a533SAndrzej Pietrasiewicz  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
837a3a533SAndrzej Pietrasiewicz  *		http://www.samsung.com
937a3a533SAndrzej Pietrasiewicz  *
101b4a3b51SAndrzej Pietrasiewicz  * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
1137a3a533SAndrzej Pietrasiewicz  */
1237a3a533SAndrzej Pietrasiewicz 
1337a3a533SAndrzej Pietrasiewicz #ifndef __U_OS_DESC_H__
1437a3a533SAndrzej Pietrasiewicz #define __U_OS_DESC_H__
1537a3a533SAndrzej Pietrasiewicz 
16*5f60d5f6SAl Viro #include <linux/unaligned.h>
1737a3a533SAndrzej Pietrasiewicz #include <linux/nls.h>
1837a3a533SAndrzej Pietrasiewicz 
1937a3a533SAndrzej Pietrasiewicz #define USB_EXT_PROP_DW_SIZE			0
2037a3a533SAndrzej Pietrasiewicz #define USB_EXT_PROP_DW_PROPERTY_DATA_TYPE	4
2137a3a533SAndrzej Pietrasiewicz #define USB_EXT_PROP_W_PROPERTY_NAME_LENGTH	8
2237a3a533SAndrzej Pietrasiewicz #define USB_EXT_PROP_B_PROPERTY_NAME		10
2337a3a533SAndrzej Pietrasiewicz #define USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH	10
2437a3a533SAndrzej Pietrasiewicz #define USB_EXT_PROP_B_PROPERTY_DATA		14
2537a3a533SAndrzej Pietrasiewicz 
2637a3a533SAndrzej Pietrasiewicz #define USB_EXT_PROP_RESERVED			0
2737a3a533SAndrzej Pietrasiewicz #define USB_EXT_PROP_UNICODE			1
2837a3a533SAndrzej Pietrasiewicz #define USB_EXT_PROP_UNICODE_ENV		2
2937a3a533SAndrzej Pietrasiewicz #define USB_EXT_PROP_BINARY			3
3037a3a533SAndrzej Pietrasiewicz #define USB_EXT_PROP_LE32			4
3137a3a533SAndrzej Pietrasiewicz #define USB_EXT_PROP_BE32			5
3237a3a533SAndrzej Pietrasiewicz #define USB_EXT_PROP_UNICODE_LINK		6
3337a3a533SAndrzej Pietrasiewicz #define USB_EXT_PROP_UNICODE_MULTI		7
3437a3a533SAndrzej Pietrasiewicz 
__usb_ext_prop_ptr(u8 * buf,size_t offset)357ea4f088SAndrzej Pietrasiewicz static inline u8 *__usb_ext_prop_ptr(u8 *buf, size_t offset)
367ea4f088SAndrzej Pietrasiewicz {
377ea4f088SAndrzej Pietrasiewicz 	return buf + offset;
387ea4f088SAndrzej Pietrasiewicz }
397ea4f088SAndrzej Pietrasiewicz 
usb_ext_prop_size_ptr(u8 * buf)407ea4f088SAndrzej Pietrasiewicz static inline u8 *usb_ext_prop_size_ptr(u8 *buf)
417ea4f088SAndrzej Pietrasiewicz {
427ea4f088SAndrzej Pietrasiewicz 	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_DW_SIZE);
437ea4f088SAndrzej Pietrasiewicz }
447ea4f088SAndrzej Pietrasiewicz 
usb_ext_prop_type_ptr(u8 * buf)457ea4f088SAndrzej Pietrasiewicz static inline u8 *usb_ext_prop_type_ptr(u8 *buf)
467ea4f088SAndrzej Pietrasiewicz {
477ea4f088SAndrzej Pietrasiewicz 	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_DW_PROPERTY_DATA_TYPE);
487ea4f088SAndrzej Pietrasiewicz }
497ea4f088SAndrzej Pietrasiewicz 
usb_ext_prop_name_len_ptr(u8 * buf)507ea4f088SAndrzej Pietrasiewicz static inline u8 *usb_ext_prop_name_len_ptr(u8 *buf)
517ea4f088SAndrzej Pietrasiewicz {
527ea4f088SAndrzej Pietrasiewicz 	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_W_PROPERTY_NAME_LENGTH);
537ea4f088SAndrzej Pietrasiewicz }
547ea4f088SAndrzej Pietrasiewicz 
usb_ext_prop_name_ptr(u8 * buf)557ea4f088SAndrzej Pietrasiewicz static inline u8 *usb_ext_prop_name_ptr(u8 *buf)
567ea4f088SAndrzej Pietrasiewicz {
577ea4f088SAndrzej Pietrasiewicz 	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_B_PROPERTY_NAME);
587ea4f088SAndrzej Pietrasiewicz }
597ea4f088SAndrzej Pietrasiewicz 
usb_ext_prop_data_len_ptr(u8 * buf,size_t off)607ea4f088SAndrzej Pietrasiewicz static inline u8 *usb_ext_prop_data_len_ptr(u8 *buf, size_t off)
617ea4f088SAndrzej Pietrasiewicz {
627ea4f088SAndrzej Pietrasiewicz 	return __usb_ext_prop_ptr(buf,
637ea4f088SAndrzej Pietrasiewicz 				  USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + off);
647ea4f088SAndrzej Pietrasiewicz }
657ea4f088SAndrzej Pietrasiewicz 
usb_ext_prop_data_ptr(u8 * buf,size_t off)667ea4f088SAndrzej Pietrasiewicz static inline u8 *usb_ext_prop_data_ptr(u8 *buf, size_t off)
677ea4f088SAndrzej Pietrasiewicz {
687ea4f088SAndrzej Pietrasiewicz 	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_B_PROPERTY_DATA + off);
697ea4f088SAndrzej Pietrasiewicz }
707ea4f088SAndrzej Pietrasiewicz 
usb_ext_prop_put_size(u8 * buf,int dw_size)7137a3a533SAndrzej Pietrasiewicz static inline void usb_ext_prop_put_size(u8 *buf, int dw_size)
7237a3a533SAndrzej Pietrasiewicz {
737ea4f088SAndrzej Pietrasiewicz 	put_unaligned_le32(dw_size, usb_ext_prop_size_ptr(buf));
7437a3a533SAndrzej Pietrasiewicz }
7537a3a533SAndrzej Pietrasiewicz 
usb_ext_prop_put_type(u8 * buf,int type)7637a3a533SAndrzej Pietrasiewicz static inline void usb_ext_prop_put_type(u8 *buf, int type)
7737a3a533SAndrzej Pietrasiewicz {
787ea4f088SAndrzej Pietrasiewicz 	put_unaligned_le32(type, usb_ext_prop_type_ptr(buf));
7937a3a533SAndrzej Pietrasiewicz }
8037a3a533SAndrzej Pietrasiewicz 
usb_ext_prop_put_name(u8 * buf,const char * name,int pnl)8137a3a533SAndrzej Pietrasiewicz static inline int usb_ext_prop_put_name(u8 *buf, const char *name, int pnl)
8237a3a533SAndrzej Pietrasiewicz {
8337a3a533SAndrzej Pietrasiewicz 	int result;
8437a3a533SAndrzej Pietrasiewicz 
857ea4f088SAndrzej Pietrasiewicz 	put_unaligned_le16(pnl, usb_ext_prop_name_len_ptr(buf));
8637a3a533SAndrzej Pietrasiewicz 	result = utf8s_to_utf16s(name, strlen(name), UTF16_LITTLE_ENDIAN,
877ea4f088SAndrzej Pietrasiewicz 		(wchar_t *) usb_ext_prop_name_ptr(buf), pnl - 2);
8837a3a533SAndrzej Pietrasiewicz 	if (result < 0)
8937a3a533SAndrzej Pietrasiewicz 		return result;
9037a3a533SAndrzej Pietrasiewicz 
917ea4f088SAndrzej Pietrasiewicz 	put_unaligned_le16(0, &buf[USB_EXT_PROP_B_PROPERTY_NAME + pnl - 2]);
9237a3a533SAndrzej Pietrasiewicz 
9337a3a533SAndrzej Pietrasiewicz 	return pnl;
9437a3a533SAndrzej Pietrasiewicz }
9537a3a533SAndrzej Pietrasiewicz 
usb_ext_prop_put_binary(u8 * buf,int pnl,const u8 * data,int data_len)9637a3a533SAndrzej Pietrasiewicz static inline void usb_ext_prop_put_binary(u8 *buf, int pnl, const u8 *data,
9737a3a533SAndrzej Pietrasiewicz 					   int data_len)
9837a3a533SAndrzej Pietrasiewicz {
997ea4f088SAndrzej Pietrasiewicz 	put_unaligned_le32(data_len, usb_ext_prop_data_len_ptr(buf, pnl));
1007ea4f088SAndrzej Pietrasiewicz 	memcpy(usb_ext_prop_data_ptr(buf, pnl), data, data_len);
10137a3a533SAndrzej Pietrasiewicz }
10237a3a533SAndrzej Pietrasiewicz 
usb_ext_prop_put_unicode(u8 * buf,int pnl,const char * string,int data_len)10337a3a533SAndrzej Pietrasiewicz static inline int usb_ext_prop_put_unicode(u8 *buf, int pnl, const char *string,
10437a3a533SAndrzej Pietrasiewicz 					   int data_len)
10537a3a533SAndrzej Pietrasiewicz {
10637a3a533SAndrzej Pietrasiewicz 	int result;
1077ea4f088SAndrzej Pietrasiewicz 	put_unaligned_le32(data_len, usb_ext_prop_data_len_ptr(buf, pnl));
10837a3a533SAndrzej Pietrasiewicz 	result = utf8s_to_utf16s(string, data_len >> 1, UTF16_LITTLE_ENDIAN,
1097ea4f088SAndrzej Pietrasiewicz 			(wchar_t *) usb_ext_prop_data_ptr(buf, pnl),
11037a3a533SAndrzej Pietrasiewicz 			data_len - 2);
11137a3a533SAndrzej Pietrasiewicz 	if (result < 0)
11237a3a533SAndrzej Pietrasiewicz 		return result;
11337a3a533SAndrzej Pietrasiewicz 
11437a3a533SAndrzej Pietrasiewicz 	put_unaligned_le16(0,
1157ea4f088SAndrzej Pietrasiewicz 		&buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl + data_len - 2]);
11637a3a533SAndrzej Pietrasiewicz 
11737a3a533SAndrzej Pietrasiewicz 	return data_len;
11837a3a533SAndrzej Pietrasiewicz }
11937a3a533SAndrzej Pietrasiewicz 
12037a3a533SAndrzej Pietrasiewicz #endif /* __U_OS_DESC_H__ */
121