MFprojects/hid:
- Fix usbhidctl and usbhidaction to handle HID devices with multiple report ids, such as multimedia keyboards. - Add collection type and report id to the `usbhidctl -r` output. They are important for proper device understanding and debugging. - Fix usbhidaction tool to properly handle items having report_count more then 1. Approved by: re (kib) MFC after: 2 weeks
This commit is contained in:
parent
c86c3aa3d9
commit
1bee2ec756
@ -322,6 +322,8 @@ hid_get_item(hid_data_t s, hid_item_t *h)
|
||||
* one and one item:
|
||||
*/
|
||||
c->report_count = 1;
|
||||
c->usage_minimum = 0;
|
||||
c->usage_maximum = 0;
|
||||
} else {
|
||||
s->ncount = 1;
|
||||
}
|
||||
@ -512,13 +514,14 @@ hid_report_size(report_desc_t r, enum hid_kind k, int id)
|
||||
uint32_t temp;
|
||||
uint32_t hpos;
|
||||
uint32_t lpos;
|
||||
int report_id = 0;
|
||||
|
||||
hpos = 0;
|
||||
lpos = 0xFFFFFFFF;
|
||||
|
||||
memset(&h, 0, sizeof h);
|
||||
for (d = hid_start_parse(r, 1 << k, id); hid_get_item(d, &h); ) {
|
||||
if (h.report_ID == id && h.kind == k) {
|
||||
if ((h.report_ID == id || id < 0) && h.kind == k) {
|
||||
/* compute minimum */
|
||||
if (lpos > h.pos)
|
||||
lpos = h.pos;
|
||||
@ -527,6 +530,8 @@ hid_report_size(report_desc_t r, enum hid_kind k, int id)
|
||||
/* compute maximum */
|
||||
if (hpos < temp)
|
||||
hpos = temp;
|
||||
if (h.report_ID != 0)
|
||||
report_id = 1;
|
||||
}
|
||||
}
|
||||
hid_end_parse(d);
|
||||
@ -537,11 +542,8 @@ hid_report_size(report_desc_t r, enum hid_kind k, int id)
|
||||
else
|
||||
temp = hpos - lpos;
|
||||
|
||||
if (id)
|
||||
temp += 8;
|
||||
|
||||
/* return length in bytes rounded up */
|
||||
return ((temp + 7) / 8);
|
||||
return ((temp + 7) / 8 + report_id);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -92,12 +92,12 @@ main(int argc, char **argv)
|
||||
char buf[100];
|
||||
char devnamebuf[PATH_MAX];
|
||||
struct command *cmd;
|
||||
int reportid;
|
||||
int reportid = -1;
|
||||
|
||||
demon = 1;
|
||||
ignore = 0;
|
||||
dieearly = 0;
|
||||
while ((ch = getopt(argc, argv, "c:def:ip:t:v")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "c:def:ip:r:t:v")) != -1) {
|
||||
switch(ch) {
|
||||
case 'c':
|
||||
conf = optarg;
|
||||
@ -117,6 +117,9 @@ main(int argc, char **argv)
|
||||
case 'p':
|
||||
pidfile = optarg;
|
||||
break;
|
||||
case 'r':
|
||||
reportid = atoi(optarg);
|
||||
break;
|
||||
case 't':
|
||||
table = optarg;
|
||||
break;
|
||||
@ -146,14 +149,13 @@ main(int argc, char **argv)
|
||||
fd = open(dev, O_RDWR);
|
||||
if (fd < 0)
|
||||
err(1, "%s", dev);
|
||||
reportid = hid_get_report_id(fd);
|
||||
repd = hid_get_report_desc(fd);
|
||||
if (repd == NULL)
|
||||
err(1, "hid_get_report_desc() failed");
|
||||
|
||||
commands = parse_conf(conf, repd, reportid, ignore);
|
||||
|
||||
sz = (size_t)hid_report_size(repd, hid_input, reportid);
|
||||
sz = (size_t)hid_report_size(repd, hid_input, -1);
|
||||
|
||||
if (verbose)
|
||||
printf("report size %zu\n", sz);
|
||||
@ -198,7 +200,23 @@ main(int argc, char **argv)
|
||||
}
|
||||
#endif
|
||||
for (cmd = commands; cmd; cmd = cmd->next) {
|
||||
val = hid_get_data(buf, &cmd->item);
|
||||
if (cmd->item.report_ID != 0 &&
|
||||
buf[0] != cmd->item.report_ID)
|
||||
continue;
|
||||
if (cmd->item.flags & HIO_VARIABLE)
|
||||
val = hid_get_data(buf, &cmd->item);
|
||||
else {
|
||||
uint32_t pos = cmd->item.pos;
|
||||
for (i = 0; i < cmd->item.report_count; i++) {
|
||||
val = hid_get_data(buf, &cmd->item);
|
||||
if (val == cmd->value)
|
||||
break;
|
||||
cmd->item.pos += cmd->item.report_size;
|
||||
}
|
||||
cmd->item.pos = pos;
|
||||
val = (i < cmd->item.report_count) ?
|
||||
cmd->value : -1;
|
||||
}
|
||||
if (cmd->value != val && cmd->anyvalue == 0)
|
||||
goto next;
|
||||
if ((cmd->debounce == 0) ||
|
||||
|
@ -46,7 +46,6 @@ int verbose = 0;
|
||||
int all = 0;
|
||||
int noname = 0;
|
||||
int hexdump = 0;
|
||||
static int reportid;
|
||||
|
||||
char **names;
|
||||
int nnames;
|
||||
@ -101,11 +100,12 @@ dumpitem(const char *label, struct hid_item *h)
|
||||
{
|
||||
if ((h->flags & HIO_CONST) && !verbose)
|
||||
return;
|
||||
printf("%s size=%d count=%d page=%s usage=%s%s", label,
|
||||
h->report_size, h->report_count,
|
||||
printf("%s rid=%d size=%d count=%d page=%s usage=%s%s%s", label,
|
||||
h->report_ID, h->report_size, h->report_count,
|
||||
hid_usage_page(HID_PAGE(h->usage)),
|
||||
hid_usage_in_page(h->usage),
|
||||
h->flags & HIO_CONST ? " Const" : "");
|
||||
h->flags & HIO_CONST ? " Const" : "",
|
||||
h->flags & HIO_VARIABLE ? "" : " Array");
|
||||
printf(", logical range %d..%d",
|
||||
h->logical_minimum, h->logical_maximum);
|
||||
if (h->physical_minimum != h->physical_maximum)
|
||||
@ -116,6 +116,24 @@ dumpitem(const char *label, struct hid_item *h)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static const char *
|
||||
hid_collection_type(int32_t type)
|
||||
{
|
||||
static char num[8];
|
||||
|
||||
switch (type) {
|
||||
case 0: return ("Physical");
|
||||
case 1: return ("Application");
|
||||
case 2: return ("Logical");
|
||||
case 3: return ("Report");
|
||||
case 4: return ("Named_Array");
|
||||
case 5: return ("Usage_Switch");
|
||||
case 6: return ("Usage_Modifier");
|
||||
}
|
||||
snprintf(num, sizeof(num), "0x%02x", type);
|
||||
return (num);
|
||||
}
|
||||
|
||||
void
|
||||
dumpitems(report_desc_t r)
|
||||
{
|
||||
@ -123,10 +141,11 @@ dumpitems(report_desc_t r)
|
||||
struct hid_item h;
|
||||
int size;
|
||||
|
||||
for (d = hid_start_parse(r, ~0, reportid); hid_get_item(d, &h); ) {
|
||||
for (d = hid_start_parse(r, ~0, -1); hid_get_item(d, &h); ) {
|
||||
switch (h.kind) {
|
||||
case hid_collection:
|
||||
printf("Collection page=%s usage=%s\n",
|
||||
printf("Collection type=%s page=%s usage=%s\n",
|
||||
hid_collection_type(h.collection),
|
||||
hid_usage_page(HID_PAGE(h.usage)),
|
||||
hid_usage_in_page(h.usage));
|
||||
break;
|
||||
@ -145,13 +164,13 @@ dumpitems(report_desc_t r)
|
||||
}
|
||||
}
|
||||
hid_end_parse(d);
|
||||
size = hid_report_size(r, hid_input, 0);
|
||||
size = hid_report_size(r, hid_input, -1);
|
||||
printf("Total input size %d bytes\n", size);
|
||||
|
||||
size = hid_report_size(r, hid_output, 0);
|
||||
size = hid_report_size(r, hid_output, -1);
|
||||
printf("Total output size %d bytes\n", size);
|
||||
|
||||
size = hid_report_size(r, hid_feature, 0);
|
||||
size = hid_report_size(r, hid_feature, -1);
|
||||
printf("Total feature size %d bytes\n", size);
|
||||
}
|
||||
|
||||
@ -180,14 +199,17 @@ prdata(u_char *buf, struct hid_item *h)
|
||||
pos = h->pos;
|
||||
for (i = 0; i < h->report_count; i++) {
|
||||
data = hid_get_data(buf, h);
|
||||
if (i > 0)
|
||||
printf(" ");
|
||||
if (h->logical_minimum < 0)
|
||||
printf("%d", (int)data);
|
||||
else
|
||||
printf("%u", data);
|
||||
if (hexdump)
|
||||
printf(" [0x%x]", data);
|
||||
pos += h->report_size;
|
||||
h->pos += h->report_size;
|
||||
}
|
||||
h->pos = pos;
|
||||
}
|
||||
|
||||
void
|
||||
@ -202,7 +224,7 @@ dumpdata(int f, report_desc_t rd, int loop)
|
||||
char namebuf[10000], *namep;
|
||||
|
||||
hids = 0;
|
||||
for (d = hid_start_parse(rd, 1<<hid_input, reportid);
|
||||
for (d = hid_start_parse(rd, 1<<hid_input, -1);
|
||||
hid_get_item(d, &h); ) {
|
||||
if (h.kind == hid_collection)
|
||||
colls[++sp] = h.usage;
|
||||
@ -217,7 +239,7 @@ dumpdata(int f, report_desc_t rd, int loop)
|
||||
}
|
||||
hid_end_parse(d);
|
||||
rev(&hids);
|
||||
dlen = hid_report_size(rd, hid_input, 0);
|
||||
dlen = hid_report_size(rd, hid_input, -1);
|
||||
dbuf = malloc(dlen);
|
||||
if (!loop)
|
||||
if (hid_set_immed(f, 1) < 0) {
|
||||
@ -228,10 +250,12 @@ dumpdata(int f, report_desc_t rd, int loop)
|
||||
}
|
||||
do {
|
||||
r = read(f, dbuf, dlen);
|
||||
if (r != dlen) {
|
||||
err(1, "bad read %d != %d", r, dlen);
|
||||
if (r < 1) {
|
||||
err(1, "read error");
|
||||
}
|
||||
for (n = hids; n; n = n->next) {
|
||||
if (n->report_ID != 0 && dbuf[0] != n->report_ID)
|
||||
continue;
|
||||
namep = namebuf;
|
||||
namep += sprintf(namep, "%s:%s.",
|
||||
hid_usage_page(HID_PAGE(n->collection)),
|
||||
@ -242,7 +266,7 @@ dumpdata(int f, report_desc_t rd, int loop)
|
||||
if (all || gotname(namebuf)) {
|
||||
if (!noname)
|
||||
printf("%s=", namebuf);
|
||||
prdata(dbuf + (reportid != 0), n);
|
||||
prdata(dbuf, n);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user