1 // SPDX-License-Identifier: GPL-2.0+
2 
3 /*
4  *  HID driver for UC-Logic devices not fully compliant with HID standard
5  *
6  *  Copyright (c) 2022 José Expósito <jose.exposito89@gmail.com>
7  */
8 
9 #include <kunit/test.h>
10 #include "./hid-uclogic-rdesc.h"
11 
12 struct uclogic_template_case {
13 	const char *name;
14 	const __u8 *template;
15 	size_t template_size;
16 	const s32 *param_list;
17 	size_t param_num;
18 	const __u8 *expected;
19 };
20 
21 static const s32 params_pen_all[UCLOGIC_RDESC_PH_ID_NUM] = {
22 	[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = 0xAA,
23 	[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0xBB,
24 	[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = 0xCC,
25 	[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0xDD,
26 	[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 0xEE,
27 };
28 
29 static const s32 params_pen_some[] = {
30 	[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = 0xAA,
31 	[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0xBB,
32 };
33 
34 static const s32 params_frame_all[UCLOGIC_RDESC_PH_ID_NUM] = {
35 	[UCLOGIC_RDESC_FRAME_PH_ID_UM] = 0xFF,
36 };
37 
38 static const __u8 template_empty[] = { };
39 static const __u8 template_small[] = { 0x00 };
40 static const __u8 template_no_ph[] = { 0xAA, 0xFE, 0xAA, 0xED, 0x1D };
41 
42 static const __u8 template_pen_ph_end[] = {
43 	0xAA, 0xBB, UCLOGIC_RDESC_PEN_PH_HEAD
44 };
45 
46 static const __u8 template_btn_ph_end[] = {
47 	0xAA, 0xBB, UCLOGIC_RDESC_FRAME_PH_BTN_HEAD
48 };
49 
50 static const __u8 template_pen_all_params[] = {
51 	UCLOGIC_RDESC_PEN_PH(X_LM),
52 	0x47, UCLOGIC_RDESC_PEN_PH(X_PM),
53 	0x27, UCLOGIC_RDESC_PEN_PH(Y_LM),
54 	UCLOGIC_RDESC_PEN_PH(Y_PM),
55 	0x00, UCLOGIC_RDESC_PEN_PH(PRESSURE_LM),
56 };
57 
58 static const __u8 expected_pen_all_params[] = {
59 	0xAA, 0x00, 0x00, 0x00,
60 	0x47, 0xBB, 0x00, 0x00, 0x00,
61 	0x27, 0xCC, 0x00, 0x00, 0x00,
62 	0xDD, 0x00, 0x00, 0x00,
63 	0x00, 0xEE, 0x00, 0x00, 0x00,
64 };
65 
66 static const __u8 template_frame_all_params[] = {
67 	0x01, 0x02,
68 	UCLOGIC_RDESC_FRAME_PH_BTN,
69 	0x99,
70 };
71 
72 static const __u8 expected_frame_all_params[] = {
73 	0x01, 0x02,
74 	0x2A, 0xFF, 0x00,
75 	0x99,
76 };
77 
78 static const __u8 template_pen_some_params[] = {
79 	0x01, 0x02,
80 	UCLOGIC_RDESC_PEN_PH(X_LM),
81 	0x03, UCLOGIC_RDESC_PEN_PH(X_PM),
82 	0x04, 0x05,
83 };
84 
85 static const __u8 expected_pen_some_params[] = {
86 	0x01, 0x02,
87 	0xAA, 0x00, 0x00, 0x00,
88 	0x03, 0xBB, 0x00, 0x00, 0x00,
89 	0x04, 0x05,
90 };
91 
92 static const __u8 template_params_none[] = {
93 	0x27, UCLOGIC_RDESC_PEN_PH(Y_LM),
94 	UCLOGIC_RDESC_PEN_PH(Y_PM),
95 	0x00, UCLOGIC_RDESC_PEN_PH(PRESSURE_LM),
96 };
97 
98 static struct uclogic_template_case uclogic_template_cases[] = {
99 	{
100 		.name = "Empty template",
101 		.template = template_empty,
102 		.template_size = sizeof(template_empty),
103 		.param_list = params_pen_all,
104 		.param_num = ARRAY_SIZE(params_pen_all),
105 		.expected = template_empty,
106 	},
107 	{
108 		.name = "Template smaller than the placeholder",
109 		.template = template_small,
110 		.template_size = sizeof(template_small),
111 		.param_list = params_pen_all,
112 		.param_num = ARRAY_SIZE(params_pen_all),
113 		.expected = template_small,
114 	},
115 	{
116 		.name = "No placeholder",
117 		.template = template_no_ph,
118 		.template_size = sizeof(template_no_ph),
119 		.param_list = params_pen_all,
120 		.param_num = ARRAY_SIZE(params_pen_all),
121 		.expected = template_no_ph,
122 	},
123 	{
124 		.name = "Pen placeholder at the end, without ID",
125 		.template = template_pen_ph_end,
126 		.template_size = sizeof(template_pen_ph_end),
127 		.param_list = params_pen_all,
128 		.param_num = ARRAY_SIZE(params_pen_all),
129 		.expected = template_pen_ph_end,
130 	},
131 	{
132 		.name = "Frame button placeholder at the end, without ID",
133 		.template = template_btn_ph_end,
134 		.template_size = sizeof(template_btn_ph_end),
135 		.param_list = params_frame_all,
136 		.param_num = ARRAY_SIZE(params_frame_all),
137 		.expected = template_btn_ph_end,
138 	},
139 	{
140 		.name = "All params present in the pen template",
141 		.template = template_pen_all_params,
142 		.template_size = sizeof(template_pen_all_params),
143 		.param_list = params_pen_all,
144 		.param_num = ARRAY_SIZE(params_pen_all),
145 		.expected = expected_pen_all_params,
146 	},
147 	{
148 		.name = "All params present in the frame template",
149 		.template = template_frame_all_params,
150 		.template_size = sizeof(template_frame_all_params),
151 		.param_list = params_frame_all,
152 		.param_num = ARRAY_SIZE(params_frame_all),
153 		.expected = expected_frame_all_params,
154 	},
155 	{
156 		.name = "Some params present in the pen template (complete param list)",
157 		.template = template_pen_some_params,
158 		.template_size = sizeof(template_pen_some_params),
159 		.param_list = params_pen_all,
160 		.param_num = ARRAY_SIZE(params_pen_all),
161 		.expected = expected_pen_some_params,
162 	},
163 	{
164 		.name = "Some params present in the pen template (incomplete param list)",
165 		.template = template_pen_some_params,
166 		.template_size = sizeof(template_pen_some_params),
167 		.param_list = params_pen_some,
168 		.param_num = ARRAY_SIZE(params_pen_some),
169 		.expected = expected_pen_some_params,
170 	},
171 	{
172 		.name = "No params present in the template",
173 		.template = template_params_none,
174 		.template_size = sizeof(template_params_none),
175 		.param_list = params_pen_some,
176 		.param_num = ARRAY_SIZE(params_pen_some),
177 		.expected = template_params_none,
178 	},
179 };
180 
181 static void uclogic_template_case_desc(struct uclogic_template_case *t,
182 				       char *desc)
183 {
184 	strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
185 }
186 
187 KUNIT_ARRAY_PARAM(uclogic_template, uclogic_template_cases,
188 		  uclogic_template_case_desc);
189 
190 static void uclogic_template_test(struct kunit *test)
191 {
192 	__u8 *res;
193 	const struct uclogic_template_case *params = test->param_value;
194 
195 	res = uclogic_rdesc_template_apply(params->template,
196 					   params->template_size,
197 					   params->param_list,
198 					   params->param_num);
199 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, res);
200 	KUNIT_EXPECT_EQ(test, 0,
201 			memcmp(res, params->expected, params->template_size));
202 	kfree(res);
203 }
204 
205 static struct kunit_case hid_uclogic_rdesc_test_cases[] = {
206 	KUNIT_CASE_PARAM(uclogic_template_test, uclogic_template_gen_params),
207 	{}
208 };
209 
210 static struct kunit_suite hid_uclogic_rdesc_test_suite = {
211 	.name = "hid-uclogic-rdesc-test",
212 	.test_cases = hid_uclogic_rdesc_test_cases,
213 };
214 
215 kunit_test_suite(hid_uclogic_rdesc_test_suite);
216 
217 MODULE_DESCRIPTION("KUnit tests for the UC-Logic driver");
218 MODULE_LICENSE("GPL");
219 MODULE_AUTHOR("José Expósito <jose.exposito89@gmail.com>");
220