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