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