From: R0b0t1 <r030t1@gmail.com>
To: linux-input@vger.kernel.org, linux-usb@vger.kernel.org
Subject: UHID Device Reports Do Not Generate OS Activity
Date: Sat, 10 Feb 2018 03:33:41 -0600 [thread overview]
Message-ID: <CAAD4mYj0pUUbwX8mKDP2qTn=QZM9ubk3f9FsabefK4xntY7bFA@mail.gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 559 bytes --]
Hello,
I am trying to simulate a keyboard using the uhid interface. The fake
device shows up in dmesg, but attempting to press the "a" key does
nothing I can see. No input appears in the active terminal, nor in an
xev window.
The program receives UHID_OPEN, UHID_START, and UHID_CLOSE.
Many different report descriptors were tried. The one currently
uncommented is the one distributed with the USB implementor forum's
HID report descriptor tool. The other is one found in a description of
a boot device compatible keyboard.
Thanks in advance,
R0b0t1
[-- Attachment #2: kbd.c --]
[-- Type: text/x-csrc, Size: 4931 bytes --]
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <sys/ioctl.h>
#include <linux/uhid.h>
#define handle_error(m) \
do { perror(m); exit(EXIT_FAILURE); } while (0)
static unsigned char rdesc[] = {
0x05, 0x01,
0x09, 0x06,
0xa1, 0x01,
0x05, 0x07,
0x19, 0xe0,
0x29, 0xe7,
0x15, 0x00,
0x25, 0x01,
0x75, 0x01,
0x95, 0x08,
0x81, 0x02,
0x95, 0x01,
0x75, 0x08,
0x81, 0x03,
0x95, 0x05,
0x75, 0x01,
0x05, 0x08,
0x19, 0x01,
0x29, 0x05,
0x91, 0x02,
0x95, 0x01,
0x75, 0x03,
0x91, 0x03,
0x95, 0x06,
0x75, 0x08,
0x15, 0x00,
0x25, 0x65,
0x05, 0x07,
0x19, 0x00,
0x29, 0x65,
0x81, 0x00,
0xc0
};
/*
static unsigned char rdesc[] = {
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x06, // Usage (Keyboard)
0xa1, 0x01, // Collection (Application)
// Modifier report.
0x75, 0x01, // Report Size (1)
0x95, 0x08, // Report Count (8)
0x05, 0x07, // Usage Page (Key Codes)
0x19, 0xe0, // Usage Minimum (224)
0x29, 0xe7, // Usage Maximum (231)
0x15, 0x00, // Logical Minimum (0) - Shorten (0x14)?
0x25, 0x01, // Logical Maximum (1)
0x81, 0x02, // Input (Data, Variable, Absolute)
// Reserved byte.
0x95, 0x01, // Report Count (1)
0x75, 0x08, // Report Size (8)
0x81, 0x01, // Input (Constant)
// LED report.
0x95, 0x05, // Report Count (5)
0x75, 0x01, // Report Size (1)
0x05, 0x08, // Usage Page (LEDs)
0x19, 0x01, // Usage Minimum (1)
0x29, 0x05, // Usage Maximum (5)
0x91, 0x02, // Output (Data, Variable, Absolute)
// LED report padding.
0x95, 0x01, // Report Count (1)
0x75, 0x03, // Report Size (3)
0x91, 0x01, // Output (Constant)
// Key code report.
0x95, 0x06, // Report Count (6)
0x75, 0x08, // Report Size (8)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xff, 0x00, // Logical Maximum (255)
0x05, 0x07, // Usage Page (Key Codes)
0x19, 0x00, // Usage Minimum (0)
0x29, 0xff, // Usage Maximum (255)
0x81, 0x00, // Input (Data, Array)
0xc0 // End Collection
};
*/
static int
uhid_write(int fd, const struct uhid_event *he)
{
ssize_t r = write(fd, he, sizeof(*he));
if (r < 0) {
fprintf(stderr, "write: cannot write to uhid: %m\n");
return -errno;
} else if (r != sizeof(*he)) {
fprintf(stderr, "write: wrong size written to uhid: %ld != %lu\n",
r, sizeof(*he));
return -EFAULT;
} else return 0;
}
static int
uhid_event(int fd)
{
struct uhid_event he;
ssize_t sz;
if ((sz = read(fd, &he, sizeof(he))) == -1)
handle_error("read");
switch (he.type) {
case UHID_START:
fprintf(stderr, "UHID_START from uhid-dev.\n");
break;
case UHID_STOP:
fprintf(stderr, "UHID_STOP from uhid-dev.\n");
break;
case UHID_OPEN:
fprintf(stderr, "UHID_OPEN from uhid-dev.\n");
return 0;
case UHID_CLOSE:
fprintf(stderr, "UHID_CLOSE from uhid-dev.\n");
break;
case UHID_OUTPUT:
fprintf(stderr, "UHID_OUTPUT from uhid-dev.\n");
// TODO: Handle output.
break;
case UHID_OUTPUT_EV:
fprintf(stderr, "UHID_OUTPUT_EV from uhid-dev.\n");
break;
default:
fprintf(stderr, "Invalid event from uhid-dev: %u.\n", he.type);
}
return 1;
}
int
main(int argc, char *argv[])
{
int fd;
ssize_t sz;
struct uhid_event he;
if ((fd = open("/dev/uhid", O_RDWR | O_CLOEXEC)) == -1)
handle_error("open");
struct pollfd fds[1] = {
{.fd = fd, .events = POLLIN}
};
memset(&he, 0, sizeof(he));
he.type = UHID_CREATE2;
strcpy((char *)he.u.create.name, "kb-daemon-device");
memcpy(he.u.create2.rd_data, rdesc, sizeof(rdesc));
he.u.create2.rd_size = sizeof(rdesc);
he.u.create2.bus = BUS_USB;
he.u.create2.vendor = 0x15d9;
he.u.create2.product = 0x0a37;
he.u.create2.version = 0;
he.u.create2.country = 0;
if (uhid_write(fd, &he))
handle_error("uhid_write");
char cont = 1;
while (cont) {
int n = ppoll(fds, sizeof(fds), NULL, NULL);
if (n == -1)
handle_error("ppoll");
for (int i = 0; i < n; i++) {
if (fds[i].fd == fd &&
fds[i].revents & POLLIN)
cont = uhid_event(fds[i].fd);
}
}
memset(&he, 0, sizeof(he));
he.type = UHID_INPUT2;
he.u.input2.size = 8;
he.u.input2.data[0] = 0x00;
he.u.input2.data[1] = 0x00;
he.u.input2.data[2] = 0x04;
he.u.input2.data[3] = 0x00;
he.u.input2.data[4] = 0x00;
he.u.input2.data[5] = 0x00;
he.u.input2.data[6] = 0x00;
he.u.input2.data[7] = 0x00;
if (uhid_write(fd, &he))
handle_error("uhid_write");
memset(&he, 0, sizeof(he));
he.type = UHID_INPUT2;
he.u.input2.size = 8;
he.u.input2.data[0] = 0x00;
he.u.input2.data[1] = 0x00;
he.u.input2.data[2] = 0x00;
he.u.input2.data[3] = 0x00;
he.u.input2.data[4] = 0x00;
he.u.input2.data[5] = 0x00;
he.u.input2.data[6] = 0x00;
he.u.input2.data[7] = 0x00;
if (uhid_write(fd, &he))
handle_error("uhid_write");
memset(&he, 0, sizeof(he));
he.type = UHID_DESTROY;
if (uhid_write(fd, &he))
handle_error("uhid_write");
uhid_event(fd);
return EXIT_SUCCESS;
}
next reply other threads:[~2018-02-10 9:33 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-10 9:33 R0b0t1 [this message]
2018-02-11 19:46 ` UHID Device Reports Do Not Generate OS Activity Roderick Colenbrander
[not found] ` <CAEc3jaAyQiNDLbOvNkT65n-Vju-LOHjoSuiOqDunBFna0YDaBQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2018-02-11 20:22 ` R0b0t1
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CAAD4mYj0pUUbwX8mKDP2qTn=QZM9ubk3f9FsabefK4xntY7bFA@mail.gmail.com' \
--to=r030t1@gmail.com \
--cc=linux-input@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).