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