xref: /dflybsd-src/lib/libu4bhid/usage.c (revision 75d796ba91a5113779666919834b3cf2d51050fb)
112bd3c8bSSascha Wildner /*	$NetBSD: usage.c,v 1.8 2000/10/10 19:23:58 is Exp $	*/
212bd3c8bSSascha Wildner 
312bd3c8bSSascha Wildner /*
412bd3c8bSSascha Wildner  * Copyright (c) 1999 Lennart Augustsson <augustss@netbsd.org>
512bd3c8bSSascha Wildner  * All rights reserved.
612bd3c8bSSascha Wildner  *
712bd3c8bSSascha Wildner  * Redistribution and use in source and binary forms, with or without
812bd3c8bSSascha Wildner  * modification, are permitted provided that the following conditions
912bd3c8bSSascha Wildner  * are met:
1012bd3c8bSSascha Wildner  * 1. Redistributions of source code must retain the above copyright
1112bd3c8bSSascha Wildner  *    notice, this list of conditions and the following disclaimer.
1212bd3c8bSSascha Wildner  * 2. Redistributions in binary form must reproduce the above copyright
1312bd3c8bSSascha Wildner  *    notice, this list of conditions and the following disclaimer in the
1412bd3c8bSSascha Wildner  *    documentation and/or other materials provided with the distribution.
1512bd3c8bSSascha Wildner  *
1612bd3c8bSSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1712bd3c8bSSascha Wildner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1812bd3c8bSSascha Wildner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1912bd3c8bSSascha Wildner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2012bd3c8bSSascha Wildner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2112bd3c8bSSascha Wildner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2212bd3c8bSSascha Wildner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2312bd3c8bSSascha Wildner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2412bd3c8bSSascha Wildner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2512bd3c8bSSascha Wildner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2612bd3c8bSSascha Wildner  * SUCH DAMAGE.
27ee284e10SSascha Wildner  *
28ee284e10SSascha Wildner  * $FreeBSD: head/lib/libusbhid/usage.c 205728 2010-03-27 08:00:16Z kaiw $
2912bd3c8bSSascha Wildner  */
3012bd3c8bSSascha Wildner 
3112bd3c8bSSascha Wildner #include <sys/param.h>
3212bd3c8bSSascha Wildner #include <assert.h>
3312bd3c8bSSascha Wildner #include <ctype.h>
3412bd3c8bSSascha Wildner #include <err.h>
3512bd3c8bSSascha Wildner #include <stdio.h>
3612bd3c8bSSascha Wildner #include <stdlib.h>
3712bd3c8bSSascha Wildner #include <string.h>
3812bd3c8bSSascha Wildner 
3912bd3c8bSSascha Wildner #include "usbhid.h"
4012bd3c8bSSascha Wildner 
4112bd3c8bSSascha Wildner #define _PATH_HIDTABLE "/usr/share/misc/usb_hid_usages"
4212bd3c8bSSascha Wildner 
4312bd3c8bSSascha Wildner struct usage_in_page {
4412bd3c8bSSascha Wildner 	const char *name;
4512bd3c8bSSascha Wildner 	int usage;
4612bd3c8bSSascha Wildner };
4712bd3c8bSSascha Wildner 
4812bd3c8bSSascha Wildner static struct usage_page {
4912bd3c8bSSascha Wildner 	const char *name;
5012bd3c8bSSascha Wildner 	int usage;
5112bd3c8bSSascha Wildner 	struct usage_in_page *page_contents;
5212bd3c8bSSascha Wildner 	int pagesize, pagesizemax;
5312bd3c8bSSascha Wildner } *pages;
5412bd3c8bSSascha Wildner static int npages, npagesmax;
5512bd3c8bSSascha Wildner 
5612bd3c8bSSascha Wildner #ifdef DEBUG
5712bd3c8bSSascha Wildner void
dump_hid_table(void)5812bd3c8bSSascha Wildner dump_hid_table(void)
5912bd3c8bSSascha Wildner {
6012bd3c8bSSascha Wildner 	int i, j;
6112bd3c8bSSascha Wildner 
6212bd3c8bSSascha Wildner 	for (i = 0; i < npages; i++) {
6312bd3c8bSSascha Wildner 		printf("%d\t%s\n", pages[i].usage, pages[i].name);
6412bd3c8bSSascha Wildner 		for (j = 0; j < pages[i].pagesize; j++) {
6512bd3c8bSSascha Wildner 			printf("\t%d\t%s\n", pages[i].page_contents[j].usage,
6612bd3c8bSSascha Wildner 			       pages[i].page_contents[j].name);
6712bd3c8bSSascha Wildner 		}
6812bd3c8bSSascha Wildner 	}
6912bd3c8bSSascha Wildner }
7012bd3c8bSSascha Wildner #endif
7112bd3c8bSSascha Wildner 
7212bd3c8bSSascha Wildner void
hid_init(const char * hidname)7312bd3c8bSSascha Wildner hid_init(const char *hidname)
7412bd3c8bSSascha Wildner {
7512bd3c8bSSascha Wildner 	FILE *f;
7612bd3c8bSSascha Wildner 	char line[100], name[100], *p, *n;
7712bd3c8bSSascha Wildner 	int no;
7812bd3c8bSSascha Wildner 	int lineno;
79*75d796baSSascha Wildner 	struct usage_page *curpage = NULL;
8012bd3c8bSSascha Wildner 
81*75d796baSSascha Wildner 	if (hidname == NULL)
8212bd3c8bSSascha Wildner 		hidname = _PATH_HIDTABLE;
8312bd3c8bSSascha Wildner 
8412bd3c8bSSascha Wildner 	f = fopen(hidname, "r");
8512bd3c8bSSascha Wildner 	if (f == NULL)
8612bd3c8bSSascha Wildner 		err(1, "%s", hidname);
8712bd3c8bSSascha Wildner 	for (lineno = 1; ; lineno++) {
8812bd3c8bSSascha Wildner 		if (fgets(line, sizeof line, f) == NULL)
8912bd3c8bSSascha Wildner 			break;
9012bd3c8bSSascha Wildner 		if (line[0] == '#')
9112bd3c8bSSascha Wildner 			continue;
9212bd3c8bSSascha Wildner 		for (p = line; *p && isspace(*p); p++)
9312bd3c8bSSascha Wildner 			;
9412bd3c8bSSascha Wildner 		if (!*p)
9512bd3c8bSSascha Wildner 			continue;
9612bd3c8bSSascha Wildner 		if (sscanf(line, " * %[^\n]", name) == 1)
9712bd3c8bSSascha Wildner 			no = -1;
9812bd3c8bSSascha Wildner 		else if (sscanf(line, " 0x%x %[^\n]", &no, name) != 2 &&
9912bd3c8bSSascha Wildner 			 sscanf(line, " %d %[^\n]", &no, name) != 2)
10012bd3c8bSSascha Wildner 			errx(1, "file %s, line %d, syntax error",
10112bd3c8bSSascha Wildner 			     hidname, lineno);
10212bd3c8bSSascha Wildner 		for (p = name; *p; p++)
10312bd3c8bSSascha Wildner 			if (isspace(*p) || *p == '.')
10412bd3c8bSSascha Wildner 				*p = '_';
10512bd3c8bSSascha Wildner 		n = strdup(name);
10612bd3c8bSSascha Wildner 		if (!n)
10712bd3c8bSSascha Wildner 			err(1, "strdup");
10812bd3c8bSSascha Wildner 		if (isspace(line[0])) {
10912bd3c8bSSascha Wildner 			if (!curpage)
11012bd3c8bSSascha Wildner 				errx(1, "file %s, line %d, syntax error",
11112bd3c8bSSascha Wildner 				     hidname, lineno);
11212bd3c8bSSascha Wildner 			if (curpage->pagesize >= curpage->pagesizemax) {
11312bd3c8bSSascha Wildner 				curpage->pagesizemax += 10;
11412bd3c8bSSascha Wildner 				curpage->page_contents =
11512bd3c8bSSascha Wildner 					realloc(curpage->page_contents,
11612bd3c8bSSascha Wildner 						curpage->pagesizemax *
11712bd3c8bSSascha Wildner 						sizeof (struct usage_in_page));
11812bd3c8bSSascha Wildner 				if (!curpage->page_contents)
11912bd3c8bSSascha Wildner 					err(1, "realloc");
12012bd3c8bSSascha Wildner 			}
12112bd3c8bSSascha Wildner 			curpage->page_contents[curpage->pagesize].name = n;
12212bd3c8bSSascha Wildner 			curpage->page_contents[curpage->pagesize].usage = no;
12312bd3c8bSSascha Wildner 			curpage->pagesize++;
12412bd3c8bSSascha Wildner 		} else {
12512bd3c8bSSascha Wildner 			if (npages >= npagesmax) {
126*75d796baSSascha Wildner 				if (pages == NULL) {
12712bd3c8bSSascha Wildner 					npagesmax = 5;
12812bd3c8bSSascha Wildner 					pages = malloc(npagesmax *
12912bd3c8bSSascha Wildner 						  sizeof (struct usage_page));
13012bd3c8bSSascha Wildner 				} else {
13112bd3c8bSSascha Wildner 					npagesmax += 5;
13212bd3c8bSSascha Wildner 					pages = realloc(pages,
13312bd3c8bSSascha Wildner 						   npagesmax *
13412bd3c8bSSascha Wildner 						   sizeof (struct usage_page));
13512bd3c8bSSascha Wildner 				}
13612bd3c8bSSascha Wildner 				if (!pages)
13712bd3c8bSSascha Wildner 					err(1, "alloc");
13812bd3c8bSSascha Wildner 			}
13912bd3c8bSSascha Wildner 			curpage = &pages[npages++];
14012bd3c8bSSascha Wildner 			curpage->name = n;
14112bd3c8bSSascha Wildner 			curpage->usage = no;
14212bd3c8bSSascha Wildner 			curpage->pagesize = 0;
14312bd3c8bSSascha Wildner 			curpage->pagesizemax = 10;
14412bd3c8bSSascha Wildner 			curpage->page_contents =
14512bd3c8bSSascha Wildner 				malloc(curpage->pagesizemax *
14612bd3c8bSSascha Wildner 				       sizeof (struct usage_in_page));
14712bd3c8bSSascha Wildner 			if (!curpage->page_contents)
14812bd3c8bSSascha Wildner 				err(1, "malloc");
14912bd3c8bSSascha Wildner 		}
15012bd3c8bSSascha Wildner 	}
15112bd3c8bSSascha Wildner 	fclose(f);
15212bd3c8bSSascha Wildner #ifdef DEBUG
15312bd3c8bSSascha Wildner 	dump_hid_table();
15412bd3c8bSSascha Wildner #endif
15512bd3c8bSSascha Wildner }
15612bd3c8bSSascha Wildner 
15712bd3c8bSSascha Wildner const char *
hid_usage_page(int i)15812bd3c8bSSascha Wildner hid_usage_page(int i)
15912bd3c8bSSascha Wildner {
16012bd3c8bSSascha Wildner 	static char b[10];
16112bd3c8bSSascha Wildner 	int k;
16212bd3c8bSSascha Wildner 
16312bd3c8bSSascha Wildner 	if (!pages)
16412bd3c8bSSascha Wildner 		errx(1, "no hid table");
16512bd3c8bSSascha Wildner 
16612bd3c8bSSascha Wildner 	for (k = 0; k < npages; k++)
16712bd3c8bSSascha Wildner 		if (pages[k].usage == i)
16812bd3c8bSSascha Wildner 			return pages[k].name;
16912bd3c8bSSascha Wildner 	sprintf(b, "0x%04x", i);
17012bd3c8bSSascha Wildner 	return b;
17112bd3c8bSSascha Wildner }
17212bd3c8bSSascha Wildner 
17312bd3c8bSSascha Wildner const char *
hid_usage_in_page(unsigned int u)17412bd3c8bSSascha Wildner hid_usage_in_page(unsigned int u)
17512bd3c8bSSascha Wildner {
17612bd3c8bSSascha Wildner 	int page = HID_PAGE(u);
17712bd3c8bSSascha Wildner 	int i = HID_USAGE(u);
17812bd3c8bSSascha Wildner 	static char b[100];
17912bd3c8bSSascha Wildner 	int j, k, us;
18012bd3c8bSSascha Wildner 
18112bd3c8bSSascha Wildner 	for (k = 0; k < npages; k++)
18212bd3c8bSSascha Wildner 		if (pages[k].usage == page)
18312bd3c8bSSascha Wildner 			break;
18412bd3c8bSSascha Wildner 	if (k >= npages)
18512bd3c8bSSascha Wildner 		goto bad;
18612bd3c8bSSascha Wildner 	for (j = 0; j < pages[k].pagesize; j++) {
18712bd3c8bSSascha Wildner 		us = pages[k].page_contents[j].usage;
18812bd3c8bSSascha Wildner 		if (us == -1) {
18912bd3c8bSSascha Wildner 			sprintf(b,
19012bd3c8bSSascha Wildner 			    fmtcheck(pages[k].page_contents[j].name, "%d"),
19112bd3c8bSSascha Wildner 			    i);
19212bd3c8bSSascha Wildner 			return b;
19312bd3c8bSSascha Wildner 		}
19412bd3c8bSSascha Wildner 		if (us == i)
19512bd3c8bSSascha Wildner 			return pages[k].page_contents[j].name;
19612bd3c8bSSascha Wildner 	}
19712bd3c8bSSascha Wildner  bad:
19812bd3c8bSSascha Wildner 	sprintf(b, "0x%04x", i);
19912bd3c8bSSascha Wildner 	return b;
20012bd3c8bSSascha Wildner }
20112bd3c8bSSascha Wildner 
20212bd3c8bSSascha Wildner int
hid_parse_usage_page(const char * name)20312bd3c8bSSascha Wildner hid_parse_usage_page(const char *name)
20412bd3c8bSSascha Wildner {
20512bd3c8bSSascha Wildner 	int k;
20612bd3c8bSSascha Wildner 
20712bd3c8bSSascha Wildner 	if (!pages)
20812bd3c8bSSascha Wildner 		errx(1, "no hid table");
20912bd3c8bSSascha Wildner 
21012bd3c8bSSascha Wildner 	for (k = 0; k < npages; k++)
21112bd3c8bSSascha Wildner 		if (strcmp(pages[k].name, name) == 0)
21212bd3c8bSSascha Wildner 			return pages[k].usage;
21312bd3c8bSSascha Wildner 	return -1;
21412bd3c8bSSascha Wildner }
21512bd3c8bSSascha Wildner 
21612bd3c8bSSascha Wildner /* XXX handle hex */
21712bd3c8bSSascha Wildner int
hid_parse_usage_in_page(const char * name)21812bd3c8bSSascha Wildner hid_parse_usage_in_page(const char *name)
21912bd3c8bSSascha Wildner {
22012bd3c8bSSascha Wildner 	const char *sep;
22112bd3c8bSSascha Wildner 	int k, j;
22212bd3c8bSSascha Wildner 	unsigned int l;
22312bd3c8bSSascha Wildner 
22412bd3c8bSSascha Wildner 	sep = strchr(name, ':');
22512bd3c8bSSascha Wildner 	if (sep == NULL)
22612bd3c8bSSascha Wildner 		return -1;
22712bd3c8bSSascha Wildner 	l = sep - name;
22812bd3c8bSSascha Wildner 	for (k = 0; k < npages; k++)
22912bd3c8bSSascha Wildner 		if (strncmp(pages[k].name, name, l) == 0)
23012bd3c8bSSascha Wildner 			goto found;
23112bd3c8bSSascha Wildner 	return -1;
23212bd3c8bSSascha Wildner  found:
23312bd3c8bSSascha Wildner 	sep++;
23412bd3c8bSSascha Wildner 	for (j = 0; j < pages[k].pagesize; j++)
23512bd3c8bSSascha Wildner 		if (strcmp(pages[k].page_contents[j].name, sep) == 0)
23612bd3c8bSSascha Wildner 			return (pages[k].usage << 16) | pages[k].page_contents[j].usage;
23712bd3c8bSSascha Wildner 	return (-1);
23812bd3c8bSSascha Wildner }
239