1 /*
2  * Copyright (c) 2018 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <zephyr/tc_util.h>
9 
10 #include <zephyr/sys/byteorder.h>
11 #include <zephyr/usb/usb_device.h>
12 #include <os_desc.h>
13 
14 #define MSOS_STRING_LENGTH	18
15 static struct string_desc {
16 	uint8_t bLength;
17 	uint8_t bDescriptorType;
18 	uint8_t bString[MSOS_STRING_LENGTH - 4];
19 	uint8_t bMS_VendorCode;
20 	uint8_t bPad;
21 } __packed msosv1_string_descriptor = {
22 	.bLength = MSOS_STRING_LENGTH,
23 	.bDescriptorType = USB_DESC_STRING,
24 	/* Signature MSFT100 */
25 	.bString = {
26 		'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00,
27 		'1', 0x00, '0', 0x00, '0', 0x00
28 	},
29 	.bMS_VendorCode = 0x03,	/* Vendor Code, used for a control request */
30 	.bPad = 0x00,		/* Padding byte for VendorCode look as UTF16 */
31 };
32 
33 static struct compat_id_desc {
34 	/* MS OS 1.0 Header Section */
35 	uint32_t dwLength;
36 	uint16_t bcdVersion;
37 	uint16_t wIndex;
38 	uint8_t bCount;
39 	uint8_t Reserved[7];
40 	/* MS OS 1.0 Function Section */
41 	struct compat_id_func {
42 		uint8_t bFirstInterfaceNumber;
43 		uint8_t Reserved1;
44 		uint8_t compatibleID[8];
45 		uint8_t subCompatibleID[8];
46 		uint8_t Reserved2[6];
47 	} __packed func[1];
48 } __packed msosv1_compatid_descriptor = {
49 	.dwLength = sys_cpu_to_le32(40),
50 	.bcdVersion = sys_cpu_to_le16(0x0100),
51 	.wIndex = sys_cpu_to_le16(USB_OSDESC_EXTENDED_COMPAT_ID),
52 	.bCount = 0x01, /* One function section */
53 	.Reserved = {
54 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
55 	},
56 
57 	.func = {
58 		{
59 			.bFirstInterfaceNumber = 0x00,
60 			.Reserved1 = 0x01,
61 			.compatibleID = {
62 				'R', 'N', 'D', 'I', 'S', 0x00, 0x00, 0x00
63 			},
64 			.subCompatibleID = {
65 				'5', '1', '6', '2', '0', '0', '1', 0x00
66 			},
67 			.Reserved2 = {
68 				0x00, 0x00, 0x00, 0x00, 0x00, 0x00
69 			}
70 		},
71 	}
72 };
73 
74 static struct usb_os_descriptor os_desc = {
75 	.string = (uint8_t *)&msosv1_string_descriptor,
76 	.string_len = sizeof(msosv1_string_descriptor),
77 	.vendor_code = 0x03,
78 	.compat_id = (uint8_t *)&msosv1_compatid_descriptor,
79 	.compat_id_len = sizeof(msosv1_compatid_descriptor),
80 };
81 
test_register_osdesc(void)82 void test_register_osdesc(void)
83 {
84 	TC_PRINT("%s\n", __func__);
85 
86 	usb_register_os_desc(&os_desc);
87 }
88 
test_handle_os_desc(void)89 static void test_handle_os_desc(void)
90 {
91 	struct usb_setup_packet setup;
92 	int32_t len = 0;
93 	uint8_t *data = NULL;
94 	int ret;
95 
96 	setup.wValue = (USB_DESC_STRING & 0xFF) << 8;
97 	setup.wValue |= USB_OSDESC_STRING_DESC_INDEX;
98 
99 	ret = usb_handle_os_desc(&setup, &len, &data);
100 
101 	TC_PRINT("%s: ret %d len %u data %p\n", __func__, ret, len, data);
102 
103 	zassert_true(!ret, "Return code failed");
104 	zassert_equal(len, sizeof(msosv1_string_descriptor), "Wrong length");
105 	zassert_true(!memcmp(data, &msosv1_string_descriptor, len),
106 		     "Wrong data");
107 }
108 
test_handle_os_desc_feature(void)109 static void test_handle_os_desc_feature(void)
110 {
111 	struct usb_setup_packet setup;
112 	int32_t len = 0;
113 	uint8_t *data = NULL;
114 	int ret;
115 
116 	setup.bRequest = os_desc.vendor_code;
117 	setup.wIndex = USB_OSDESC_EXTENDED_COMPAT_ID;
118 
119 	ret = usb_handle_os_desc_feature(&setup, &len, &data);
120 
121 	TC_PRINT("%s: ret %d len %u data %p\n", __func__, ret, len, data);
122 
123 	zassert_true(!ret, "Return code failed");
124 	zassert_equal(len, sizeof(msosv1_compatid_descriptor), "Wrong length");
125 	zassert_true(!memcmp(data, &msosv1_compatid_descriptor, len),
126 		     "Wrong data");
127 }
128 
ZTEST(os_desc,test_osdesc_string)129 ZTEST(os_desc, test_osdesc_string)
130 {
131 	test_register_osdesc();
132 	test_handle_os_desc();
133 }
134 
ZTEST(os_desc,test_osdesc_feature)135 ZTEST(os_desc, test_osdesc_feature)
136 {
137 	test_register_osdesc();
138 	test_handle_os_desc_feature();
139 }
140 
141 /* test case main entry */
142 ZTEST_SUITE(os_desc, NULL, NULL, NULL, NULL, NULL);
143