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