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