/*-
* Copyright (c) 1999-2003 MAEKAWA Masahide <gehenna@daemon-systems.org>
* Copyright (c) 1999-2000 UCHIYAMA Yasushi
* 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.
* 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.
*
* 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.
*
* $Id: hid.c,v 1.10 2003/01/11 14:46:36 maekawa Exp $
*/
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <unistd.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbhid.h>
#include "main.h"
#include "hid.h"
#include "hiddefs.h"
#include "hiddefs_data.h"
static void hid_report(uint8_t *, size_t);
extern int fd, level;
/*
* Class: Human Interface Devices (HID)
*/
void
hid_device(usb_descriptor_t *desc, int interface)
{
usb_hid_descriptor_t *hdesc = (usb_hid_descriptor_t *)desc;
int n, i;
printf("\t\tHID Descriptor:\n\t\t bLength %d\n"
"\t\t bDescriptorType %02x\n\t\t bcdHID %04x\n"
"\t\t bCountryCode %02x\n\t\t bNumDescriptors %d\n",
hdesc->bLength, hdesc->bDescriptorType, UGETW(hdesc->bcdHID),
hdesc->bCountryCode, hdesc->bNumDescriptors);
n = hdesc->bNumDescriptors;
for (i = 0 ; i < n ; i++) {
uint8_t *buffer;
size_t length;
int j;
printf("\t\t bDescriptorType %02x\n"
"\t\t wDescriptorLength %d\n\n",
hdesc->descrs[i].bDescriptorType,
UGETW(hdesc->descrs[i].wDescriptorLength));
length = UGETW(hdesc->descrs[i].wDescriptorLength);
if ((buffer = (uint8_t *)malloc(length)) == NULL)
err(1, "hid_device");
if (usb_get_descriptor(interface,
hdesc->descrs[i].bDescriptorType, i,
interface, buffer, length) == 0) {
if (hdesc->descrs[i].bDescriptorType == UDESC_REPORT) {
printf("\t\tReport Desctiptor (ID: %d) {\n", i);
hid_report(buffer, length);
printf("\t\t}\n");
} else {
printf("\t\t");
for (j = 0 ; (size_t)j < length ; j++)
printf(" %02x", buffer[j]);
printf("\n");
}
}
free(buffer);
}
printf("\n");
}
void
hid_report(uint8_t *buffer, size_t bufsize)
{
int bSize, bType, bTag, i = 0;
uint8_t *end, item;
const char *name;
for (end = buffer + bufsize ; buffer < end ; /* do nothing */) {
item = *buffer++;
bSize = HID_ITEM_SIZE_GET(HID_ITEM_SIZE(item));
bType = HID_ITEM_TYPE(item);
bTag = HID_ITEM_TAG(item);
if (bTag == HID_ITEM_TAG_LONGITEM) {
fprintf(stderr, "WARNING: long item (reserved for "
"future use.\n");
bSize = *buffer++;
bTag = *buffer++;
}
if ((name = hid_get_item_name(bType, bTag)) != NULL) {
if (bType == HID_ITEM_TYPE_MAIN &&
bTag == HID_MAIN_ITEM_ENDCOLLECTION)
level--;
iprintf("%s", name);
} else {
iprintf("Unknown Item(%01x, %01x): ", bType, bTag);
for (i = 0 ; i < bSize ; i++)
printf("%02x ", buffer[i]);
}
switch (bType) {
case HID_ITEM_TYPE_MAIN:
hid_main_item(bTag, buffer, bSize);
break;
case HID_ITEM_TYPE_GLOBAL:
hid_global_item(bTag, buffer, bSize);
break;
case HID_ITEM_TYPE_LOCAL:
hid_local_item(bTag, buffer, bSize);
break;
}
buffer += bSize; /* next item */
}
}
const char *
hid_get_item_name(uint8_t type, uint8_t tag)
{
struct hid_item *hi;
for (hi = hid_items ; hi->name != NULL ; hi++) {
if (hi->type == type && hi->tag == tag)
break;
}
return (hi->name);
}
const char *
hid_get_collection_name(uint8_t type)
{
struct hid_collection *hc;
if (type >= HID_COLLECTION_VENDOR_START &&
type <= HID_COLLECTION_VENDOR_END)
return ("Vendor-defined");
for (hc = hid_collections ; hc->name != NULL ; hc++) {
if (hc->type == type)
break;
}
return (hc->name);
}
const char *
hid_get_page_name(uint16_t page)
{
struct hid_usage_page *hp;
if (page >= HID_USAGE_PAGE_VENDOR_START &&
page <= HID_USAGE_PAGE_VENDOR_END)
return ("Vendor-defined");
for (hp = hid_usage_pages ; hp->name != NULL ; hp++) {
if (hp->page == page)
break;
}
return (hp->name);
}
const char *
hid_get_usage_name(uint16_t page, uint16_t usage)
{
struct hid_usage *hu;
for (hu = hid_usages ; hu->name != NULL ; hu++) {
if (hu->page == page && hu->usage == usage)
break;
}
return (hu->name);
}
uint32_t
hid_get_usage_type(uint16_t page, uint16_t usage)
{
struct hid_usage *hu;
for (hu = hid_usages ; hu->name != NULL ; hu++) {
if (hu->page == page && hu->usage == usage)
break;
}
return (hu->type);
}
syntax highlighted by Code2HTML, v. 0.9.1