usage.c revision 1.4 1 1.4 salo /* $NetBSD: usage.c,v 1.4 2003/07/26 19:25:09 salo 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.4 salo __RCSID("$NetBSD: usage.c,v 1.4 2003/07/26 19:25:09 salo 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.1 augustss void
58 1.1 augustss dump_hid_table(void)
59 1.1 augustss {
60 1.1 augustss int i, j;
61 1.1 augustss
62 1.1 augustss for (i = 0; i < npages; i++) {
63 1.1 augustss printf("%d\t%s\n", pages[i].usage, pages[i].name);
64 1.1 augustss for (j = 0; j < pages[i].pagesize; j++) {
65 1.1 augustss printf("\t%d\t%s\n", pages[i].page_contents[j].usage,
66 1.1 augustss pages[i].page_contents[j].name);
67 1.1 augustss }
68 1.1 augustss }
69 1.1 augustss }
70 1.1 augustss #endif
71 1.1 augustss
72 1.1 augustss void
73 1.1 augustss hid_init(const char *hidname)
74 1.1 augustss {
75 1.1 augustss FILE *f;
76 1.1 augustss char line[100], name[100], *p, *n;
77 1.1 augustss int no;
78 1.1 augustss int lineno;
79 1.1 augustss struct usage_page *curpage = 0;
80 1.1 augustss
81 1.1 augustss if (hidname == 0)
82 1.1 augustss hidname = _PATH_HIDTABLE;
83 1.1 augustss
84 1.1 augustss f = fopen(hidname, "r");
85 1.1 augustss if (f == NULL)
86 1.1 augustss err(1, "%s", hidname);
87 1.1 augustss for (lineno = 1; ; lineno++) {
88 1.1 augustss if (fgets(line, sizeof line, f) == NULL)
89 1.1 augustss break;
90 1.1 augustss if (line[0] == '#')
91 1.1 augustss continue;
92 1.1 augustss for (p = line; *p && isspace(*p); p++)
93 1.1 augustss ;
94 1.1 augustss if (!*p)
95 1.1 augustss continue;
96 1.1 augustss if (sscanf(line, " * %[^\n]", name) == 1)
97 1.1 augustss no = -1;
98 1.1 augustss else if (sscanf(line, " 0x%x %[^\n]", &no, name) != 2 &&
99 1.1 augustss sscanf(line, " %d %[^\n]", &no, name) != 2)
100 1.2 grant errx(1, "file %s, line %d, syntax error",
101 1.1 augustss hidname, lineno);
102 1.1 augustss for (p = name; *p; p++)
103 1.1 augustss if (isspace(*p) || *p == '.')
104 1.1 augustss *p = '_';
105 1.1 augustss n = strdup(name);
106 1.1 augustss if (!n)
107 1.1 augustss err(1, "strdup");
108 1.1 augustss if (isspace(line[0])) {
109 1.1 augustss if (!curpage)
110 1.2 grant errx(1, "file %s, line %d, syntax error",
111 1.1 augustss hidname, lineno);
112 1.1 augustss if (curpage->pagesize >= curpage->pagesizemax) {
113 1.1 augustss curpage->pagesizemax += 10;
114 1.1 augustss curpage->page_contents =
115 1.1 augustss realloc(curpage->page_contents,
116 1.1 augustss curpage->pagesizemax *
117 1.1 augustss sizeof (struct usage_in_page));
118 1.1 augustss if (!curpage->page_contents)
119 1.1 augustss err(1, "realloc");
120 1.1 augustss }
121 1.1 augustss curpage->page_contents[curpage->pagesize].name = n;
122 1.1 augustss curpage->page_contents[curpage->pagesize].usage = no;
123 1.1 augustss curpage->pagesize++;
124 1.1 augustss } else {
125 1.1 augustss if (npages >= npagesmax) {
126 1.1 augustss if (pages == 0) {
127 1.1 augustss npagesmax = 5;
128 1.1 augustss pages = malloc(npagesmax *
129 1.1 augustss sizeof (struct usage_page));
130 1.1 augustss } else {
131 1.1 augustss npagesmax += 5;
132 1.1 augustss pages = realloc(pages,
133 1.1 augustss npagesmax *
134 1.1 augustss sizeof (struct usage_page));
135 1.1 augustss }
136 1.1 augustss if (!pages)
137 1.1 augustss err(1, "alloc");
138 1.1 augustss }
139 1.1 augustss curpage = &pages[npages++];
140 1.1 augustss curpage->name = n;
141 1.1 augustss curpage->usage = no;
142 1.1 augustss curpage->pagesize = 0;
143 1.1 augustss curpage->pagesizemax = 10;
144 1.1 augustss curpage->page_contents =
145 1.1 augustss malloc(curpage->pagesizemax *
146 1.1 augustss sizeof (struct usage_in_page));
147 1.1 augustss if (!curpage->page_contents)
148 1.1 augustss err(1, "malloc");
149 1.1 augustss }
150 1.1 augustss }
151 1.1 augustss fclose(f);
152 1.1 augustss #ifdef DEBUG
153 1.1 augustss dump_hid_table();
154 1.1 augustss #endif
155 1.1 augustss }
156 1.1 augustss
157 1.1 augustss const char *
158 1.1 augustss hid_usage_page(int i)
159 1.1 augustss {
160 1.1 augustss static char b[10];
161 1.1 augustss int k;
162 1.1 augustss
163 1.1 augustss if (!pages)
164 1.2 grant errx(1, "no hid table");
165 1.1 augustss
166 1.1 augustss for (k = 0; k < npages; k++)
167 1.1 augustss if (pages[k].usage == i)
168 1.1 augustss return pages[k].name;
169 1.1 augustss sprintf(b, "0x%04x", i);
170 1.1 augustss return b;
171 1.1 augustss }
172 1.1 augustss
173 1.1 augustss const char *
174 1.1 augustss hid_usage_in_page(unsigned int u)
175 1.1 augustss {
176 1.1 augustss int page = HID_PAGE(u);
177 1.1 augustss int i = HID_USAGE(u);
178 1.1 augustss static char b[100];
179 1.1 augustss int j, k, us;
180 1.1 augustss
181 1.1 augustss for (k = 0; k < npages; k++)
182 1.1 augustss if (pages[k].usage == page)
183 1.1 augustss break;
184 1.1 augustss if (k >= npages)
185 1.1 augustss goto bad;
186 1.1 augustss for (j = 0; j < pages[k].pagesize; j++) {
187 1.1 augustss us = pages[k].page_contents[j].usage;
188 1.1 augustss if (us == -1) {
189 1.1 augustss sprintf(b,
190 1.1 augustss fmtcheck(pages[k].page_contents[j].name, "%d"),
191 1.1 augustss i);
192 1.1 augustss return b;
193 1.1 augustss }
194 1.1 augustss if (us == i)
195 1.1 augustss return pages[k].page_contents[j].name;
196 1.1 augustss }
197 1.1 augustss bad:
198 1.1 augustss sprintf(b, "0x%04x", i);
199 1.1 augustss return b;
200 1.1 augustss }
201 1.1 augustss
202 1.1 augustss int
203 1.1 augustss hid_parse_usage_page(const char *name)
204 1.1 augustss {
205 1.1 augustss int k;
206 1.1 augustss
207 1.1 augustss if (!pages)
208 1.2 grant errx(1, "no hid table");
209 1.1 augustss
210 1.1 augustss for (k = 0; k < npages; k++)
211 1.1 augustss if (strcmp(pages[k].name, name) == 0)
212 1.1 augustss return pages[k].usage;
213 1.1 augustss return -1;
214 1.1 augustss }
215 1.1 augustss
216 1.1 augustss /* XXX handle hex */
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.1 augustss
224 1.1 augustss _DIAGASSERT(name != NULL);
225 1.1 augustss
226 1.1 augustss sep = strchr(name, ':');
227 1.1 augustss if (sep == NULL)
228 1.1 augustss return -1;
229 1.1 augustss l = sep - name;
230 1.1 augustss for (k = 0; k < npages; k++)
231 1.1 augustss if (strncmp(pages[k].name, name, l) == 0)
232 1.1 augustss goto found;
233 1.1 augustss return -1;
234 1.1 augustss found:
235 1.1 augustss sep++;
236 1.1 augustss for (j = 0; j < pages[k].pagesize; j++)
237 1.1 augustss if (strcmp(pages[k].page_contents[j].name, sep) == 0)
238 1.1 augustss return (pages[k].usage << 16) | pages[k].page_contents[j].usage;
239 1.1 augustss return (-1);
240 1.1 augustss }
241