aboutsummaryrefslogtreecommitdiff
path: root/hidptp.c
blob: 9cf9918a951bf22f9e1aa6b5b51547f29581f83d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#include <linux/ioctl.h>
#include <linux/hiddev.h>

static int devfd;

static char *get_device_name()
{
	static char buf[1024];

	if (ioctl(devfd, HIDIOCGNAME(sizeof(buf)), buf) >= 0) {
		return buf;
	}

	return NULL;
}

static void process_event(struct hiddev_usage_ref *ev)
{
	printf("0x%x (0x%x): %d\n", ev->usage_code, ev->report_id, ev->value);
}

static bool send_report(unsigned int report_type, unsigned int report_id)
{
	struct hiddev_report_info rinfo;
	rinfo.report_type = report_type;
	rinfo.report_id = report_id;
	rinfo.num_fields = 0;

	if (ioctl(devfd, HIDIOCSREPORT, &rinfo) < 0) {
		perror("HIDIOCSREPORT");
		return false;
	}

	printf("Report 0x%x sent\n", rinfo.report_id);

	return true;
}

static __s32 read_usage(unsigned int report_type, unsigned int usage_code)
{
	struct hiddev_usage_ref uref;
	uref.report_type = report_type;
	uref.report_id = HID_REPORT_ID_UNKNOWN;
	uref.usage_code = usage_code;

	if (ioctl(devfd, HIDIOCGUSAGE, &uref) < 0) {
		perror("HIDIOCGUSAGE");
		return -1;
	}

	printf("0x%x: %d\n", uref.usage_code, uref.value);

	return uref.value;
}

static void write_usage(unsigned int report_type, unsigned int usage_code, __s32 value)
{
	struct hiddev_usage_ref uref;
	uref.report_type = report_type;
	uref.report_id = HID_REPORT_ID_UNKNOWN;
	uref.usage_code = usage_code;

	if (ioctl(devfd, HIDIOCGUSAGE, &uref) < 0) {
		perror("HIDIOCGUSAGE");
		return;
	}

	uref.value = value;
	if (ioctl(devfd, HIDIOCSUSAGE, &uref) < 0)
	{
		perror("HIDIOCSUSAGE");
		return;
	}

	printf("0x%x := %d\n", uref.usage_code, uref.value);

	send_report(uref.report_type, uref.report_id);
}

int main(int argc, const char *argv[])
{
	if (argc != 3) {
		fprintf(stderr, "Usage: %s <device> <0|1>\n", argv[0]);
		return EXIT_FAILURE;
	}

	const char *device = argv[1];
	const bool enable_ptp = strtol(argv[2], NULL, 10);

	printf("Opening %s...\n", device);
	devfd = open(device, O_RDONLY);

	if (devfd == -1) {
		perror("Could not open device");
		return EXIT_FAILURE;
	}

	printf("Found '%s'\n", get_device_name());

	// Setup flags
	int flags = HIDDEV_FLAG_UREF | HIDDEV_FLAG_REPORT;
	if (ioctl(devfd, HIDIOCSFLAG, &flags) < 0) {
		perror("HIDIOCSFLAG");
		return EXIT_FAILURE;
	}

	write_usage(HID_REPORT_TYPE_FEATURE, 0x0d0052, enable_ptp ? 3 : 0);

	int rc;
	do {
		struct hiddev_usage_ref ev;
		rc = read(devfd, &ev, sizeof(ev));
		if (rc < 0) {
			perror("Could not read events from device");
			return EXIT_FAILURE;
		} else if (rc == 0) {
		}

		process_event(&ev);
	} while (rc > 0);

	return EXIT_SUCCESS;
}