167217Sn_hibma/* $NetBSD: usage.c,v 1.8 2000/10/10 19:23:58 is Exp $ */ 261560Sn_hibma 361560Sn_hibma/* 461560Sn_hibma * Copyright (c) 1999 Lennart Augustsson <augustss@netbsd.org> 561560Sn_hibma * All rights reserved. 661560Sn_hibma * 761560Sn_hibma * Redistribution and use in source and binary forms, with or without 861560Sn_hibma * modification, are permitted provided that the following conditions 961560Sn_hibma * are met: 1061560Sn_hibma * 1. Redistributions of source code must retain the above copyright 1161560Sn_hibma * notice, this list of conditions and the following disclaimer. 1261560Sn_hibma * 2. Redistributions in binary form must reproduce the above copyright 1361560Sn_hibma * notice, this list of conditions and the following disclaimer in the 1461560Sn_hibma * documentation and/or other materials provided with the distribution. 1561560Sn_hibma * 1661560Sn_hibma * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1761560Sn_hibma * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1861560Sn_hibma * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1961560Sn_hibma * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2061560Sn_hibma * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2161560Sn_hibma * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2261560Sn_hibma * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2361560Sn_hibma * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2461560Sn_hibma * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2561560Sn_hibma * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2661560Sn_hibma * SUCH DAMAGE. 2761560Sn_hibma */ 2861560Sn_hibma 2984224Sdillon#include <sys/cdefs.h> 3084224Sdillon__FBSDID("$FreeBSD$"); 3184224Sdillon 32205728Skaiw#include <sys/param.h> 33113273Smdodd#include <assert.h> 3461560Sn_hibma#include <ctype.h> 3561560Sn_hibma#include <err.h> 3661560Sn_hibma#include <stdio.h> 3761560Sn_hibma#include <stdlib.h> 3861560Sn_hibma#include <string.h> 3961560Sn_hibma 40113273Smdodd#include "usbhid.h" 4161560Sn_hibma 4261560Sn_hibma#define _PATH_HIDTABLE "/usr/share/misc/usb_hid_usages" 4361560Sn_hibma 4461560Sn_hibmastruct usage_in_page { 4561560Sn_hibma const char *name; 4661560Sn_hibma int usage; 4761560Sn_hibma}; 4861560Sn_hibma 4961560Sn_hibmastatic struct usage_page { 5061560Sn_hibma const char *name; 5161560Sn_hibma int usage; 5261560Sn_hibma struct usage_in_page *page_contents; 5361560Sn_hibma int pagesize, pagesizemax; 5461560Sn_hibma} *pages; 5561560Sn_hibmastatic int npages, npagesmax; 5661560Sn_hibma 5761560Sn_hibma#ifdef DEBUG 5861560Sn_hibmavoid 5961560Sn_hibmadump_hid_table(void) 6061560Sn_hibma{ 6161560Sn_hibma int i, j; 6261560Sn_hibma 6361560Sn_hibma for (i = 0; i < npages; i++) { 6461560Sn_hibma printf("%d\t%s\n", pages[i].usage, pages[i].name); 6561560Sn_hibma for (j = 0; j < pages[i].pagesize; j++) { 6661560Sn_hibma printf("\t%d\t%s\n", pages[i].page_contents[j].usage, 6761560Sn_hibma pages[i].page_contents[j].name); 6861560Sn_hibma } 6961560Sn_hibma } 7061560Sn_hibma} 7161560Sn_hibma#endif 7261560Sn_hibma 7361560Sn_hibmavoid 7461560Sn_hibmahid_init(const char *hidname) 7561560Sn_hibma{ 7661560Sn_hibma FILE *f; 7761560Sn_hibma char line[100], name[100], *p, *n; 7861560Sn_hibma int no; 7961560Sn_hibma int lineno; 8061560Sn_hibma struct usage_page *curpage = 0; 8161560Sn_hibma 8261560Sn_hibma if (hidname == 0) 8361560Sn_hibma hidname = _PATH_HIDTABLE; 8461560Sn_hibma 8561560Sn_hibma f = fopen(hidname, "r"); 8661560Sn_hibma if (f == NULL) 8761560Sn_hibma err(1, "%s", hidname); 8861560Sn_hibma for (lineno = 1; ; lineno++) { 8961560Sn_hibma if (fgets(line, sizeof line, f) == NULL) 9061560Sn_hibma break; 9161560Sn_hibma if (line[0] == '#') 9261560Sn_hibma continue; 9361560Sn_hibma for (p = line; *p && isspace(*p); p++) 9461560Sn_hibma ; 9561560Sn_hibma if (!*p) 9661560Sn_hibma continue; 9761560Sn_hibma if (sscanf(line, " * %[^\n]", name) == 1) 9861560Sn_hibma no = -1; 9961560Sn_hibma else if (sscanf(line, " 0x%x %[^\n]", &no, name) != 2 && 10061560Sn_hibma sscanf(line, " %d %[^\n]", &no, name) != 2) 101113193Smdodd errx(1, "file %s, line %d, syntax error", 10261560Sn_hibma hidname, lineno); 10361560Sn_hibma for (p = name; *p; p++) 10461560Sn_hibma if (isspace(*p) || *p == '.') 10561560Sn_hibma *p = '_'; 10661560Sn_hibma n = strdup(name); 10761560Sn_hibma if (!n) 10861560Sn_hibma err(1, "strdup"); 10961560Sn_hibma if (isspace(line[0])) { 11061560Sn_hibma if (!curpage) 111113193Smdodd errx(1, "file %s, line %d, syntax error", 11261560Sn_hibma hidname, lineno); 11361560Sn_hibma if (curpage->pagesize >= curpage->pagesizemax) { 11461560Sn_hibma curpage->pagesizemax += 10; 11561560Sn_hibma curpage->page_contents = 11661560Sn_hibma realloc(curpage->page_contents, 11761560Sn_hibma curpage->pagesizemax * 11861560Sn_hibma sizeof (struct usage_in_page)); 11961560Sn_hibma if (!curpage->page_contents) 12061560Sn_hibma err(1, "realloc"); 12161560Sn_hibma } 12261560Sn_hibma curpage->page_contents[curpage->pagesize].name = n; 12361560Sn_hibma curpage->page_contents[curpage->pagesize].usage = no; 12461560Sn_hibma curpage->pagesize++; 12561560Sn_hibma } else { 12661560Sn_hibma if (npages >= npagesmax) { 12761560Sn_hibma if (pages == 0) { 12861560Sn_hibma npagesmax = 5; 12961560Sn_hibma pages = malloc(npagesmax * 13061560Sn_hibma sizeof (struct usage_page)); 13161560Sn_hibma } else { 13261560Sn_hibma npagesmax += 5; 13361560Sn_hibma pages = realloc(pages, 13461560Sn_hibma npagesmax * 13561560Sn_hibma sizeof (struct usage_page)); 13661560Sn_hibma } 13761560Sn_hibma if (!pages) 13861560Sn_hibma err(1, "alloc"); 13961560Sn_hibma } 14061560Sn_hibma curpage = &pages[npages++]; 14161560Sn_hibma curpage->name = n; 14261560Sn_hibma curpage->usage = no; 14361560Sn_hibma curpage->pagesize = 0; 14461560Sn_hibma curpage->pagesizemax = 10; 14561560Sn_hibma curpage->page_contents = 14661560Sn_hibma malloc(curpage->pagesizemax * 14761560Sn_hibma sizeof (struct usage_in_page)); 14861560Sn_hibma if (!curpage->page_contents) 14961560Sn_hibma err(1, "malloc"); 15061560Sn_hibma } 15161560Sn_hibma } 15261560Sn_hibma fclose(f); 15361560Sn_hibma#ifdef DEBUG 15461560Sn_hibma dump_hid_table(); 15561560Sn_hibma#endif 15661560Sn_hibma} 15761560Sn_hibma 15861560Sn_hibmaconst char * 15961560Sn_hibmahid_usage_page(int i) 16061560Sn_hibma{ 16161560Sn_hibma static char b[10]; 16261560Sn_hibma int k; 16361560Sn_hibma 16461560Sn_hibma if (!pages) 165113193Smdodd errx(1, "no hid table"); 16661560Sn_hibma 16761560Sn_hibma for (k = 0; k < npages; k++) 16861560Sn_hibma if (pages[k].usage == i) 16961560Sn_hibma return pages[k].name; 17065116Sn_hibma sprintf(b, "0x%04x", i); 17161560Sn_hibma return b; 17261560Sn_hibma} 17361560Sn_hibma 17461560Sn_hibmaconst char * 17561560Sn_hibmahid_usage_in_page(unsigned int u) 17661560Sn_hibma{ 17761560Sn_hibma int page = HID_PAGE(u); 17861560Sn_hibma int i = HID_USAGE(u); 17961560Sn_hibma static char b[100]; 18061560Sn_hibma int j, k, us; 18161560Sn_hibma 18261560Sn_hibma for (k = 0; k < npages; k++) 18361560Sn_hibma if (pages[k].usage == page) 18461560Sn_hibma break; 18561560Sn_hibma if (k >= npages) 18661560Sn_hibma goto bad; 18761560Sn_hibma for (j = 0; j < pages[k].pagesize; j++) { 18861560Sn_hibma us = pages[k].page_contents[j].usage; 18961560Sn_hibma if (us == -1) { 190113193Smdodd sprintf(b, 191113193Smdodd fmtcheck(pages[k].page_contents[j].name, "%d"), 192113193Smdodd i); 19361560Sn_hibma return b; 19461560Sn_hibma } 19561560Sn_hibma if (us == i) 19661560Sn_hibma return pages[k].page_contents[j].name; 19761560Sn_hibma } 19861560Sn_hibma bad: 19965116Sn_hibma sprintf(b, "0x%04x", i); 20061560Sn_hibma return b; 20161560Sn_hibma} 20267217Sn_hibma 20367217Sn_hibmaint 20467217Sn_hibmahid_parse_usage_page(const char *name) 20567217Sn_hibma{ 20667217Sn_hibma int k; 20767217Sn_hibma 20867217Sn_hibma if (!pages) 209113193Smdodd errx(1, "no hid table"); 21067217Sn_hibma 21167217Sn_hibma for (k = 0; k < npages; k++) 21267217Sn_hibma if (strcmp(pages[k].name, name) == 0) 21367217Sn_hibma return pages[k].usage; 21467217Sn_hibma return -1; 21567217Sn_hibma} 21667217Sn_hibma 21767217Sn_hibma/* XXX handle hex */ 21867217Sn_hibmaint 21967217Sn_hibmahid_parse_usage_in_page(const char *name) 22067217Sn_hibma{ 221113193Smdodd const char *sep; 22267217Sn_hibma int k, j; 22367217Sn_hibma unsigned int l; 22467217Sn_hibma 225113193Smdodd sep = strchr(name, ':'); 22667217Sn_hibma if (sep == NULL) 22767217Sn_hibma return -1; 22867217Sn_hibma l = sep - name; 22967217Sn_hibma for (k = 0; k < npages; k++) 23067217Sn_hibma if (strncmp(pages[k].name, name, l) == 0) 23167217Sn_hibma goto found; 23267217Sn_hibma return -1; 23367217Sn_hibma found: 23467217Sn_hibma sep++; 23567217Sn_hibma for (j = 0; j < pages[k].pagesize; j++) 23667217Sn_hibma if (strcmp(pages[k].page_contents[j].name, sep) == 0) 23767217Sn_hibma return (pages[k].usage << 16) | pages[k].page_contents[j].usage; 23867217Sn_hibma return (-1); 23967217Sn_hibma} 240