2006-04-09 04:49:55 +04:00
|
|
|
/* $NetBSD: usage.c,v 1.7 2006/04/09 00:49:55 christos Exp $ */
|
1999-05-12 01:02:24 +04:00
|
|
|
|
|
|
|
/*
|
2003-07-26 23:24:24 +04:00
|
|
|
* Copyright (c) 1999 Lennart Augustsson <augustss@NetBSD.org>
|
1999-05-12 01:02:24 +04:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
1999-05-12 01:15:46 +04:00
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
1999-05-12 01:02:24 +04:00
|
|
|
*
|
1999-05-12 01:15:46 +04:00
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
1999-05-12 01:02:24 +04:00
|
|
|
*/
|
|
|
|
|
2003-03-08 10:42:33 +03:00
|
|
|
#include <sys/cdefs.h>
|
2006-04-09 04:49:55 +04:00
|
|
|
__RCSID("$NetBSD: usage.c,v 1.7 2006/04/09 00:49:55 christos Exp $");
|
2003-03-08 10:42:33 +03:00
|
|
|
|
2001-01-09 18:59:47 +03:00
|
|
|
#include <assert.h>
|
1999-05-12 01:02:24 +04:00
|
|
|
#include <ctype.h>
|
|
|
|
#include <err.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2001-12-28 20:45:25 +03:00
|
|
|
#include "usbhid.h"
|
1999-05-12 01:02:24 +04:00
|
|
|
|
|
|
|
#define _PATH_HIDTABLE "/usr/share/misc/usb_hid_usages"
|
|
|
|
|
|
|
|
struct usage_in_page {
|
2000-04-02 15:10:53 +04:00
|
|
|
const char *name;
|
1999-05-12 01:02:24 +04:00
|
|
|
int usage;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct usage_page {
|
2000-04-02 15:10:53 +04:00
|
|
|
const char *name;
|
1999-05-12 01:02:24 +04:00
|
|
|
int usage;
|
|
|
|
struct usage_in_page *page_contents;
|
|
|
|
int pagesize, pagesizemax;
|
|
|
|
} *pages;
|
|
|
|
static int npages, npagesmax;
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
2006-04-09 04:49:55 +04:00
|
|
|
static void dump_hid_table(void);
|
|
|
|
static void
|
1999-05-12 01:02:24 +04:00
|
|
|
dump_hid_table(void)
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
for (i = 0; i < npages; i++) {
|
|
|
|
printf("%d\t%s\n", pages[i].usage, pages[i].name);
|
|
|
|
for (j = 0; j < pages[i].pagesize; j++) {
|
|
|
|
printf("\t%d\t%s\n", pages[i].page_contents[j].usage,
|
|
|
|
pages[i].page_contents[j].name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void
|
2000-04-02 15:10:53 +04:00
|
|
|
hid_init(const char *hidname)
|
1999-05-12 01:02:24 +04:00
|
|
|
{
|
|
|
|
FILE *f;
|
|
|
|
char line[100], name[100], *p, *n;
|
|
|
|
int no;
|
|
|
|
int lineno;
|
|
|
|
struct usage_page *curpage = 0;
|
|
|
|
|
|
|
|
if (hidname == 0)
|
|
|
|
hidname = _PATH_HIDTABLE;
|
|
|
|
|
|
|
|
f = fopen(hidname, "r");
|
|
|
|
if (f == NULL)
|
|
|
|
err(1, "%s", hidname);
|
|
|
|
for (lineno = 1; ; lineno++) {
|
|
|
|
if (fgets(line, sizeof line, f) == NULL)
|
|
|
|
break;
|
|
|
|
if (line[0] == '#')
|
|
|
|
continue;
|
2004-10-29 01:14:52 +04:00
|
|
|
for (p = line; *p && isspace((unsigned char)*p); p++)
|
1999-05-12 01:02:24 +04:00
|
|
|
;
|
|
|
|
if (!*p)
|
|
|
|
continue;
|
|
|
|
if (sscanf(line, " * %[^\n]", name) == 1)
|
|
|
|
no = -1;
|
|
|
|
else if (sscanf(line, " 0x%x %[^\n]", &no, name) != 2 &&
|
|
|
|
sscanf(line, " %d %[^\n]", &no, name) != 2)
|
2002-07-20 12:36:17 +04:00
|
|
|
errx(1, "file %s, line %d, syntax error",
|
1999-05-12 01:02:24 +04:00
|
|
|
hidname, lineno);
|
|
|
|
for (p = name; *p; p++)
|
2004-10-29 01:14:52 +04:00
|
|
|
if (isspace((unsigned char)*p) || *p == '.')
|
1999-05-12 01:02:24 +04:00
|
|
|
*p = '_';
|
|
|
|
n = strdup(name);
|
|
|
|
if (!n)
|
|
|
|
err(1, "strdup");
|
2004-10-29 01:14:52 +04:00
|
|
|
if (isspace((unsigned char)line[0])) {
|
1999-05-12 01:02:24 +04:00
|
|
|
if (!curpage)
|
2002-07-20 12:36:17 +04:00
|
|
|
errx(1, "file %s, line %d, syntax error",
|
1999-05-12 01:02:24 +04:00
|
|
|
hidname, lineno);
|
|
|
|
if (curpage->pagesize >= curpage->pagesizemax) {
|
|
|
|
curpage->pagesizemax += 10;
|
1999-07-02 19:46:05 +04:00
|
|
|
curpage->page_contents =
|
1999-05-12 01:02:24 +04:00
|
|
|
realloc(curpage->page_contents,
|
1999-07-02 19:46:05 +04:00
|
|
|
curpage->pagesizemax *
|
1999-05-12 01:02:24 +04:00
|
|
|
sizeof (struct usage_in_page));
|
|
|
|
if (!curpage->page_contents)
|
|
|
|
err(1, "realloc");
|
|
|
|
}
|
|
|
|
curpage->page_contents[curpage->pagesize].name = n;
|
|
|
|
curpage->page_contents[curpage->pagesize].usage = no;
|
|
|
|
curpage->pagesize++;
|
|
|
|
} else {
|
|
|
|
if (npages >= npagesmax) {
|
|
|
|
if (pages == 0) {
|
|
|
|
npagesmax = 5;
|
1999-07-02 19:46:05 +04:00
|
|
|
pages = malloc(npagesmax *
|
1999-05-12 01:02:24 +04:00
|
|
|
sizeof (struct usage_page));
|
|
|
|
} else {
|
|
|
|
npagesmax += 5;
|
1999-07-02 19:46:05 +04:00
|
|
|
pages = realloc(pages,
|
|
|
|
npagesmax *
|
1999-05-12 01:02:24 +04:00
|
|
|
sizeof (struct usage_page));
|
|
|
|
}
|
|
|
|
if (!pages)
|
|
|
|
err(1, "alloc");
|
|
|
|
}
|
|
|
|
curpage = &pages[npages++];
|
|
|
|
curpage->name = n;
|
|
|
|
curpage->usage = no;
|
|
|
|
curpage->pagesize = 0;
|
|
|
|
curpage->pagesizemax = 10;
|
1999-07-02 19:46:05 +04:00
|
|
|
curpage->page_contents =
|
|
|
|
malloc(curpage->pagesizemax *
|
1999-05-12 01:02:24 +04:00
|
|
|
sizeof (struct usage_in_page));
|
|
|
|
if (!curpage->page_contents)
|
|
|
|
err(1, "malloc");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fclose(f);
|
|
|
|
#ifdef DEBUG
|
|
|
|
dump_hid_table();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2000-04-02 15:10:53 +04:00
|
|
|
const char *
|
1999-05-12 04:37:43 +04:00
|
|
|
hid_usage_page(int i)
|
1999-05-12 01:02:24 +04:00
|
|
|
{
|
|
|
|
static char b[10];
|
|
|
|
int k;
|
|
|
|
|
|
|
|
if (!pages)
|
2002-07-20 12:36:17 +04:00
|
|
|
errx(1, "no hid table");
|
1999-05-12 01:02:24 +04:00
|
|
|
|
|
|
|
for (k = 0; k < npages; k++)
|
|
|
|
if (pages[k].usage == i)
|
|
|
|
return pages[k].name;
|
2000-08-14 02:22:02 +04:00
|
|
|
sprintf(b, "0x%04x", i);
|
1999-05-12 01:02:24 +04:00
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
2000-04-02 15:10:53 +04:00
|
|
|
const char *
|
1999-05-12 04:37:43 +04:00
|
|
|
hid_usage_in_page(unsigned int u)
|
1999-05-12 01:02:24 +04:00
|
|
|
{
|
|
|
|
int page = HID_PAGE(u);
|
|
|
|
int i = HID_USAGE(u);
|
|
|
|
static char b[100];
|
|
|
|
int j, k, us;
|
|
|
|
|
|
|
|
for (k = 0; k < npages; k++)
|
|
|
|
if (pages[k].usage == page)
|
|
|
|
break;
|
|
|
|
if (k >= npages)
|
|
|
|
goto bad;
|
|
|
|
for (j = 0; j < pages[k].pagesize; j++) {
|
|
|
|
us = pages[k].page_contents[j].usage;
|
|
|
|
if (us == -1) {
|
2000-12-28 04:22:40 +03:00
|
|
|
sprintf(b,
|
|
|
|
fmtcheck(pages[k].page_contents[j].name, "%d"),
|
|
|
|
i);
|
1999-05-12 01:02:24 +04:00
|
|
|
return b;
|
|
|
|
}
|
|
|
|
if (us == i)
|
|
|
|
return pages[k].page_contents[j].name;
|
|
|
|
}
|
|
|
|
bad:
|
2000-08-14 02:22:02 +04:00
|
|
|
sprintf(b, "0x%04x", i);
|
1999-05-12 01:02:24 +04:00
|
|
|
return b;
|
|
|
|
}
|
2000-09-24 06:17:52 +04:00
|
|
|
|
|
|
|
int
|
|
|
|
hid_parse_usage_page(const char *name)
|
|
|
|
{
|
|
|
|
int k;
|
|
|
|
|
|
|
|
if (!pages)
|
2002-07-20 12:36:17 +04:00
|
|
|
errx(1, "no hid table");
|
2000-09-24 06:17:52 +04:00
|
|
|
|
|
|
|
for (k = 0; k < npages; k++)
|
|
|
|
if (strcmp(pages[k].name, name) == 0)
|
|
|
|
return pages[k].usage;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX handle hex */
|
|
|
|
int
|
|
|
|
hid_parse_usage_in_page(const char *name)
|
|
|
|
{
|
2001-01-09 17:29:22 +03:00
|
|
|
const char *sep;
|
2000-09-24 06:17:52 +04:00
|
|
|
int k, j;
|
|
|
|
unsigned int l;
|
|
|
|
|
2001-01-09 17:29:22 +03:00
|
|
|
_DIAGASSERT(name != NULL);
|
|
|
|
|
|
|
|
sep = strchr(name, ':');
|
2000-09-24 06:17:52 +04:00
|
|
|
if (sep == NULL)
|
|
|
|
return -1;
|
|
|
|
l = sep - name;
|
|
|
|
for (k = 0; k < npages; k++)
|
|
|
|
if (strncmp(pages[k].name, name, l) == 0)
|
|
|
|
goto found;
|
|
|
|
return -1;
|
|
|
|
found:
|
|
|
|
sep++;
|
|
|
|
for (j = 0; j < pages[k].pagesize; j++)
|
|
|
|
if (strcmp(pages[k].page_contents[j].name, sep) == 0)
|
|
|
|
return (pages[k].usage << 16) | pages[k].page_contents[j].usage;
|
|
|
|
return (-1);
|
|
|
|
}
|