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_with_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_with_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 hid_test_uclogic_template(struct kunit *test) |
191 | { |
192 | __u8 *res; |
193 | const struct uclogic_template_case *params = test->param_value; |
194 | |
195 | res = uclogic_rdesc_template_apply(template_ptr: params->template, |
196 | template_size: params->template_size, |
197 | param_list: params->param_list, |
198 | param_num: params->param_num); |
199 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, res); |
200 | KUNIT_EXPECT_MEMEQ(test, res, params->expected, params->template_size); |
201 | kfree(objp: res); |
202 | } |
203 | |
204 | static struct kunit_case hid_uclogic_rdesc_test_cases[] = { |
205 | KUNIT_CASE_PARAM(hid_test_uclogic_template, uclogic_template_gen_params), |
206 | {} |
207 | }; |
208 | |
209 | static struct kunit_suite hid_uclogic_rdesc_test_suite = { |
210 | .name = "hid_uclogic_rdesc_test" , |
211 | .test_cases = hid_uclogic_rdesc_test_cases, |
212 | }; |
213 | |
214 | kunit_test_suite(hid_uclogic_rdesc_test_suite); |
215 | |
216 | MODULE_DESCRIPTION("KUnit tests for the UC-Logic driver" ); |
217 | MODULE_LICENSE("GPL" ); |
218 | MODULE_AUTHOR("José Expósito <jose.exposito89@gmail.com>" ); |
219 | |