1b425e319SNick Hibma /* $NetBSD: usage.c,v 1.8 2000/10/10 19:23:58 is Exp $ */ 29e2046dfSNick Hibma 39e2046dfSNick Hibma /* 49e2046dfSNick Hibma * Copyright (c) 1999 Lennart Augustsson <augustss@netbsd.org> 59e2046dfSNick Hibma * All rights reserved. 69e2046dfSNick Hibma * 79e2046dfSNick Hibma * Redistribution and use in source and binary forms, with or without 89e2046dfSNick Hibma * modification, are permitted provided that the following conditions 99e2046dfSNick Hibma * are met: 109e2046dfSNick Hibma * 1. Redistributions of source code must retain the above copyright 119e2046dfSNick Hibma * notice, this list of conditions and the following disclaimer. 129e2046dfSNick Hibma * 2. Redistributions in binary form must reproduce the above copyright 139e2046dfSNick Hibma * notice, this list of conditions and the following disclaimer in the 149e2046dfSNick Hibma * documentation and/or other materials provided with the distribution. 159e2046dfSNick Hibma * 169e2046dfSNick Hibma * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 179e2046dfSNick Hibma * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 189e2046dfSNick Hibma * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 199e2046dfSNick Hibma * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 209e2046dfSNick Hibma * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 219e2046dfSNick Hibma * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 229e2046dfSNick Hibma * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 239e2046dfSNick Hibma * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 249e2046dfSNick Hibma * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 259e2046dfSNick Hibma * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 269e2046dfSNick Hibma * SUCH DAMAGE. 279e2046dfSNick Hibma */ 289e2046dfSNick Hibma 29209040d8SMatthew Dillon #include <sys/cdefs.h> 30209040d8SMatthew Dillon __FBSDID("$FreeBSD$"); 31209040d8SMatthew Dillon 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 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 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; 799e2046dfSNick Hibma struct usage_page *curpage = 0; 809e2046dfSNick Hibma 819e2046dfSNick Hibma if (hidname == 0) 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) { 1269e2046dfSNick Hibma if (pages == 0) { 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 * 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 * 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 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 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