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