1b425e319SNick Hibma /* $NetBSD: usage.c,v 1.8 2000/10/10 19:23:58 is Exp $ */ 29e2046dfSNick Hibma 3*5e53a4f9SPedro F. Giffuni /*- 4*5e53a4f9SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-NetBSD 5*5e53a4f9SPedro 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 31209040d8SMatthew Dillon #include <sys/cdefs.h> 32209040d8SMatthew Dillon __FBSDID("$FreeBSD$"); 33209040d8SMatthew Dillon 34cde58781SKai Wang #include <sys/param.h> 35cf0e07e5SMatthew N. Dodd #include <assert.h> 369e2046dfSNick Hibma #include <ctype.h> 379e2046dfSNick Hibma #include <err.h> 389e2046dfSNick Hibma #include <stdio.h> 399e2046dfSNick Hibma #include <stdlib.h> 409e2046dfSNick Hibma #include <string.h> 419e2046dfSNick Hibma 42cf0e07e5SMatthew N. Dodd #include "usbhid.h" 439e2046dfSNick Hibma 449e2046dfSNick Hibma #define _PATH_HIDTABLE "/usr/share/misc/usb_hid_usages" 459e2046dfSNick Hibma 469e2046dfSNick Hibma struct usage_in_page { 479e2046dfSNick Hibma const char *name; 489e2046dfSNick Hibma int usage; 499e2046dfSNick Hibma }; 509e2046dfSNick Hibma 519e2046dfSNick Hibma static struct usage_page { 529e2046dfSNick Hibma const char *name; 539e2046dfSNick Hibma int usage; 549e2046dfSNick Hibma struct usage_in_page *page_contents; 559e2046dfSNick Hibma int pagesize, pagesizemax; 569e2046dfSNick Hibma } *pages; 579e2046dfSNick Hibma static int npages, npagesmax; 589e2046dfSNick Hibma 599e2046dfSNick Hibma #ifdef DEBUG 609e2046dfSNick Hibma void 619e2046dfSNick Hibma dump_hid_table(void) 629e2046dfSNick Hibma { 639e2046dfSNick Hibma int i, j; 649e2046dfSNick Hibma 659e2046dfSNick Hibma for (i = 0; i < npages; i++) { 669e2046dfSNick Hibma printf("%d\t%s\n", pages[i].usage, pages[i].name); 679e2046dfSNick Hibma for (j = 0; j < pages[i].pagesize; j++) { 689e2046dfSNick Hibma printf("\t%d\t%s\n", pages[i].page_contents[j].usage, 699e2046dfSNick Hibma pages[i].page_contents[j].name); 709e2046dfSNick Hibma } 719e2046dfSNick Hibma } 729e2046dfSNick Hibma } 739e2046dfSNick Hibma #endif 749e2046dfSNick Hibma 759e2046dfSNick Hibma void 769e2046dfSNick Hibma hid_init(const char *hidname) 779e2046dfSNick Hibma { 789e2046dfSNick Hibma FILE *f; 799e2046dfSNick Hibma char line[100], name[100], *p, *n; 809e2046dfSNick Hibma int no; 819e2046dfSNick Hibma int lineno; 822bf49386SPedro F. Giffuni struct usage_page *curpage = NULL; 839e2046dfSNick Hibma 842bf49386SPedro F. Giffuni if (hidname == NULL) 859e2046dfSNick Hibma hidname = _PATH_HIDTABLE; 869e2046dfSNick Hibma 879e2046dfSNick Hibma f = fopen(hidname, "r"); 889e2046dfSNick Hibma if (f == NULL) 899e2046dfSNick Hibma err(1, "%s", hidname); 909e2046dfSNick Hibma for (lineno = 1; ; lineno++) { 919e2046dfSNick Hibma if (fgets(line, sizeof line, f) == NULL) 929e2046dfSNick Hibma break; 939e2046dfSNick Hibma if (line[0] == '#') 949e2046dfSNick Hibma continue; 959e2046dfSNick Hibma for (p = line; *p && isspace(*p); p++) 969e2046dfSNick Hibma ; 979e2046dfSNick Hibma if (!*p) 989e2046dfSNick Hibma continue; 999e2046dfSNick Hibma if (sscanf(line, " * %[^\n]", name) == 1) 1009e2046dfSNick Hibma no = -1; 1019e2046dfSNick Hibma else if (sscanf(line, " 0x%x %[^\n]", &no, name) != 2 && 1029e2046dfSNick Hibma sscanf(line, " %d %[^\n]", &no, name) != 2) 103234e6b87SMatthew N. Dodd errx(1, "file %s, line %d, syntax error", 1049e2046dfSNick Hibma hidname, lineno); 1059e2046dfSNick Hibma for (p = name; *p; p++) 1069e2046dfSNick Hibma if (isspace(*p) || *p == '.') 1079e2046dfSNick Hibma *p = '_'; 1089e2046dfSNick Hibma n = strdup(name); 1099e2046dfSNick Hibma if (!n) 1109e2046dfSNick Hibma err(1, "strdup"); 1119e2046dfSNick Hibma if (isspace(line[0])) { 1129e2046dfSNick Hibma if (!curpage) 113234e6b87SMatthew N. Dodd errx(1, "file %s, line %d, syntax error", 1149e2046dfSNick Hibma hidname, lineno); 1159e2046dfSNick Hibma if (curpage->pagesize >= curpage->pagesizemax) { 1169e2046dfSNick Hibma curpage->pagesizemax += 10; 1179e2046dfSNick Hibma curpage->page_contents = 1189e2046dfSNick Hibma realloc(curpage->page_contents, 1199e2046dfSNick Hibma curpage->pagesizemax * 1209e2046dfSNick Hibma sizeof (struct usage_in_page)); 1219e2046dfSNick Hibma if (!curpage->page_contents) 1229e2046dfSNick Hibma err(1, "realloc"); 1239e2046dfSNick Hibma } 1249e2046dfSNick Hibma curpage->page_contents[curpage->pagesize].name = n; 1259e2046dfSNick Hibma curpage->page_contents[curpage->pagesize].usage = no; 1269e2046dfSNick Hibma curpage->pagesize++; 1279e2046dfSNick Hibma } else { 1289e2046dfSNick Hibma if (npages >= npagesmax) { 1292bf49386SPedro F. Giffuni if (pages == NULL) { 1309e2046dfSNick Hibma npagesmax = 5; 1319e2046dfSNick Hibma pages = malloc(npagesmax * 1329e2046dfSNick Hibma sizeof (struct usage_page)); 1339e2046dfSNick Hibma } else { 1349e2046dfSNick Hibma npagesmax += 5; 1359e2046dfSNick Hibma pages = realloc(pages, 1369e2046dfSNick Hibma npagesmax * 1379e2046dfSNick Hibma sizeof (struct usage_page)); 1389e2046dfSNick Hibma } 1399e2046dfSNick Hibma if (!pages) 1409e2046dfSNick Hibma err(1, "alloc"); 1419e2046dfSNick Hibma } 1429e2046dfSNick Hibma curpage = &pages[npages++]; 1439e2046dfSNick Hibma curpage->name = n; 1449e2046dfSNick Hibma curpage->usage = no; 1459e2046dfSNick Hibma curpage->pagesize = 0; 1469e2046dfSNick Hibma curpage->pagesizemax = 10; 1479e2046dfSNick Hibma curpage->page_contents = 1489e2046dfSNick Hibma malloc(curpage->pagesizemax * 1499e2046dfSNick Hibma sizeof (struct usage_in_page)); 1509e2046dfSNick Hibma if (!curpage->page_contents) 1519e2046dfSNick Hibma err(1, "malloc"); 1529e2046dfSNick Hibma } 1539e2046dfSNick Hibma } 1549e2046dfSNick Hibma fclose(f); 1559e2046dfSNick Hibma #ifdef DEBUG 1569e2046dfSNick Hibma dump_hid_table(); 1579e2046dfSNick Hibma #endif 1589e2046dfSNick Hibma } 1599e2046dfSNick Hibma 1609e2046dfSNick Hibma const char * 1619e2046dfSNick Hibma hid_usage_page(int i) 1629e2046dfSNick Hibma { 1639e2046dfSNick Hibma static char b[10]; 1649e2046dfSNick Hibma int k; 1659e2046dfSNick Hibma 1669e2046dfSNick Hibma if (!pages) 167234e6b87SMatthew N. Dodd errx(1, "no hid table"); 1689e2046dfSNick Hibma 1699e2046dfSNick Hibma for (k = 0; k < npages; k++) 1709e2046dfSNick Hibma if (pages[k].usage == i) 1719e2046dfSNick Hibma return pages[k].name; 17225d1d43dSNick Hibma sprintf(b, "0x%04x", i); 1739e2046dfSNick Hibma return b; 1749e2046dfSNick Hibma } 1759e2046dfSNick Hibma 1769e2046dfSNick Hibma const char * 1779e2046dfSNick Hibma hid_usage_in_page(unsigned int u) 1789e2046dfSNick Hibma { 1799e2046dfSNick Hibma int page = HID_PAGE(u); 1809e2046dfSNick Hibma int i = HID_USAGE(u); 1819e2046dfSNick Hibma static char b[100]; 1829e2046dfSNick Hibma int j, k, us; 1839e2046dfSNick Hibma 1849e2046dfSNick Hibma for (k = 0; k < npages; k++) 1859e2046dfSNick Hibma if (pages[k].usage == page) 1869e2046dfSNick Hibma break; 1879e2046dfSNick Hibma if (k >= npages) 1889e2046dfSNick Hibma goto bad; 1899e2046dfSNick Hibma for (j = 0; j < pages[k].pagesize; j++) { 1909e2046dfSNick Hibma us = pages[k].page_contents[j].usage; 1919e2046dfSNick Hibma if (us == -1) { 192234e6b87SMatthew N. Dodd sprintf(b, 193234e6b87SMatthew N. Dodd fmtcheck(pages[k].page_contents[j].name, "%d"), 194234e6b87SMatthew N. Dodd i); 1959e2046dfSNick Hibma return b; 1969e2046dfSNick Hibma } 1979e2046dfSNick Hibma if (us == i) 1989e2046dfSNick Hibma return pages[k].page_contents[j].name; 1999e2046dfSNick Hibma } 2009e2046dfSNick Hibma bad: 20125d1d43dSNick Hibma sprintf(b, "0x%04x", i); 2029e2046dfSNick Hibma return b; 2039e2046dfSNick Hibma } 204b425e319SNick Hibma 205b425e319SNick Hibma int 206b425e319SNick Hibma hid_parse_usage_page(const char *name) 207b425e319SNick Hibma { 208b425e319SNick Hibma int k; 209b425e319SNick Hibma 210b425e319SNick Hibma if (!pages) 211234e6b87SMatthew N. Dodd errx(1, "no hid table"); 212b425e319SNick Hibma 213b425e319SNick Hibma for (k = 0; k < npages; k++) 214b425e319SNick Hibma if (strcmp(pages[k].name, name) == 0) 215b425e319SNick Hibma return pages[k].usage; 216b425e319SNick Hibma return -1; 217b425e319SNick Hibma } 218b425e319SNick Hibma 219b425e319SNick Hibma /* XXX handle hex */ 220b425e319SNick Hibma int 221b425e319SNick Hibma hid_parse_usage_in_page(const char *name) 222b425e319SNick Hibma { 223234e6b87SMatthew N. Dodd const char *sep; 224b425e319SNick Hibma int k, j; 225b425e319SNick Hibma unsigned int l; 226b425e319SNick Hibma 227234e6b87SMatthew N. Dodd sep = strchr(name, ':'); 228b425e319SNick Hibma if (sep == NULL) 229b425e319SNick Hibma return -1; 230b425e319SNick Hibma l = sep - name; 231b425e319SNick Hibma for (k = 0; k < npages; k++) 232b425e319SNick Hibma if (strncmp(pages[k].name, name, l) == 0) 233b425e319SNick Hibma goto found; 234b425e319SNick Hibma return -1; 235b425e319SNick Hibma found: 236b425e319SNick Hibma sep++; 237b425e319SNick Hibma for (j = 0; j < pages[k].pagesize; j++) 238b425e319SNick Hibma if (strcmp(pages[k].page_contents[j].name, sep) == 0) 239b425e319SNick Hibma return (pages[k].usage << 16) | pages[k].page_contents[j].usage; 240b425e319SNick Hibma return (-1); 241b425e319SNick Hibma } 242