1b425e319SNick Hibma /* $NetBSD: usage.c,v 1.8 2000/10/10 19:23:58 is Exp $ */
29e2046dfSNick Hibma
35e53a4f9SPedro F. Giffuni /*-
4*b61a5730SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
55e53a4f9SPedro F. Giffuni *
69e2046dfSNick Hibma * Copyright (c) 1999 Lennart Augustsson <augustss@netbsd.org>
79e2046dfSNick Hibma * All rights reserved.
89e2046dfSNick Hibma *
99e2046dfSNick Hibma * Redistribution and use in source and binary forms, with or without
109e2046dfSNick Hibma * modification, are permitted provided that the following conditions
119e2046dfSNick Hibma * are met:
129e2046dfSNick Hibma * 1. Redistributions of source code must retain the above copyright
139e2046dfSNick Hibma * notice, this list of conditions and the following disclaimer.
149e2046dfSNick Hibma * 2. Redistributions in binary form must reproduce the above copyright
159e2046dfSNick Hibma * notice, this list of conditions and the following disclaimer in the
169e2046dfSNick Hibma * documentation and/or other materials provided with the distribution.
179e2046dfSNick Hibma *
189e2046dfSNick Hibma * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
199e2046dfSNick Hibma * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
209e2046dfSNick Hibma * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
219e2046dfSNick Hibma * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
229e2046dfSNick Hibma * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
239e2046dfSNick Hibma * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
249e2046dfSNick Hibma * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
259e2046dfSNick Hibma * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
269e2046dfSNick Hibma * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
279e2046dfSNick Hibma * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
289e2046dfSNick Hibma * SUCH DAMAGE.
299e2046dfSNick Hibma */
309e2046dfSNick Hibma
31cde58781SKai Wang #include <sys/param.h>
32cf0e07e5SMatthew N. Dodd #include <assert.h>
339e2046dfSNick Hibma #include <ctype.h>
349e2046dfSNick Hibma #include <err.h>
359e2046dfSNick Hibma #include <stdio.h>
369e2046dfSNick Hibma #include <stdlib.h>
379e2046dfSNick Hibma #include <string.h>
389e2046dfSNick Hibma
39cf0e07e5SMatthew N. Dodd #include "usbhid.h"
409e2046dfSNick Hibma
419e2046dfSNick Hibma #define _PATH_HIDTABLE "/usr/share/misc/usb_hid_usages"
429e2046dfSNick Hibma
439e2046dfSNick Hibma struct usage_in_page {
449e2046dfSNick Hibma const char *name;
459e2046dfSNick Hibma int usage;
469e2046dfSNick Hibma };
479e2046dfSNick Hibma
489e2046dfSNick Hibma static struct usage_page {
499e2046dfSNick Hibma const char *name;
509e2046dfSNick Hibma int usage;
519e2046dfSNick Hibma struct usage_in_page *page_contents;
529e2046dfSNick Hibma int pagesize, pagesizemax;
539e2046dfSNick Hibma } *pages;
549e2046dfSNick Hibma static int npages, npagesmax;
559e2046dfSNick Hibma
569e2046dfSNick Hibma #ifdef DEBUG
579e2046dfSNick Hibma void
dump_hid_table(void)589e2046dfSNick Hibma dump_hid_table(void)
599e2046dfSNick Hibma {
609e2046dfSNick Hibma int i, j;
619e2046dfSNick Hibma
629e2046dfSNick Hibma for (i = 0; i < npages; i++) {
639e2046dfSNick Hibma printf("%d\t%s\n", pages[i].usage, pages[i].name);
649e2046dfSNick Hibma for (j = 0; j < pages[i].pagesize; j++) {
659e2046dfSNick Hibma printf("\t%d\t%s\n", pages[i].page_contents[j].usage,
669e2046dfSNick Hibma pages[i].page_contents[j].name);
679e2046dfSNick Hibma }
689e2046dfSNick Hibma }
699e2046dfSNick Hibma }
709e2046dfSNick Hibma #endif
719e2046dfSNick Hibma
729e2046dfSNick Hibma void
hid_init(const char * hidname)739e2046dfSNick Hibma hid_init(const char *hidname)
749e2046dfSNick Hibma {
759e2046dfSNick Hibma FILE *f;
769e2046dfSNick Hibma char line[100], name[100], *p, *n;
779e2046dfSNick Hibma int no;
789e2046dfSNick Hibma int lineno;
792bf49386SPedro F. Giffuni struct usage_page *curpage = NULL;
809e2046dfSNick Hibma
812bf49386SPedro F. Giffuni if (hidname == NULL)
829e2046dfSNick Hibma hidname = _PATH_HIDTABLE;
839e2046dfSNick Hibma
849e2046dfSNick Hibma f = fopen(hidname, "r");
859e2046dfSNick Hibma if (f == NULL)
869e2046dfSNick Hibma err(1, "%s", hidname);
879e2046dfSNick Hibma for (lineno = 1; ; lineno++) {
889e2046dfSNick Hibma if (fgets(line, sizeof line, f) == NULL)
899e2046dfSNick Hibma break;
909e2046dfSNick Hibma if (line[0] == '#')
919e2046dfSNick Hibma continue;
929e2046dfSNick Hibma for (p = line; *p && isspace(*p); p++)
939e2046dfSNick Hibma ;
949e2046dfSNick Hibma if (!*p)
959e2046dfSNick Hibma continue;
969e2046dfSNick Hibma if (sscanf(line, " * %[^\n]", name) == 1)
979e2046dfSNick Hibma no = -1;
989e2046dfSNick Hibma else if (sscanf(line, " 0x%x %[^\n]", &no, name) != 2 &&
999e2046dfSNick Hibma sscanf(line, " %d %[^\n]", &no, name) != 2)
100234e6b87SMatthew N. Dodd errx(1, "file %s, line %d, syntax error",
1019e2046dfSNick Hibma hidname, lineno);
1029e2046dfSNick Hibma for (p = name; *p; p++)
1039e2046dfSNick Hibma if (isspace(*p) || *p == '.')
1049e2046dfSNick Hibma *p = '_';
1059e2046dfSNick Hibma n = strdup(name);
1069e2046dfSNick Hibma if (!n)
1079e2046dfSNick Hibma err(1, "strdup");
1089e2046dfSNick Hibma if (isspace(line[0])) {
1099e2046dfSNick Hibma if (!curpage)
110234e6b87SMatthew N. Dodd errx(1, "file %s, line %d, syntax error",
1119e2046dfSNick Hibma hidname, lineno);
1129e2046dfSNick Hibma if (curpage->pagesize >= curpage->pagesizemax) {
1139e2046dfSNick Hibma curpage->pagesizemax += 10;
1149e2046dfSNick Hibma curpage->page_contents =
1159e2046dfSNick Hibma realloc(curpage->page_contents,
1169e2046dfSNick Hibma curpage->pagesizemax *
1179e2046dfSNick Hibma sizeof (struct usage_in_page));
1189e2046dfSNick Hibma if (!curpage->page_contents)
1199e2046dfSNick Hibma err(1, "realloc");
1209e2046dfSNick Hibma }
1219e2046dfSNick Hibma curpage->page_contents[curpage->pagesize].name = n;
1229e2046dfSNick Hibma curpage->page_contents[curpage->pagesize].usage = no;
1239e2046dfSNick Hibma curpage->pagesize++;
1249e2046dfSNick Hibma } else {
1259e2046dfSNick Hibma if (npages >= npagesmax) {
1262bf49386SPedro F. Giffuni if (pages == NULL) {
1279e2046dfSNick Hibma npagesmax = 5;
1289e2046dfSNick Hibma pages = malloc(npagesmax *
1299e2046dfSNick Hibma sizeof (struct usage_page));
1309e2046dfSNick Hibma } else {
1319e2046dfSNick Hibma npagesmax += 5;
1329e2046dfSNick Hibma pages = realloc(pages,
1339e2046dfSNick Hibma npagesmax *
1349e2046dfSNick Hibma sizeof (struct usage_page));
1359e2046dfSNick Hibma }
1369e2046dfSNick Hibma if (!pages)
1379e2046dfSNick Hibma err(1, "alloc");
1389e2046dfSNick Hibma }
1399e2046dfSNick Hibma curpage = &pages[npages++];
1409e2046dfSNick Hibma curpage->name = n;
1419e2046dfSNick Hibma curpage->usage = no;
1429e2046dfSNick Hibma curpage->pagesize = 0;
1439e2046dfSNick Hibma curpage->pagesizemax = 10;
1449e2046dfSNick Hibma curpage->page_contents =
1459e2046dfSNick Hibma malloc(curpage->pagesizemax *
1469e2046dfSNick Hibma sizeof (struct usage_in_page));
1479e2046dfSNick Hibma if (!curpage->page_contents)
1489e2046dfSNick Hibma err(1, "malloc");
1499e2046dfSNick Hibma }
1509e2046dfSNick Hibma }
1519e2046dfSNick Hibma fclose(f);
1529e2046dfSNick Hibma #ifdef DEBUG
1539e2046dfSNick Hibma dump_hid_table();
1549e2046dfSNick Hibma #endif
1559e2046dfSNick Hibma }
1569e2046dfSNick Hibma
1579e2046dfSNick Hibma const char *
hid_usage_page(int i)1589e2046dfSNick Hibma hid_usage_page(int i)
1599e2046dfSNick Hibma {
1609e2046dfSNick Hibma static char b[10];
1619e2046dfSNick Hibma int k;
1629e2046dfSNick Hibma
1639e2046dfSNick Hibma if (!pages)
164234e6b87SMatthew N. Dodd errx(1, "no hid table");
1659e2046dfSNick Hibma
1669e2046dfSNick Hibma for (k = 0; k < npages; k++)
1679e2046dfSNick Hibma if (pages[k].usage == i)
1689e2046dfSNick Hibma return pages[k].name;
16925d1d43dSNick Hibma sprintf(b, "0x%04x", i);
1709e2046dfSNick Hibma return b;
1719e2046dfSNick Hibma }
1729e2046dfSNick Hibma
1739e2046dfSNick Hibma const char *
hid_usage_in_page(unsigned int u)1749e2046dfSNick Hibma hid_usage_in_page(unsigned int u)
1759e2046dfSNick Hibma {
1769e2046dfSNick Hibma int page = HID_PAGE(u);
1779e2046dfSNick Hibma int i = HID_USAGE(u);
1789e2046dfSNick Hibma static char b[100];
1799e2046dfSNick Hibma int j, k, us;
1809e2046dfSNick Hibma
1819e2046dfSNick Hibma for (k = 0; k < npages; k++)
1829e2046dfSNick Hibma if (pages[k].usage == page)
1839e2046dfSNick Hibma break;
1849e2046dfSNick Hibma if (k >= npages)
1859e2046dfSNick Hibma goto bad;
1869e2046dfSNick Hibma for (j = 0; j < pages[k].pagesize; j++) {
1879e2046dfSNick Hibma us = pages[k].page_contents[j].usage;
1889e2046dfSNick Hibma if (us == -1) {
189234e6b87SMatthew N. Dodd sprintf(b,
190234e6b87SMatthew N. Dodd fmtcheck(pages[k].page_contents[j].name, "%d"),
191234e6b87SMatthew N. Dodd i);
1929e2046dfSNick Hibma return b;
1939e2046dfSNick Hibma }
1949e2046dfSNick Hibma if (us == i)
1959e2046dfSNick Hibma return pages[k].page_contents[j].name;
1969e2046dfSNick Hibma }
1979e2046dfSNick Hibma bad:
19825d1d43dSNick Hibma sprintf(b, "0x%04x", i);
1999e2046dfSNick Hibma return b;
2009e2046dfSNick Hibma }
201b425e319SNick Hibma
202b425e319SNick Hibma int
hid_parse_usage_page(const char * name)203b425e319SNick Hibma hid_parse_usage_page(const char *name)
204b425e319SNick Hibma {
205b425e319SNick Hibma int k;
206b425e319SNick Hibma
207b425e319SNick Hibma if (!pages)
208234e6b87SMatthew N. Dodd errx(1, "no hid table");
209b425e319SNick Hibma
210b425e319SNick Hibma for (k = 0; k < npages; k++)
211b425e319SNick Hibma if (strcmp(pages[k].name, name) == 0)
212b425e319SNick Hibma return pages[k].usage;
213b425e319SNick Hibma return -1;
214b425e319SNick Hibma }
215b425e319SNick Hibma
216b425e319SNick Hibma /* XXX handle hex */
217b425e319SNick Hibma int
hid_parse_usage_in_page(const char * name)218b425e319SNick Hibma hid_parse_usage_in_page(const char *name)
219b425e319SNick Hibma {
220234e6b87SMatthew N. Dodd const char *sep;
221b425e319SNick Hibma int k, j;
222b425e319SNick Hibma unsigned int l;
223b425e319SNick Hibma
224234e6b87SMatthew N. Dodd sep = strchr(name, ':');
225b425e319SNick Hibma if (sep == NULL)
226b425e319SNick Hibma return -1;
227b425e319SNick Hibma l = sep - name;
228b425e319SNick Hibma for (k = 0; k < npages; k++)
229b425e319SNick Hibma if (strncmp(pages[k].name, name, l) == 0)
230b425e319SNick Hibma goto found;
231b425e319SNick Hibma return -1;
232b425e319SNick Hibma found:
233b425e319SNick Hibma sep++;
234b425e319SNick Hibma for (j = 0; j < pages[k].pagesize; j++)
235b425e319SNick Hibma if (strcmp(pages[k].page_contents[j].name, sep) == 0)
236b425e319SNick Hibma return (pages[k].usage << 16) | pages[k].page_contents[j].usage;
237b425e319SNick Hibma return (-1);
238b425e319SNick Hibma }
239