linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* UHID Device Reports Do Not Generate OS Activity
@ 2018-02-10  9:33 R0b0t1
  2018-02-11 19:46 ` Roderick Colenbrander
  0 siblings, 1 reply; 3+ messages in thread
From: R0b0t1 @ 2018-02-10  9:33 UTC (permalink / raw)
  To: linux-input, linux-usb

[-- 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;
}

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: UHID Device Reports Do Not Generate OS Activity
  2018-02-10  9:33 UHID Device Reports Do Not Generate OS Activity R0b0t1
@ 2018-02-11 19:46 ` Roderick Colenbrander
       [not found]   ` <CAEc3jaAyQiNDLbOvNkT65n-Vju-LOHjoSuiOqDunBFna0YDaBQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 3+ messages in thread
From: Roderick Colenbrander @ 2018-02-11 19:46 UTC (permalink / raw)
  To: R0b0t1; +Cc: linux-input, linux-usb

It is hard to say what is wrong. I would start with reading the uhid /
hid code and see where you are getting stuck (and double check uhid
docs). Even for others we would need to do that as it is not easy to
see what is wrong.

I'm not sure what your goal is obvious you want to simulate a keyboard
for some purpose, but do you really need to operate at the HID layer?
If not it is much more convenient to use uinput, which will create a
evdev device for you.

Thanks,
Roderick

On Sat, Feb 10, 2018 at 1:33 AM, R0b0t1 <r030t1@gmail.com> wrote:
> 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

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: UHID Device Reports Do Not Generate OS Activity
       [not found]   ` <CAEc3jaAyQiNDLbOvNkT65n-Vju-LOHjoSuiOqDunBFna0YDaBQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2018-02-11 20:22     ` R0b0t1
  0 siblings, 0 replies; 3+ messages in thread
From: R0b0t1 @ 2018-02-11 20:22 UTC (permalink / raw)
  To: Roderick Colenbrander; +Cc: linux-input, linux-usb-u79uwXL29TY76Z2rM5mHXA

On Sun, Feb 11, 2018 at 1:46 PM, Roderick Colenbrander
<thunderbird2k-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> It is hard to say what is wrong. I would start with reading the uhid /
> hid code and see where you are getting stuck (and double check uhid
> docs). Even for others we would need to do that as it is not easy to
> see what is wrong.
>

The issue was that the device is not immediately able to give input to
userspace programs after being opened by the kernel.

Waiting 32ms (2 timeslices?) gives a 100% success rate, with 16ms
having a 50% success rate. Checking modern kernel sources timeslices
may no longer be 16ms.

> I'm not sure what your goal is obvious you want to simulate a keyboard
> for some purpose, but do you really need to operate at the HID layer?
> If not it is much more convenient to use uinput, which will create a
> evdev device for you.
>

My kernel was not originally compiled with uinput. I used uhid to
avoid rebooting. (I have since rebooted and ended 199 days of uptime.)

There were other reasons for doing it this way, one of them being that
I am going to be prototyping an HID device. A software model will
help. I also wanted more control of the keystrokes initially to see if
it would be necessary to maintain that control.

It might be best to switch to uinput, but once you have USB
descriptors USB is actually very simple.

Cheers,
     R0b0t1

> Thanks,
> Roderick
>
> On Sat, Feb 10, 2018 at 1:33 AM, R0b0t1 <r030t1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2018-02-11 20:22 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-02-10  9:33 UHID Device Reports Do Not Generate OS Activity R0b0t1
2018-02-11 19:46 ` Roderick Colenbrander
     [not found]   ` <CAEc3jaAyQiNDLbOvNkT65n-Vju-LOHjoSuiOqDunBFna0YDaBQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2018-02-11 20:22     ` R0b0t1

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).