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