-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
177 lines (147 loc) · 4.69 KB
/
main.c
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// Most of the stuff in this file are shamelessly stolen from https://github.com/gjasny/v4l-utils/blob/master/utils/keytable/keytable.c
#include "hid_usb.h"
#include <errno.h>
#include <fcntl.h>
#include <linux/input.h>
#include <linux/lirc.h>
#include <poll.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
static struct timeval last_event_ts;
static long timeval_diff_ms(struct timeval* start, struct timeval* end)
{
long seconds = end->tv_sec - start->tv_sec;
long microseconds = end->tv_usec - start->tv_usec;
return seconds * 1000 + microseconds / 1000;
}
static void evcode_to_keypress(int32_t evcode)
{
hid_buf_t buf;
switch (evcode) {
case 77: // ch- button on remote = - button on keyboard (for volume down)
buf = hid_buf_new(0, IKO_KEY_KPMINUS);
hid_send(buf);
break;
case 76: // ch+ button on remote = + button on keyboard (for volume up)
buf = hid_buf_new(0, IKO_KEY_KPPLUS);
hid_send(buf);
break;
case 88: // up arrow button
buf = hid_buf_new(0, IKO_KEY_UP);
hid_send(buf);
break;
case 89: // down arrow button
buf = hid_buf_new(0, IKO_KEY_DOWN);
hid_send(buf);
break;
case 90: // left arrow button
buf = hid_buf_new(0, IKO_KEY_LEFT);
hid_send(buf);
break;
case 91: // right arrow button
buf = hid_buf_new(0, IKO_KEY_RIGHT);
hid_send(buf);
break;
case 44: // play button on remote = space on keyboard
buf = hid_buf_new(0, IKO_KEY_SPACE);
hid_send(buf);
break;
case 92: // ok button on remote = enter on keyboard
buf = hid_buf_new(0, IKO_KEY_ENTER);
hid_send(buf);
break;
case 10: // back button on remote = backspace on keyboard
buf = hid_buf_new(0, IKO_KEY_BACKSPACE);
hid_send(buf);
break;
default:
// Unmapped IR remote key, ignore
return;
}
}
static void print_scancodes(const struct lirc_scancode* scancodes, size_t count)
{
for (size_t i = 0; i < count; i++) {
unsigned long long ts1 = scancodes[i].timestamp / 1000000000ull;
unsigned long long ts2 = (scancodes[i].timestamp % 1000000000ull) / 1000ull;
printf("%llu.%06llu: scancode = 0x%llx\n", ts1, ts2, scancodes[i].scancode);
}
}
static void print_eventcodes(const struct input_event* eventcodes, size_t count)
{
for (size_t i = 0; i < count; i += 2) {
struct timeval ts = eventcodes[i].time;
long diff = timeval_diff_ms(&last_event_ts, &ts);
printf("diff: %li\n", diff);
if (diff < 250) {
break;
}
last_event_ts = ts;
int32_t val = eventcodes[i].value;
const long ts1 = eventcodes[i].time.tv_sec;
const long ts2 = (eventcodes[i].time.tv_usec);
printf("%li.%06li: scancode = %d\n", ts1, ts2, eventcodes[i].value);
evcode_to_keypress(val);
}
}
static void read_events(const char* lirc_name, int32_t fd)
{
struct input_event ev[64];
struct lirc_scancode sc[64];
ssize_t rd;
int32_t lircfd = -1;
/* LIRC reports time in monotonic, set event to same */
{
size_t mode = CLOCK_MONOTONIC;
ioctl(fd, EVIOCSCLOCKID, &mode);
}
uint32_t mode = LIRC_MODE_SCANCODE;
lircfd = open(lirc_name, O_RDONLY | O_NONBLOCK);
if (lircfd == -1) {
perror("Can't open lirc device");
return;
}
ioctl(lircfd, LIRC_SET_REC_MODE, &mode);
printf("Reading events. Please, press CTRL-C to abort.\n");
while (1) {
struct pollfd pollstruct[2] = {
{ .fd = fd, .events = POLLIN },
{ .fd = lircfd, .events = POLLIN },
};
if (poll(pollstruct, 2, -1) < 0) {
if (errno == EINTR)
continue;
perror("poll returned error");
}
rd = read(lircfd, sc, sizeof(sc));
if (rd != -1) {
// print_scancodes(sc, rd / sizeof(struct lirc_scancode));
(void)print_scancodes;
} else if (errno != EAGAIN) {
perror("Error reading lirc scancode");
return;
}
rd = read(fd, ev, sizeof(ev));
size_t count = (size_t)rd / sizeof(struct input_event);
print_eventcodes(ev, count);
printf("here we go again\n");
}
}
int main(void)
{
const char* lirc_name = "/dev/lirc0";
const char* input_name = "/dev/input/event0";
if (gettimeofday(&last_event_ts, NULL) == -1) {
perror("gettimeofday");
return 1;
}
int32_t fd = open(input_name, O_RDONLY | O_NONBLOCK);
if (fd < 0) {
perror(input_name);
return -1;
}
read_events(lirc_name, fd);
return 0;
}