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
12struct 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
21static 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
29static 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
34static const s32 params_frame_all[UCLOGIC_RDESC_PH_ID_NUM] = {
35	[UCLOGIC_RDESC_FRAME_PH_ID_UM] = 0xFF,
36};
37
38static const __u8 template_empty[] = { };
39static const __u8 template_small[] = { 0x00 };
40static const __u8 template_no_ph[] = { 0xAA, 0xFE, 0xAA, 0xED, 0x1D };
41
42static const __u8 template_pen_ph_end[] = {
43	0xAA, 0xBB, UCLOGIC_RDESC_PEN_PH_HEAD
44};
45
46static const __u8 template_btn_ph_end[] = {
47	0xAA, 0xBB, UCLOGIC_RDESC_FRAME_PH_BTN_HEAD
48};
49
50static 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
58static 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
66static const __u8 template_frame_all_params[] = {
67	0x01, 0x02,
68	UCLOGIC_RDESC_FRAME_PH_BTN,
69	0x99,
70};
71
72static const __u8 expected_frame_all_params[] = {
73	0x01, 0x02,
74	0x2A, 0xFF, 0x00,
75	0x99,
76};
77
78static 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
85static 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
92static 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
98static 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
181static 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
187KUNIT_ARRAY_PARAM(uclogic_template, uclogic_template_cases,
188		  uclogic_template_case_desc);
189
190static 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(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_MEMEQ(test, res, params->expected, params->template_size);
201	kfree(res);
202}
203
204static struct kunit_case hid_uclogic_rdesc_test_cases[] = {
205	KUNIT_CASE_PARAM(hid_test_uclogic_template, uclogic_template_gen_params),
206	{}
207};
208
209static struct kunit_suite hid_uclogic_rdesc_test_suite = {
210	.name = "hid_uclogic_rdesc_test",
211	.test_cases = hid_uclogic_rdesc_test_cases,
212};
213
214kunit_test_suite(hid_uclogic_rdesc_test_suite);
215
216MODULE_DESCRIPTION("KUnit tests for the UC-Logic driver");
217MODULE_LICENSE("GPL");
218MODULE_AUTHOR("Jos�� Exp��sito <jose.exposito89@gmail.com>");
219