GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libusbhid/usage.c Lines: 0 127 0.0 %
Date: 2017-11-07 Branches: 0 96 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: usage.c,v 1.16 2014/10/08 04:49:36 deraadt Exp $	*/
2
/*	$NetBSD: usage.c,v 1.1 2001/12/28 17:45:27 augustss Exp $	*/
3
4
/*
5
 * Copyright (c) 1999 Lennart Augustsson <augustss@netbsd.org>
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29
30
#include <ctype.h>
31
#include <err.h>
32
#include <stdio.h>
33
#include <stdlib.h>
34
#include <string.h>
35
#include <errno.h>
36
37
#include "usbhid.h"
38
39
#define _PATH_HIDTABLE "/usr/share/misc/usb_hid_usages"
40
41
struct usage_in_page {
42
	const char *name;
43
	int usage;
44
};
45
46
static struct usage_page {
47
	const char *name;
48
	int usage;
49
	struct usage_in_page *page_contents;
50
	int pagesize, pagesizemax;
51
} *pages;
52
static int npages, npagesmax;
53
54
#ifdef DEBUG
55
void
56
dump_hid_table(void)
57
{
58
	int i, j;
59
60
	for (i = 0; i < npages; i++) {
61
		printf("%d\t%s\n", pages[i].usage, pages[i].name);
62
		for (j = 0; j < pages[i].pagesize; j++) {
63
			printf("\t%d\t%s\n", pages[i].page_contents[j].usage,
64
			    pages[i].page_contents[j].name);
65
		}
66
	}
67
}
68
#endif
69
70
void
71
hid_init(const char *hidname)
72
{
73
	if (hid_start(hidname) == -1)
74
		errx(1, "hid_init: failed");
75
}
76
77
int
78
hid_start(const char *hidname)
79
{
80
	char line[100], name[100], *p, *n;
81
	struct usage_page *curpage = NULL;
82
	int lineno, no;
83
	FILE *f;
84
85
	if (hidname == NULL)
86
		hidname = _PATH_HIDTABLE;
87
88
	f = fopen(hidname, "r");
89
	if (f == NULL)
90
		return -1;
91
	for (lineno = 1; ; lineno++) {
92
		if (fgets(line, sizeof line, f) == NULL)
93
			break;
94
		if (line[0] == '#')
95
			continue;
96
		for (p = line; isspace((unsigned char)*p); p++)
97
			;
98
		if (!*p)
99
			continue;
100
		if (sscanf(line, " * %99[^\n]", name) == 1)
101
			no = -1;
102
		else if (sscanf(line, " 0x%x %99[^\n]", &no, name) != 2 &&
103
		    sscanf(line, " %d %99[^\n]", &no, name) != 2) {
104
			warnx("file %s, line %d, syntax error",
105
			    hidname, lineno);
106
			errno = EINVAL;
107
			goto fail;
108
		}
109
		for (p = name; *p; p++)
110
			if (isspace((unsigned char)*p) || *p == '.')
111
				*p = '_';
112
		n = strdup(name);
113
		if (!n)
114
			goto fail;
115
116
		if (isspace((unsigned char)line[0])) {
117
			if (!curpage) {
118
				warnx("file %s, line %d, syntax error",
119
				    hidname, lineno);
120
				free(n);
121
				errno = EINVAL;
122
				goto fail;
123
			}
124
			if (curpage->pagesize >= curpage->pagesizemax) {
125
				void *new;
126
				int len;
127
128
				len = curpage->pagesizemax + 10;
129
				new = reallocarray(curpage->page_contents,
130
				    len, sizeof(struct usage_in_page));
131
				if (!new) {
132
					free(curpage->page_contents);
133
					curpage->page_contents = NULL;
134
					free(n);
135
					goto fail;
136
				}
137
				curpage->pagesizemax = len;
138
				curpage->page_contents = new;
139
			}
140
			curpage->page_contents[curpage->pagesize].name = n;
141
			curpage->page_contents[curpage->pagesize].usage = no;
142
			curpage->pagesize++;
143
		} else {
144
			if (npages >= npagesmax) {
145
				int len;
146
				void *new;
147
148
				if (pages == NULL) {
149
					len = 5;
150
					pages = calloc(len,
151
					    sizeof (struct usage_page));
152
				} else {
153
					len = npagesmax * 5;
154
					new = reallocarray(pages,
155
					    len, sizeof(struct usage_page));
156
					if (!new) {
157
						free(n);
158
						goto fail;
159
					}
160
					pages = new;
161
					bzero(pages + npagesmax,
162
					    (len - npagesmax) *
163
					    sizeof(struct usage_page));
164
				}
165
				if (!pages) {
166
					free(n);
167
					goto fail;
168
				}
169
				npagesmax = len;
170
			}
171
			curpage = &pages[npages++];
172
			curpage->name = n;
173
			curpage->usage = no;
174
			curpage->pagesize = 0;
175
			curpage->pagesizemax = 10;
176
			curpage->page_contents = calloc(curpage->pagesizemax,
177
			    sizeof (struct usage_in_page));
178
			if (!curpage->page_contents)
179
				goto fail;
180
		}
181
	}
182
	fclose(f);
183
#ifdef DEBUG
184
	dump_hid_table();
185
#endif
186
	return 0;
187
188
fail:
189
	if (f)
190
		fclose(f);
191
	if (pages) {
192
		for (no = 0; no < npages; no++) {
193
			if (pages[no].name)
194
				free((char *)pages[no].name);
195
			if (pages[no].page_contents)
196
				free((char *)pages[no].page_contents);
197
		}
198
		free(pages);
199
		pages = NULL;
200
	}
201
	npages = 0;
202
	npagesmax = 0;
203
	return -1;
204
}
205
206
const char *
207
hid_usage_page(int i)
208
{
209
	static char b[10];
210
	int k;
211
212
	if (!pages)
213
		return NULL;
214
215
	for (k = 0; k < npages; k++)
216
		if (pages[k].usage == i)
217
			return pages[k].name;
218
	snprintf(b, sizeof b, "0x%04x", i);
219
	return b;
220
}
221
222
const char *
223
hid_usage_in_page(unsigned int u)
224
{
225
	int i = HID_USAGE(u), j, k, us;
226
	int page = HID_PAGE(u);
227
	static char b[100];
228
229
	for (k = 0; k < npages; k++)
230
		if (pages[k].usage == page)
231
			break;
232
	if (k >= npages)
233
		goto bad;
234
	for (j = 0; j < pages[k].pagesize; j++) {
235
		us = pages[k].page_contents[j].usage;
236
		if (us == -1) {
237
			snprintf(b, sizeof b,
238
			    pages[k].page_contents[j].name, i);
239
			return b;
240
		}
241
		if (us == i)
242
			return pages[k].page_contents[j].name;
243
	}
244
 bad:
245
	snprintf(b, sizeof b, "0x%04x", i);
246
	return b;
247
}
248
249
int
250
hid_parse_usage_page(const char *name)
251
{
252
	int k;
253
254
	if (!pages)
255
		return 0;
256
257
	for (k = 0; k < npages; k++)
258
		if (strcmp(pages[k].name, name) == 0)
259
			return pages[k].usage;
260
	return -1;
261
}
262
263
/* XXX handle hex */
264
int
265
hid_parse_usage_in_page(const char *name)
266
{
267
	const char *sep;
268
	unsigned int l;
269
	int k, j;
270
271
	sep = strchr(name, ':');
272
	if (sep == NULL)
273
		return -1;
274
	l = sep - name;
275
	for (k = 0; k < npages; k++)
276
		if (strncmp(pages[k].name, name, l) == 0)
277
			goto found;
278
	return -1;
279
 found:
280
	sep++;
281
	for (j = 0; j < pages[k].pagesize; j++)
282
		if (strcmp(pages[k].page_contents[j].name, sep) == 0)
283
			return (pages[k].usage << 16) |
284
			    pages[k].page_contents[j].usage;
285
	return -1;
286
}