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