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