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