1/*	$NetBSD: t_usbhid.c,v 1.12 2016/08/17 12:10:42 jakllsch Exp $	*/
2
3/*
4 * Copyright (c) 2016 Jonathan A. Kollasch
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__RCSID("$NetBSD: t_usbhid.c,v 1.12 2016/08/17 12:10:42 jakllsch Exp $");
31
32#include <atf-c.h>
33
34#include <inttypes.h>
35#include <usbhid.h>
36#include <string.h>
37
38#include <stdio.h>
39#include <stdlib.h>
40
41#include <limits.h>
42
43ATF_TC(check_hid_logical_range);
44ATF_TC(check_hid_physical_range);
45ATF_TC(check_hid_usage);
46ATF_TC(check_hid_get_data);
47ATF_TC(check_hid_set_data);
48ATF_TC(check_parse_just_pop);
49
50#define MYd_ATF_CHECK_EQ(d, v) \
51	ATF_CHECK_EQ_MSG(d, v, "== %d", (d))
52
53#define MYu_ATF_CHECK_EQ(d, v) \
54	ATF_CHECK_EQ_MSG(d, v, "== %u", (d))
55
56#define MYx_ATF_CHECK_EQ(d, v) \
57	ATF_CHECK_EQ_MSG(d, v, "== 0x%x", (d))
58
59#include "hid_test_data.c"
60
61ATF_TC_HEAD(check_hid_usage, tc)
62{
63
64	atf_tc_set_md_var(tc, "descr", "Test libusbhid usage.c");
65}
66
67ATF_TC_BODY(check_hid_usage, tc)
68{
69	char usages_path[PATH_MAX];
70
71	(void)strlcpy(usages_path, atf_tc_get_config_var(tc, "srcdir"),
72	    sizeof(usages_path));
73	(void)strlcat(usages_path, "/test_usb_hid_usages",
74	    sizeof(usages_path));
75
76	hid_init(usages_path);
77
78	ATF_CHECK_STREQ("t_usbhid_page", hid_usage_page(0xff1b));
79	ATF_CHECK_EQ((uint32_t)hid_parse_usage_page("t_usbhid_page"), 0xff1b);
80
81	ATF_CHECK_STREQ("t_usbhid_usage", hid_usage_in_page(0xff1bff2a));
82	ATF_CHECK_EQ((uint32_t)hid_parse_usage_in_page(
83	    "t_usbhid_page:t_usbhid_usage"), 0xff1bff2a);
84
85	ATF_CHECK_STREQ("Quick_zephyrs_blow_vexing_daft_Jim_",
86	    hid_usage_page(0xff2a));
87	ATF_CHECK_EQ((uint32_t)hid_parse_usage_page(
88	    "Quick_zephyrs_blow_vexing_daft_Jim_"), 0xff2a);
89
90	ATF_CHECK_STREQ("Usage_ID_Zero_%", hid_usage_in_page(0xff2a0000));
91	ATF_CHECK_EQ((uint32_t)hid_parse_usage_in_page(
92	    "Quick_zephyrs_blow_vexing_daft_Jim_:Usage_ID_Zero_%"),
93	    0xff2a0000);
94
95	//ATF_CHECK_STREQ("Usage_ID_0_%", hid_usage_in_page(0xff2a0000));
96	ATF_CHECK_EQ((uint32_t)hid_parse_usage_in_page(
97	    "Quick_zephyrs_blow_vexing_daft_Jim_:Usage_ID_0_%"), 0xff2a0000);
98
99	ATF_CHECK_STREQ("Usage_ID_65535_%", hid_usage_in_page(0xff2affff));
100	ATF_CHECK_EQ((uint32_t)hid_parse_usage_in_page(
101	    "Quick_zephyrs_blow_vexing_daft_Jim_:Usage_ID_65535_%"),
102	    0xff2affff);
103
104	MYx_ATF_CHECK_EQ((uint32_t)hid_parse_usage_in_page("0xff2a:0xff1b"),
105	    0xff2aff1b);
106}
107
108ATF_TC_HEAD(check_hid_logical_range, tc)
109{
110
111	atf_tc_set_md_var(tc, "descr", "Test hid_get_item "
112	    "Logical Minimum/Maximum results");
113}
114
115ATF_TC_BODY(check_hid_logical_range, tc)
116{
117	report_desc_t hrd;
118	hid_item_t hi;
119	uint32_t minimum, maximum;
120
121	atf_tc_expect_fail("only the 32-bit opcode works, "
122	    "8 and 16-bit is broken");
123
124	ATF_REQUIRE((hrd = hid_use_report_desc(range_test_report_descriptor,
125	    __arraycount(range_test_report_descriptor))) != NULL);
126	ATF_REQUIRE(hid_locate(hrd, 0xff000001U, hid_input, &hi,
127	    NO_REPORT_ID) > 0);
128	MYd_ATF_CHECK_EQ(hi.logical_minimum, -128);
129	MYd_ATF_CHECK_EQ(hi.logical_maximum, 127);
130	ATF_REQUIRE(hid_locate(hrd, 0xff000002U, hid_input, &hi,
131	    NO_REPORT_ID) > 0);
132	MYd_ATF_CHECK_EQ(hi.logical_minimum, -32768);
133	MYd_ATF_CHECK_EQ(hi.logical_maximum, 32767);
134	ATF_REQUIRE(hid_locate(hrd, 0xff000003U, hid_input, &hi,
135	    NO_REPORT_ID) > 0);
136	MYd_ATF_CHECK_EQ(hi.logical_minimum, -2147483648);
137	MYd_ATF_CHECK_EQ(hi.logical_maximum, 2147483647);
138
139	hid_dispose_report_desc(hrd);
140	hrd = NULL;
141
142	ATF_REQUIRE((hrd = hid_use_report_desc(
143	    unsigned_range_test_report_descriptor,
144	    __arraycount(unsigned_range_test_report_descriptor))) != NULL);
145	ATF_REQUIRE(hid_locate(hrd, 0xff000011U, hid_input, &hi,
146	    NO_REPORT_ID) > 0);
147	ATF_CHECK(hi.logical_minimum > hi.logical_maximum);
148	minimum = (uint32_t)hi.logical_minimum & ((1ULL<<hi.report_size)-1);
149	MYu_ATF_CHECK_EQ(minimum, 0);
150	maximum = (uint32_t)hi.logical_maximum & ((1ULL<<hi.report_size)-1);
151	MYu_ATF_CHECK_EQ(maximum, 255);
152	ATF_REQUIRE(hid_locate(hrd, 0xff000012U, hid_input, &hi,
153	    NO_REPORT_ID) > 0);
154	ATF_CHECK(hi.logical_minimum > hi.logical_maximum);
155	minimum = hi.logical_minimum & ((1ULL<<hi.report_size)-1);
156	MYu_ATF_CHECK_EQ(minimum, 0);
157	maximum = hi.logical_maximum & ((1ULL<<hi.report_size)-1);
158	MYu_ATF_CHECK_EQ(maximum, 65535);
159	ATF_REQUIRE(hid_locate(hrd, 0xff000013U, hid_input, &hi,
160	    NO_REPORT_ID) > 0);
161	ATF_CHECK(hi.logical_minimum > hi.logical_maximum);
162	minimum = hi.logical_minimum & ((1ULL<<hi.report_size)-1);
163	MYu_ATF_CHECK_EQ(minimum, 0);
164	maximum = hi.logical_maximum & ((1ULL<<hi.report_size)-1);
165	MYu_ATF_CHECK_EQ(maximum, 4294967295);
166
167	hid_dispose_report_desc(hrd);
168	hrd = NULL;
169}
170
171ATF_TC_HEAD(check_hid_physical_range, tc)
172{
173
174	atf_tc_set_md_var(tc, "descr", "Test hid_get_item "
175	    "Physical Minimum/Maximum results");
176}
177
178ATF_TC_BODY(check_hid_physical_range, tc)
179{
180	report_desc_t hrd;
181	hid_item_t hi;
182	uint32_t minimum, maximum;
183
184	atf_tc_expect_fail("only the 32-bit opcode works, "
185	    "8 and 16-bit is broken");
186
187	ATF_REQUIRE((hrd = hid_use_report_desc(range_test_report_descriptor,
188	    __arraycount(range_test_report_descriptor))) != NULL);
189	ATF_REQUIRE(hid_locate(hrd, 0xff000001U, hid_input, &hi,
190	    NO_REPORT_ID) > 0);
191	MYd_ATF_CHECK_EQ(hi.physical_minimum, -128);
192	MYd_ATF_CHECK_EQ(hi.physical_maximum, 127);
193	ATF_REQUIRE(hid_locate(hrd, 0xff000002U, hid_input, &hi,
194	    NO_REPORT_ID) > 0);
195	MYd_ATF_CHECK_EQ(hi.physical_minimum, -32768);
196	MYd_ATF_CHECK_EQ(hi.physical_maximum, 32767);
197	ATF_REQUIRE(hid_locate(hrd, 0xff000003U, hid_input, &hi,
198	    NO_REPORT_ID) > 0);
199	MYd_ATF_CHECK_EQ(hi.physical_minimum, -2147483648);
200	MYd_ATF_CHECK_EQ(hi.physical_maximum, 2147483647);
201
202	hid_dispose_report_desc(hrd);
203	hrd = NULL;
204
205	ATF_REQUIRE((hrd = hid_use_report_desc(
206	    unsigned_range_test_report_descriptor,
207	    __arraycount(unsigned_range_test_report_descriptor))) != NULL);
208	ATF_REQUIRE(hid_locate(hrd, 0xff000011U, hid_input, &hi,
209	    NO_REPORT_ID) > 0);
210	ATF_CHECK(hi.physical_minimum > hi.physical_maximum);
211	minimum = (uint32_t)hi.physical_minimum & ((1ULL<<hi.report_size)-1);
212	MYu_ATF_CHECK_EQ(minimum, 0);
213	maximum = (uint32_t)hi.physical_maximum & ((1ULL<<hi.report_size)-1);
214	MYu_ATF_CHECK_EQ(maximum, 255);
215	ATF_REQUIRE(hid_locate(hrd, 0xff000012U, hid_input, &hi,
216	    NO_REPORT_ID) > 0);
217	ATF_CHECK(hi.physical_minimum > hi.physical_maximum);
218	minimum = hi.physical_minimum & ((1ULL<<hi.report_size)-1);
219	MYu_ATF_CHECK_EQ(minimum, 0);
220	maximum = hi.physical_maximum & ((1ULL<<hi.report_size)-1);
221	MYu_ATF_CHECK_EQ(maximum, 65535);
222	ATF_REQUIRE(hid_locate(hrd, 0xff000013U, hid_input, &hi,
223	    NO_REPORT_ID) > 0);
224	ATF_CHECK(hi.physical_minimum > hi.physical_maximum);
225	minimum = hi.physical_minimum & ((1ULL<<hi.report_size)-1);
226	MYu_ATF_CHECK_EQ(minimum, 0);
227	maximum = hi.physical_maximum & ((1ULL<<hi.report_size)-1);
228	MYu_ATF_CHECK_EQ(maximum, 4294967295);
229
230	hid_dispose_report_desc(hrd);
231	hrd = NULL;
232}
233
234ATF_TC_HEAD(check_hid_get_data, tc)
235{
236
237	atf_tc_set_md_var(tc, "descr", "Test hid_get_data results");
238}
239
240ATF_TC_BODY(check_hid_get_data, tc)
241{
242	report_desc_t hrd;
243	hid_item_t hi;
244	int32_t data;
245	uint32_t udat;
246
247	atf_tc_expect_fail("only the 32-bit opcode works, "
248	    "8 and 16-bit is broken");
249
250	ATF_REQUIRE((hrd = hid_use_report_desc(
251	    range_test_report_descriptor,
252	    __arraycount(range_test_report_descriptor))) != NULL);
253
254	ATF_REQUIRE(hid_locate(hrd, 0xff000001U, hid_input, &hi,
255	    NO_REPORT_ID) > 0);
256	data = hid_get_data(range_test_minimum_report, &hi);
257	MYd_ATF_CHECK_EQ(data, -128);
258	data = hid_get_data(range_test_negative_one_report, &hi);
259	MYd_ATF_CHECK_EQ(data, -1);
260	data = hid_get_data(range_test_positive_one_report, &hi);
261	MYd_ATF_CHECK_EQ(data, 1);
262	data = hid_get_data(range_test_maximum_report, &hi);
263	MYd_ATF_CHECK_EQ(data, 127);
264
265	ATF_REQUIRE(hid_locate(hrd, 0xff000002U, hid_input, &hi,
266	    NO_REPORT_ID) > 0);
267	data = hid_get_data(range_test_minimum_report, &hi);
268	MYd_ATF_CHECK_EQ(data, -32768);
269	data = hid_get_data(range_test_negative_one_report, &hi);
270	MYd_ATF_CHECK_EQ(data, -1);
271	data = hid_get_data(range_test_positive_one_report, &hi);
272	MYd_ATF_CHECK_EQ(data, 1);
273	data = hid_get_data(range_test_maximum_report, &hi);
274	MYd_ATF_CHECK_EQ(data, 32767);
275
276	ATF_REQUIRE(hid_locate(hrd, 0xff000003U, hid_input, &hi,
277	    NO_REPORT_ID) > 0);
278	data = hid_get_data(range_test_minimum_report, &hi);
279	MYd_ATF_CHECK_EQ(data, -2147483648);
280	data = hid_get_data(range_test_negative_one_report, &hi);
281	MYd_ATF_CHECK_EQ(data, -1);
282	data = hid_get_data(range_test_positive_one_report, &hi);
283	MYd_ATF_CHECK_EQ(data, 1);
284	data = hid_get_data(range_test_maximum_report, &hi);
285	MYd_ATF_CHECK_EQ(data, 2147483647);
286
287	hid_dispose_report_desc(hrd);
288	hrd = NULL;
289
290	ATF_REQUIRE((hrd = hid_use_report_desc(
291	    unsigned_range_test_report_descriptor,
292	    __arraycount(unsigned_range_test_report_descriptor))) != NULL);
293	ATF_REQUIRE(hid_locate(hrd, 0xff000011U, hid_input, &hi,
294	    NO_REPORT_ID) > 0);
295	udat = hid_get_data(unsigned_range_test_minimum_report, &hi);
296	MYu_ATF_CHECK_EQ(udat, 0);
297	udat = hid_get_data(unsigned_range_test_positive_one_report, &hi);
298	MYu_ATF_CHECK_EQ(udat, 1);
299	udat = hid_get_data(unsigned_range_test_negative_one_report, &hi);
300	MYu_ATF_CHECK_EQ(udat, 254);
301	udat = hid_get_data(unsigned_range_test_maximum_report, &hi);
302	MYu_ATF_CHECK_EQ(udat, 255);
303
304	ATF_REQUIRE(hid_locate(hrd, 0xff000012U, hid_input, &hi,
305	    NO_REPORT_ID) > 0);
306	udat = hid_get_data(unsigned_range_test_minimum_report, &hi);
307	MYu_ATF_CHECK_EQ(udat, 0);
308	udat = hid_get_data(unsigned_range_test_positive_one_report, &hi);
309	MYu_ATF_CHECK_EQ(udat, 1);
310	udat = hid_get_data(unsigned_range_test_negative_one_report, &hi);
311	MYu_ATF_CHECK_EQ(udat, 65534);
312	udat = hid_get_data(unsigned_range_test_maximum_report, &hi);
313	MYu_ATF_CHECK_EQ(udat, 65535);
314
315	ATF_REQUIRE(hid_locate(hrd, 0xff000013U, hid_input, &hi,
316	    NO_REPORT_ID) > 0);
317	udat = hid_get_data(unsigned_range_test_minimum_report, &hi);
318	MYu_ATF_CHECK_EQ(udat, 0);
319	udat = hid_get_data(unsigned_range_test_positive_one_report, &hi);
320	MYu_ATF_CHECK_EQ(udat, 1);
321	udat = hid_get_data(unsigned_range_test_negative_one_report, &hi);
322	MYu_ATF_CHECK_EQ(udat, 4294967294);
323	udat = hid_get_data(unsigned_range_test_maximum_report, &hi);
324	MYu_ATF_CHECK_EQ(udat, 4294967295);
325
326	hid_dispose_report_desc(hrd);
327	hrd = NULL;
328}
329
330ATF_TC_HEAD(check_hid_set_data, tc)
331{
332
333	atf_tc_set_md_var(tc, "descr", "Test hid_set_data results");
334}
335
336ATF_TC_BODY(check_hid_set_data, tc)
337{
338	report_desc_t hrd;
339	hid_item_t hi;
340	uint8_t test_data_minimum[7];
341	uint8_t test_data_negative_one[7];
342	uint8_t test_data_positive_one[7];
343	uint8_t test_data_maximum[7];
344
345	ATF_REQUIRE((hrd = hid_use_report_desc(
346	    range_test_report_descriptor,
347	    __arraycount(range_test_report_descriptor))) != NULL);
348	ATF_REQUIRE(hid_locate(hrd, 0xff000001U, hid_input, &hi,
349	    NO_REPORT_ID) > 0);
350	hid_set_data(test_data_minimum, &hi, -128);
351	hid_set_data(test_data_negative_one, &hi, -1);
352	hid_set_data(test_data_positive_one, &hi, 1);
353	hid_set_data(test_data_maximum, &hi, 127);
354	ATF_REQUIRE(hid_locate(hrd, 0xff000002U, hid_input, &hi,
355	    NO_REPORT_ID) > 0);
356	hid_set_data(test_data_minimum, &hi, -32768);
357	hid_set_data(test_data_negative_one, &hi, -1);
358	hid_set_data(test_data_positive_one, &hi, 1);
359	hid_set_data(test_data_maximum, &hi, 32767);
360	ATF_REQUIRE(hid_locate(hrd, 0xff000003U, hid_input, &hi,
361	    NO_REPORT_ID) > 0);
362	hid_set_data(test_data_minimum, &hi, -2147483648);
363	hid_set_data(test_data_negative_one, &hi, -1);
364	hid_set_data(test_data_positive_one, &hi, 1);
365	hid_set_data(test_data_maximum, &hi, 2147483647);
366	ATF_CHECK(memcmp(test_data_minimum, range_test_minimum_report,
367	    sizeof test_data_minimum) == 0);
368	ATF_CHECK(memcmp(test_data_negative_one,
369	    range_test_negative_one_report,
370	    sizeof test_data_negative_one) == 0);
371	ATF_CHECK(memcmp(test_data_positive_one,
372	    range_test_positive_one_report,
373	    sizeof test_data_positive_one) == 0);
374	ATF_CHECK(memcmp(test_data_maximum, range_test_maximum_report,
375	    sizeof test_data_maximum) == 0);
376
377	hid_dispose_report_desc(hrd);
378	hrd = NULL;
379
380	ATF_REQUIRE((hrd = hid_use_report_desc(
381	    unsigned_range_test_report_descriptor,
382	    __arraycount(range_test_report_descriptor))) != NULL);
383	ATF_REQUIRE(hid_locate(hrd, 0xff000011U, hid_input, &hi,
384	    NO_REPORT_ID) > 0);
385	hid_set_data(test_data_minimum, &hi, 0);
386	hid_set_data(test_data_positive_one, &hi, 1);
387	hid_set_data(test_data_negative_one, &hi, 0xfffffffe);
388	hid_set_data(test_data_maximum, &hi, 0xffffffff);
389	ATF_REQUIRE(hid_locate(hrd, 0xff000012U, hid_input, &hi,
390	    NO_REPORT_ID) > 0);
391	hid_set_data(test_data_minimum, &hi, 0);
392	hid_set_data(test_data_positive_one, &hi, 1);
393	hid_set_data(test_data_negative_one, &hi, 0xfffe);
394	hid_set_data(test_data_maximum, &hi, 0xffff);
395	ATF_REQUIRE(hid_locate(hrd, 0xff000013U, hid_input, &hi,
396	    NO_REPORT_ID) > 0);
397	hid_set_data(test_data_minimum, &hi, 0);
398	hid_set_data(test_data_positive_one, &hi, 1);
399	hid_set_data(test_data_negative_one, &hi, 0xfffffffe);
400	hid_set_data(test_data_maximum, &hi, 0xffffffff);
401	ATF_CHECK(memcmp(test_data_minimum,
402	    unsigned_range_test_minimum_report,
403	    sizeof test_data_minimum) == 0);
404	ATF_CHECK(memcmp(test_data_negative_one,
405	    unsigned_range_test_negative_one_report,
406	    sizeof test_data_negative_one) == 0);
407	ATF_CHECK(memcmp(test_data_positive_one,
408	    unsigned_range_test_positive_one_report,
409	    sizeof test_data_positive_one) == 0);
410	ATF_CHECK(memcmp(test_data_maximum,
411	    unsigned_range_test_maximum_report,
412	    sizeof test_data_maximum) == 0);
413
414	hid_dispose_report_desc(hrd);
415	hrd = NULL;
416}
417
418ATF_TC_HEAD(check_parse_just_pop, tc)
419{
420
421	atf_tc_set_md_var(tc, "descr", "check Pop on empty stack bug");
422}
423
424ATF_TC_BODY(check_parse_just_pop, tc)
425{
426	report_desc_t hrd;
427	hid_data_t hd;
428	hid_item_t hi;
429
430	ATF_REQUIRE((hrd = hid_use_report_desc(
431	    just_pop_report_descriptor,
432	    sizeof just_pop_report_descriptor)) != NULL);
433	hd = hid_start_parse(hrd, 0, NO_REPORT_ID);
434	while (hid_get_item(hd, &hi) > 0) {
435	}
436	hid_end_parse(hd);
437	hid_dispose_report_desc(hrd);
438	hrd = NULL;
439}
440
441ATF_TP_ADD_TCS(tp)
442{
443
444	ATF_TP_ADD_TC(tp, check_hid_logical_range);
445	ATF_TP_ADD_TC(tp, check_hid_physical_range);
446	ATF_TP_ADD_TC(tp, check_hid_usage);
447	ATF_TP_ADD_TC(tp, check_hid_get_data);
448	ATF_TP_ADD_TC(tp, check_hid_set_data);
449	ATF_TP_ADD_TC(tp, check_parse_just_pop);
450
451	return atf_no_error();
452}
453