1 /* $OpenBSD: usage.c,v 1.1 2001/12/30 07:04:38 pvalchev Exp $ */ 2 /* $NetBSD: usage.c,v 1.11 2001/01/09 15:59:47 augustss Exp $ */ 3 4 /* 5 * Copyright (c) 1999 Lennart Augustsson <augustss@netbsd.org> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 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\n", 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\n", 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\n"); 162 163 for (k = 0; k < npages; k++) 164 if (pages[k].usage == i) 165 return pages[k].name; 166 snprintf(b, sizeof 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 snprintf(b, sizeof b, "%s %d", 187 pages[k].page_contents[j].name, i); 188 return b; 189 } 190 if (us == i) 191 return pages[k].page_contents[j].name; 192 } 193 bad: 194 snprintf(b, sizeof b, "0x%04x", i); 195 return b; 196 } 197 198 int 199 hid_parse_usage_page(const char *name) 200 { 201 int k; 202 203 if (!pages) 204 errx(1, "no hid table\n"); 205 206 for (k = 0; k < npages; k++) 207 if (strcmp(pages[k].name, name) == 0) 208 return pages[k].usage; 209 return -1; 210 } 211 212 /* XXX handle hex */ 213 int 214 hid_parse_usage_in_page(const char *name) 215 { 216 const char *sep = strchr(name, ':'); 217 int k, j; 218 unsigned int l; 219 220 if (sep == NULL) 221 return -1; 222 l = sep - name; 223 for (k = 0; k < npages; k++) 224 if (strncmp(pages[k].name, name, l) == 0) 225 goto found; 226 return -1; 227 found: 228 sep++; 229 for (j = 0; j < pages[k].pagesize; j++) 230 if (strcmp(pages[k].page_contents[j].name, sep) == 0) 231 return (pages[k].usage << 16) | pages[k].page_contents[j].usage; 232 return (-1); 233 } 234