167217Sn_hibma/*	$NetBSD: usage.c,v 1.8 2000/10/10 19:23:58 is Exp $	*/
261560Sn_hibma
361560Sn_hibma/*
461560Sn_hibma * Copyright (c) 1999 Lennart Augustsson <augustss@netbsd.org>
561560Sn_hibma * All rights reserved.
661560Sn_hibma *
761560Sn_hibma * Redistribution and use in source and binary forms, with or without
861560Sn_hibma * modification, are permitted provided that the following conditions
961560Sn_hibma * are met:
1061560Sn_hibma * 1. Redistributions of source code must retain the above copyright
1161560Sn_hibma *    notice, this list of conditions and the following disclaimer.
1261560Sn_hibma * 2. Redistributions in binary form must reproduce the above copyright
1361560Sn_hibma *    notice, this list of conditions and the following disclaimer in the
1461560Sn_hibma *    documentation and/or other materials provided with the distribution.
1561560Sn_hibma *
1661560Sn_hibma * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1761560Sn_hibma * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1861560Sn_hibma * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1961560Sn_hibma * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2061560Sn_hibma * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2161560Sn_hibma * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2261560Sn_hibma * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2361560Sn_hibma * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2461560Sn_hibma * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2561560Sn_hibma * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2661560Sn_hibma * SUCH DAMAGE.
2761560Sn_hibma */
2861560Sn_hibma
2984224Sdillon#include <sys/cdefs.h>
3084224Sdillon__FBSDID("$FreeBSD$");
3184224Sdillon
32205728Skaiw#include <sys/param.h>
33113273Smdodd#include <assert.h>
3461560Sn_hibma#include <ctype.h>
3561560Sn_hibma#include <err.h>
3661560Sn_hibma#include <stdio.h>
3761560Sn_hibma#include <stdlib.h>
3861560Sn_hibma#include <string.h>
3961560Sn_hibma
40113273Smdodd#include "usbhid.h"
4161560Sn_hibma
4261560Sn_hibma#define _PATH_HIDTABLE "/usr/share/misc/usb_hid_usages"
4361560Sn_hibma
4461560Sn_hibmastruct usage_in_page {
4561560Sn_hibma	const char *name;
4661560Sn_hibma	int usage;
4761560Sn_hibma};
4861560Sn_hibma
4961560Sn_hibmastatic struct usage_page {
5061560Sn_hibma	const char *name;
5161560Sn_hibma	int usage;
5261560Sn_hibma	struct usage_in_page *page_contents;
5361560Sn_hibma	int pagesize, pagesizemax;
5461560Sn_hibma} *pages;
5561560Sn_hibmastatic int npages, npagesmax;
5661560Sn_hibma
5761560Sn_hibma#ifdef DEBUG
5861560Sn_hibmavoid
5961560Sn_hibmadump_hid_table(void)
6061560Sn_hibma{
6161560Sn_hibma	int i, j;
6261560Sn_hibma
6361560Sn_hibma	for (i = 0; i < npages; i++) {
6461560Sn_hibma		printf("%d\t%s\n", pages[i].usage, pages[i].name);
6561560Sn_hibma		for (j = 0; j < pages[i].pagesize; j++) {
6661560Sn_hibma			printf("\t%d\t%s\n", pages[i].page_contents[j].usage,
6761560Sn_hibma			       pages[i].page_contents[j].name);
6861560Sn_hibma		}
6961560Sn_hibma	}
7061560Sn_hibma}
7161560Sn_hibma#endif
7261560Sn_hibma
7361560Sn_hibmavoid
7461560Sn_hibmahid_init(const char *hidname)
7561560Sn_hibma{
7661560Sn_hibma	FILE *f;
7761560Sn_hibma	char line[100], name[100], *p, *n;
7861560Sn_hibma	int no;
7961560Sn_hibma	int lineno;
8061560Sn_hibma	struct usage_page *curpage = 0;
8161560Sn_hibma
8261560Sn_hibma	if (hidname == 0)
8361560Sn_hibma		hidname = _PATH_HIDTABLE;
8461560Sn_hibma
8561560Sn_hibma	f = fopen(hidname, "r");
8661560Sn_hibma	if (f == NULL)
8761560Sn_hibma		err(1, "%s", hidname);
8861560Sn_hibma	for (lineno = 1; ; lineno++) {
8961560Sn_hibma		if (fgets(line, sizeof line, f) == NULL)
9061560Sn_hibma			break;
9161560Sn_hibma		if (line[0] == '#')
9261560Sn_hibma			continue;
9361560Sn_hibma		for (p = line; *p && isspace(*p); p++)
9461560Sn_hibma			;
9561560Sn_hibma		if (!*p)
9661560Sn_hibma			continue;
9761560Sn_hibma		if (sscanf(line, " * %[^\n]", name) == 1)
9861560Sn_hibma			no = -1;
9961560Sn_hibma		else if (sscanf(line, " 0x%x %[^\n]", &no, name) != 2 &&
10061560Sn_hibma			 sscanf(line, " %d %[^\n]", &no, name) != 2)
101113193Smdodd			errx(1, "file %s, line %d, syntax error",
10261560Sn_hibma			     hidname, lineno);
10361560Sn_hibma		for (p = name; *p; p++)
10461560Sn_hibma			if (isspace(*p) || *p == '.')
10561560Sn_hibma				*p = '_';
10661560Sn_hibma		n = strdup(name);
10761560Sn_hibma		if (!n)
10861560Sn_hibma			err(1, "strdup");
10961560Sn_hibma		if (isspace(line[0])) {
11061560Sn_hibma			if (!curpage)
111113193Smdodd				errx(1, "file %s, line %d, syntax error",
11261560Sn_hibma				     hidname, lineno);
11361560Sn_hibma			if (curpage->pagesize >= curpage->pagesizemax) {
11461560Sn_hibma				curpage->pagesizemax += 10;
11561560Sn_hibma				curpage->page_contents =
11661560Sn_hibma					realloc(curpage->page_contents,
11761560Sn_hibma						curpage->pagesizemax *
11861560Sn_hibma						sizeof (struct usage_in_page));
11961560Sn_hibma				if (!curpage->page_contents)
12061560Sn_hibma					err(1, "realloc");
12161560Sn_hibma			}
12261560Sn_hibma			curpage->page_contents[curpage->pagesize].name = n;
12361560Sn_hibma			curpage->page_contents[curpage->pagesize].usage = no;
12461560Sn_hibma			curpage->pagesize++;
12561560Sn_hibma		} else {
12661560Sn_hibma			if (npages >= npagesmax) {
12761560Sn_hibma				if (pages == 0) {
12861560Sn_hibma					npagesmax = 5;
12961560Sn_hibma					pages = malloc(npagesmax *
13061560Sn_hibma						  sizeof (struct usage_page));
13161560Sn_hibma				} else {
13261560Sn_hibma					npagesmax += 5;
13361560Sn_hibma					pages = realloc(pages,
13461560Sn_hibma						   npagesmax *
13561560Sn_hibma						   sizeof (struct usage_page));
13661560Sn_hibma				}
13761560Sn_hibma				if (!pages)
13861560Sn_hibma					err(1, "alloc");
13961560Sn_hibma			}
14061560Sn_hibma			curpage = &pages[npages++];
14161560Sn_hibma			curpage->name = n;
14261560Sn_hibma			curpage->usage = no;
14361560Sn_hibma			curpage->pagesize = 0;
14461560Sn_hibma			curpage->pagesizemax = 10;
14561560Sn_hibma			curpage->page_contents =
14661560Sn_hibma				malloc(curpage->pagesizemax *
14761560Sn_hibma				       sizeof (struct usage_in_page));
14861560Sn_hibma			if (!curpage->page_contents)
14961560Sn_hibma				err(1, "malloc");
15061560Sn_hibma		}
15161560Sn_hibma	}
15261560Sn_hibma	fclose(f);
15361560Sn_hibma#ifdef DEBUG
15461560Sn_hibma	dump_hid_table();
15561560Sn_hibma#endif
15661560Sn_hibma}
15761560Sn_hibma
15861560Sn_hibmaconst char *
15961560Sn_hibmahid_usage_page(int i)
16061560Sn_hibma{
16161560Sn_hibma	static char b[10];
16261560Sn_hibma	int k;
16361560Sn_hibma
16461560Sn_hibma	if (!pages)
165113193Smdodd		errx(1, "no hid table");
16661560Sn_hibma
16761560Sn_hibma	for (k = 0; k < npages; k++)
16861560Sn_hibma		if (pages[k].usage == i)
16961560Sn_hibma			return pages[k].name;
17065116Sn_hibma	sprintf(b, "0x%04x", i);
17161560Sn_hibma	return b;
17261560Sn_hibma}
17361560Sn_hibma
17461560Sn_hibmaconst char *
17561560Sn_hibmahid_usage_in_page(unsigned int u)
17661560Sn_hibma{
17761560Sn_hibma	int page = HID_PAGE(u);
17861560Sn_hibma	int i = HID_USAGE(u);
17961560Sn_hibma	static char b[100];
18061560Sn_hibma	int j, k, us;
18161560Sn_hibma
18261560Sn_hibma	for (k = 0; k < npages; k++)
18361560Sn_hibma		if (pages[k].usage == page)
18461560Sn_hibma			break;
18561560Sn_hibma	if (k >= npages)
18661560Sn_hibma		goto bad;
18761560Sn_hibma	for (j = 0; j < pages[k].pagesize; j++) {
18861560Sn_hibma		us = pages[k].page_contents[j].usage;
18961560Sn_hibma		if (us == -1) {
190113193Smdodd			sprintf(b,
191113193Smdodd			    fmtcheck(pages[k].page_contents[j].name, "%d"),
192113193Smdodd			    i);
19361560Sn_hibma			return b;
19461560Sn_hibma		}
19561560Sn_hibma		if (us == i)
19661560Sn_hibma			return pages[k].page_contents[j].name;
19761560Sn_hibma	}
19861560Sn_hibma bad:
19965116Sn_hibma	sprintf(b, "0x%04x", i);
20061560Sn_hibma	return b;
20161560Sn_hibma}
20267217Sn_hibma
20367217Sn_hibmaint
20467217Sn_hibmahid_parse_usage_page(const char *name)
20567217Sn_hibma{
20667217Sn_hibma	int k;
20767217Sn_hibma
20867217Sn_hibma	if (!pages)
209113193Smdodd		errx(1, "no hid table");
21067217Sn_hibma
21167217Sn_hibma	for (k = 0; k < npages; k++)
21267217Sn_hibma		if (strcmp(pages[k].name, name) == 0)
21367217Sn_hibma			return pages[k].usage;
21467217Sn_hibma	return -1;
21567217Sn_hibma}
21667217Sn_hibma
21767217Sn_hibma/* XXX handle hex */
21867217Sn_hibmaint
21967217Sn_hibmahid_parse_usage_in_page(const char *name)
22067217Sn_hibma{
221113193Smdodd	const char *sep;
22267217Sn_hibma	int k, j;
22367217Sn_hibma	unsigned int l;
22467217Sn_hibma
225113193Smdodd	sep = strchr(name, ':');
22667217Sn_hibma	if (sep == NULL)
22767217Sn_hibma		return -1;
22867217Sn_hibma	l = sep - name;
22967217Sn_hibma	for (k = 0; k < npages; k++)
23067217Sn_hibma		if (strncmp(pages[k].name, name, l) == 0)
23167217Sn_hibma			goto found;
23267217Sn_hibma	return -1;
23367217Sn_hibma found:
23467217Sn_hibma	sep++;
23567217Sn_hibma	for (j = 0; j < pages[k].pagesize; j++)
23667217Sn_hibma		if (strcmp(pages[k].page_contents[j].name, sep) == 0)
23767217Sn_hibma			return (pages[k].usage << 16) | pages[k].page_contents[j].usage;
23867217Sn_hibma	return (-1);
23967217Sn_hibma}
240