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/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <assert.h> 33 #include <ctype.h> 34 #include <err.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 39 #include "usbhid.h" 40 41 #define _PATH_HIDTABLE "/usr/share/misc/usb_hid_usages" 42 43 struct usage_in_page { 44 const char *name; 45 int usage; 46 }; 47 48 static struct usage_page { 49 const char *name; 50 int usage; 51 struct usage_in_page *page_contents; 52 int pagesize, pagesizemax; 53 } *pages; 54 static int npages, npagesmax; 55 56 #ifdef DEBUG 57 void 58 dump_hid_table(void) 59 { 60 int i, j; 61 62 for (i = 0; i < npages; i++) { 63 printf("%d\t%s\n", pages[i].usage, pages[i].name); 64 for (j = 0; j < pages[i].pagesize; j++) { 65 printf("\t%d\t%s\n", pages[i].page_contents[j].usage, 66 pages[i].page_contents[j].name); 67 } 68 } 69 } 70 #endif 71 72 void 73 hid_init(const char *hidname) 74 { 75 FILE *f; 76 char line[100], name[100], *p, *n; 77 int no; 78 int lineno; 79 struct usage_page *curpage = 0; 80 81 if (hidname == 0) 82 hidname = _PATH_HIDTABLE; 83 84 f = fopen(hidname, "r"); 85 if (f == NULL) 86 err(1, "%s", hidname); 87 for (lineno = 1; ; lineno++) { 88 if (fgets(line, sizeof line, f) == NULL) 89 break; 90 if (line[0] == '#') 91 continue; 92 for (p = line; *p && isspace(*p); p++) 93 ; 94 if (!*p) 95 continue; 96 if (sscanf(line, " * %[^\n]", name) == 1) 97 no = -1; 98 else if (sscanf(line, " 0x%x %[^\n]", &no, name) != 2 && 99 sscanf(line, " %d %[^\n]", &no, name) != 2) 100 errx(1, "file %s, line %d, syntax error", 101 hidname, lineno); 102 for (p = name; *p; p++) 103 if (isspace(*p) || *p == '.') 104 *p = '_'; 105 n = strdup(name); 106 if (!n) 107 err(1, "strdup"); 108 if (isspace(line[0])) { 109 if (!curpage) 110 errx(1, "file %s, line %d, syntax error", 111 hidname, lineno); 112 if (curpage->pagesize >= curpage->pagesizemax) { 113 curpage->pagesizemax += 10; 114 curpage->page_contents = 115 realloc(curpage->page_contents, 116 curpage->pagesizemax * 117 sizeof (struct usage_in_page)); 118 if (!curpage->page_contents) 119 err(1, "realloc"); 120 } 121 curpage->page_contents[curpage->pagesize].name = n; 122 curpage->page_contents[curpage->pagesize].usage = no; 123 curpage->pagesize++; 124 } else { 125 if (npages >= npagesmax) { 126 if (pages == 0) { 127 npagesmax = 5; 128 pages = malloc(npagesmax * 129 sizeof (struct usage_page)); 130 } else { 131 npagesmax += 5; 132 pages = realloc(pages, 133 npagesmax * 134 sizeof (struct usage_page)); 135 } 136 if (!pages) 137 err(1, "alloc"); 138 } 139 curpage = &pages[npages++]; 140 curpage->name = n; 141 curpage->usage = no; 142 curpage->pagesize = 0; 143 curpage->pagesizemax = 10; 144 curpage->page_contents = 145 malloc(curpage->pagesizemax * 146 sizeof (struct usage_in_page)); 147 if (!curpage->page_contents) 148 err(1, "malloc"); 149 } 150 } 151 fclose(f); 152 #ifdef DEBUG 153 dump_hid_table(); 154 #endif 155 } 156 157 const char * 158 hid_usage_page(int i) 159 { 160 static char b[10]; 161 int k; 162 163 if (!pages) 164 errx(1, "no hid table"); 165 166 for (k = 0; k < npages; k++) 167 if (pages[k].usage == i) 168 return pages[k].name; 169 sprintf(b, "0x%04x", i); 170 return b; 171 } 172 173 const char * 174 hid_usage_in_page(unsigned int u) 175 { 176 int page = HID_PAGE(u); 177 int i = HID_USAGE(u); 178 static char b[100]; 179 int j, k, us; 180 181 for (k = 0; k < npages; k++) 182 if (pages[k].usage == page) 183 break; 184 if (k >= npages) 185 goto bad; 186 for (j = 0; j < pages[k].pagesize; j++) { 187 us = pages[k].page_contents[j].usage; 188 if (us == -1) { 189 sprintf(b, 190 fmtcheck(pages[k].page_contents[j].name, "%d"), 191 i); 192 return b; 193 } 194 if (us == i) 195 return pages[k].page_contents[j].name; 196 } 197 bad: 198 sprintf(b, "0x%04x", i); 199 return b; 200 } 201 202 int 203 hid_parse_usage_page(const char *name) 204 { 205 int k; 206 207 if (!pages) 208 errx(1, "no hid table"); 209 210 for (k = 0; k < npages; k++) 211 if (strcmp(pages[k].name, name) == 0) 212 return pages[k].usage; 213 return -1; 214 } 215 216 /* XXX handle hex */ 217 int 218 hid_parse_usage_in_page(const char *name) 219 { 220 const char *sep; 221 int k, j; 222 unsigned int l; 223 224 sep = strchr(name, ':'); 225 if (sep == NULL) 226 return -1; 227 l = sep - name; 228 for (k = 0; k < npages; k++) 229 if (strncmp(pages[k].name, name, l) == 0) 230 goto found; 231 return -1; 232 found: 233 sep++; 234 for (j = 0; j < pages[k].pagesize; j++) 235 if (strcmp(pages[k].page_contents[j].name, sep) == 0) 236 return (pages[k].usage << 16) | pages[k].page_contents[j].usage; 237 return (-1); 238 } 239