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 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 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