1/*	$NetBSD: t_hid.c,v 1.8 2016/05/05 17:40:26 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_hid.c,v 1.8 2016/05/05 17:40:26 jakllsch Exp $");
31
32#include <machine/types.h>
33#include <stdlib.h>
34#include <string.h>
35#include <stdio.h>
36#include <atf-c.h>
37
38#include <rump/rump.h>
39
40#define hid_start_parse rumpns_hid_start_parse
41#define hid_end_parse rumpns_hid_end_parse
42#define hid_get_item rumpns_hid_get_item
43#define hid_locate rumpns_hid_locate
44#define hid_report_size rumpns_hid_report_size
45#define hid_get_data rumpns_hid_get_data
46#define hid_get_udata rumpns_hid_get_udata
47#define uhidevdebug rumpns_uhidevdebug
48#include <usb.h>
49#include <usbhid.h>
50#include <hid.h>
51
52#include "../../lib/libusbhid/hid_test_data.c"
53
54#define MYd_ATF_CHECK_EQ(d, v) \
55	ATF_CHECK_EQ_MSG(d, v, "== %d", (d))
56
57#define MYld_ATF_CHECK_EQ(d, v) \
58	ATF_CHECK_EQ_MSG(d, v, "== %ld", (d))
59
60#define MYu_ATF_CHECK_EQ(d, v) \
61	ATF_CHECK_EQ_MSG(d, v, "== %u", (d))
62
63#define MYlu_ATF_CHECK_EQ(d, v) \
64	ATF_CHECK_EQ_MSG(d, v, "== %lu", (d))
65
66#define MYx_ATF_CHECK_EQ(d, v) \
67	ATF_CHECK_EQ_MSG(d, v, "== 0x%x", (d))
68
69#define MYlx_ATF_CHECK_EQ(d, v) \
70	ATF_CHECK_EQ_MSG(d, v, "== 0x%lx", (d))
71
72int uhidevdebug;
73
74ATF_TC(khid);
75
76ATF_TC_HEAD(khid, tc)
77{
78
79        atf_tc_set_md_var(tc, "descr", "check kernel hid.c");
80}
81
82static int
83locate_item(const void *desc, int size, u_int32_t u, u_int8_t id,
84    enum hid_kind k, struct hid_item *hip)
85{
86	struct hid_data *d;
87	struct hid_item h;
88
89	h.report_ID = 0;
90	for (d = hid_start_parse(desc, size, k); hid_get_item(d, &h); ) {
91		if (h.kind == k && !(h.flags & HIO_CONST) &&
92		    (/*XXX*/uint32_t)h.usage == u && h.report_ID == id) {
93			if (hip != NULL)
94				*hip = h;
95			hid_end_parse(d);
96			return (1);
97		}
98	}
99	hid_end_parse(d);
100	return (0);
101}
102
103ATF_TC_BODY(khid, tc)
104{
105	int ret;
106	struct hid_item hi;
107
108	uhidevdebug = 0;
109
110	rump_init();
111
112	rump_schedule();
113
114	ret = locate_item(range_test_report_descriptor,
115	    sizeof(range_test_report_descriptor), 0xff000003, 0, hid_input,
116	    &hi);
117	ATF_REQUIRE(ret > 0);
118	MYu_ATF_CHECK_EQ(hi.loc.size, 32);
119	MYu_ATF_CHECK_EQ(hi.loc.count, 1);
120	MYu_ATF_CHECK_EQ(hi.loc.pos, 0);
121	MYx_ATF_CHECK_EQ(hi.flags, 0);
122	MYd_ATF_CHECK_EQ(hi.logical_minimum, -2147483648);
123	MYd_ATF_CHECK_EQ(hi.logical_maximum, 2147483647);
124	MYd_ATF_CHECK_EQ(hi.physical_minimum, -2147483648);
125	MYd_ATF_CHECK_EQ(hi.physical_maximum, 2147483647);
126	MYld_ATF_CHECK_EQ(hid_get_data(range_test_minimum_report,
127	    &hi.loc), -2147483648);
128	MYld_ATF_CHECK_EQ(hid_get_data(range_test_negative_one_report,
129	    &hi.loc), -1);
130	MYld_ATF_CHECK_EQ(hid_get_data(range_test_positive_one_report,
131	    &hi.loc), 1);
132	MYld_ATF_CHECK_EQ(hid_get_data(range_test_maximum_report,
133	    &hi.loc), 2147483647);
134
135	ret = locate_item(range_test_report_descriptor,
136	    sizeof(range_test_report_descriptor), 0xff000002, 0, hid_input,
137	    &hi);
138	ATF_REQUIRE(ret > 0);
139	MYu_ATF_CHECK_EQ(hi.loc.size, 16);
140	MYu_ATF_CHECK_EQ(hi.loc.count, 1);
141	MYu_ATF_CHECK_EQ(hi.loc.pos, 32);
142	MYx_ATF_CHECK_EQ(hi.flags, 0);
143	MYd_ATF_CHECK_EQ(hi.logical_minimum, -32768);
144	MYd_ATF_CHECK_EQ(hi.logical_maximum, 32767);
145	MYd_ATF_CHECK_EQ(hi.physical_minimum, -32768);
146	MYd_ATF_CHECK_EQ(hi.physical_maximum, 32767);
147	MYld_ATF_CHECK_EQ(hid_get_data(range_test_minimum_report,
148	    &hi.loc), -32768);
149	MYld_ATF_CHECK_EQ(hid_get_data(range_test_negative_one_report,
150	    &hi.loc), -1);
151	MYld_ATF_CHECK_EQ(hid_get_data(range_test_positive_one_report,
152	    &hi.loc), 1);
153	MYld_ATF_CHECK_EQ(hid_get_data(range_test_maximum_report,
154	    &hi.loc), 32767);
155
156	ret = locate_item(range_test_report_descriptor,
157	    sizeof(range_test_report_descriptor), 0xff000001, 0, hid_input,
158	    &hi);
159	ATF_REQUIRE(ret > 0);
160	MYu_ATF_CHECK_EQ(hi.loc.size, 8);
161	MYu_ATF_CHECK_EQ(hi.loc.count, 1);
162	MYu_ATF_CHECK_EQ(hi.loc.pos, 48);
163	MYx_ATF_CHECK_EQ(hi.flags, 0);
164	MYd_ATF_CHECK_EQ(hi.logical_minimum, -128);
165	MYd_ATF_CHECK_EQ(hi.logical_maximum, 127);
166	MYd_ATF_CHECK_EQ(hi.physical_minimum, -128);
167	MYd_ATF_CHECK_EQ(hi.physical_maximum, 127);
168	MYld_ATF_CHECK_EQ(hid_get_data(range_test_minimum_report,
169	    &hi.loc), -128);
170	MYld_ATF_CHECK_EQ(hid_get_data(range_test_negative_one_report,
171	    &hi.loc), -1);
172	MYld_ATF_CHECK_EQ(hid_get_data(range_test_positive_one_report,
173	    &hi.loc), 1);
174	MYld_ATF_CHECK_EQ(hid_get_data(range_test_maximum_report,
175	    &hi.loc), 127);
176
177
178	ret = locate_item(unsigned_range_test_report_descriptor,
179	    sizeof(unsigned_range_test_report_descriptor), 0xff000013, 0,
180	    hid_input, &hi);
181	ATF_REQUIRE(ret > 0);
182	MYu_ATF_CHECK_EQ(hi.loc.size, 32);
183	MYu_ATF_CHECK_EQ(hi.loc.count, 1);
184	MYu_ATF_CHECK_EQ(hi.loc.pos, 0);
185	MYx_ATF_CHECK_EQ(hi.flags, 0);
186	MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_minimum_report,
187	    &hi.loc), 0x0);
188	MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_positive_one_report,
189	    &hi.loc), 0x1);
190	MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_negative_one_report,
191	    &hi.loc), 0xfffffffe);
192	MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_maximum_report,
193	    &hi.loc), 0xffffffff);
194
195	ret = locate_item(unsigned_range_test_report_descriptor,
196	    sizeof(unsigned_range_test_report_descriptor), 0xff000012, 0,
197	    hid_input, &hi);
198	ATF_REQUIRE(ret > 0);
199	MYu_ATF_CHECK_EQ(hi.loc.size, 16);
200	MYu_ATF_CHECK_EQ(hi.loc.count, 1);
201	MYu_ATF_CHECK_EQ(hi.loc.pos, 32);
202	MYx_ATF_CHECK_EQ(hi.flags, 0);
203	MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_minimum_report,
204	    &hi.loc), 0x0);
205	MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_positive_one_report,
206	    &hi.loc), 0x1);
207	MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_negative_one_report,
208	    &hi.loc), 0xfffe);
209	MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_maximum_report,
210	    &hi.loc), 0xffff);
211
212	ret = locate_item(unsigned_range_test_report_descriptor,
213	    sizeof(unsigned_range_test_report_descriptor), 0xff000011, 0,
214	    hid_input, &hi);
215	ATF_REQUIRE(ret > 0);
216	MYu_ATF_CHECK_EQ(hi.loc.size, 8);
217	MYu_ATF_CHECK_EQ(hi.loc.count, 1);
218	MYu_ATF_CHECK_EQ(hi.loc.pos, 48);
219	MYx_ATF_CHECK_EQ(hi.flags, 0);
220	MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_minimum_report,
221	    &hi.loc), 0x0);
222	MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_positive_one_report,
223	    &hi.loc), 0x1);
224	MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_negative_one_report,
225	    &hi.loc), 0xfe);
226	MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_maximum_report,
227	    &hi.loc), 0xff);
228
229	rump_unschedule();
230}
231
232ATF_TC(khid_parse_just_pop);
233
234ATF_TC_HEAD(khid_parse_just_pop, tc)
235{
236
237        atf_tc_set_md_var(tc, "descr", "check kernel hid.c for "
238	    "Pop on empty stack bug");
239}
240
241ATF_TC_BODY(khid_parse_just_pop, tc)
242{
243	struct hid_data *hdp;
244	struct hid_item hi;
245
246	rump_init();
247
248	rump_schedule();
249
250	hdp = hid_start_parse(just_pop_report_descriptor,
251	    sizeof just_pop_report_descriptor, hid_none);
252	while (hid_get_item(hdp, &hi) > 0) {
253	}
254	hid_end_parse(hdp);
255
256	rump_unschedule();
257}
258
259ATF_TP_ADD_TCS(tp)
260{
261
262        ATF_TP_ADD_TC(tp, khid);
263        ATF_TP_ADD_TC(tp, khid_parse_just_pop);
264
265	return atf_no_error();
266}
267
268