1*00c7fec1SAndroid Build Coastguard Worker #include <stdio.h>
2*00c7fec1SAndroid Build Coastguard Worker #include <stdlib.h>
3*00c7fec1SAndroid Build Coastguard Worker #include <string.h>
4*00c7fec1SAndroid Build Coastguard Worker #include <stdint.h>
5*00c7fec1SAndroid Build Coastguard Worker #include <dirent.h>
6*00c7fec1SAndroid Build Coastguard Worker #include <fcntl.h>
7*00c7fec1SAndroid Build Coastguard Worker #include <sys/ioctl.h>
8*00c7fec1SAndroid Build Coastguard Worker #include <sys/inotify.h>
9*00c7fec1SAndroid Build Coastguard Worker #include <sys/limits.h>
10*00c7fec1SAndroid Build Coastguard Worker #include <sys/poll.h>
11*00c7fec1SAndroid Build Coastguard Worker #include <linux/input.h>
12*00c7fec1SAndroid Build Coastguard Worker #include <err.h>
13*00c7fec1SAndroid Build Coastguard Worker #include <errno.h>
14*00c7fec1SAndroid Build Coastguard Worker #include <unistd.h>
15*00c7fec1SAndroid Build Coastguard Worker
16*00c7fec1SAndroid Build Coastguard Worker struct label {
17*00c7fec1SAndroid Build Coastguard Worker const char *name;
18*00c7fec1SAndroid Build Coastguard Worker int value;
19*00c7fec1SAndroid Build Coastguard Worker };
20*00c7fec1SAndroid Build Coastguard Worker
21*00c7fec1SAndroid Build Coastguard Worker #define LABEL(constant) { #constant, constant }
22*00c7fec1SAndroid Build Coastguard Worker #define LABEL_END { NULL, -1 }
23*00c7fec1SAndroid Build Coastguard Worker
24*00c7fec1SAndroid Build Coastguard Worker static struct label key_value_labels[] = {
25*00c7fec1SAndroid Build Coastguard Worker { "UP", 0 },
26*00c7fec1SAndroid Build Coastguard Worker { "DOWN", 1 },
27*00c7fec1SAndroid Build Coastguard Worker { "REPEAT", 2 },
28*00c7fec1SAndroid Build Coastguard Worker LABEL_END,
29*00c7fec1SAndroid Build Coastguard Worker };
30*00c7fec1SAndroid Build Coastguard Worker
31*00c7fec1SAndroid Build Coastguard Worker #include "input.h-labels.h"
32*00c7fec1SAndroid Build Coastguard Worker
33*00c7fec1SAndroid Build Coastguard Worker #undef LABEL
34*00c7fec1SAndroid Build Coastguard Worker #undef LABEL_END
35*00c7fec1SAndroid Build Coastguard Worker
36*00c7fec1SAndroid Build Coastguard Worker static struct pollfd *ufds;
37*00c7fec1SAndroid Build Coastguard Worker static char **device_names;
38*00c7fec1SAndroid Build Coastguard Worker static int nfds;
39*00c7fec1SAndroid Build Coastguard Worker
40*00c7fec1SAndroid Build Coastguard Worker enum {
41*00c7fec1SAndroid Build Coastguard Worker PRINT_DEVICE_ERRORS = 1U << 0,
42*00c7fec1SAndroid Build Coastguard Worker PRINT_DEVICE = 1U << 1,
43*00c7fec1SAndroid Build Coastguard Worker PRINT_DEVICE_NAME = 1U << 2,
44*00c7fec1SAndroid Build Coastguard Worker PRINT_DEVICE_INFO = 1U << 3,
45*00c7fec1SAndroid Build Coastguard Worker PRINT_VERSION = 1U << 4,
46*00c7fec1SAndroid Build Coastguard Worker PRINT_POSSIBLE_EVENTS = 1U << 5,
47*00c7fec1SAndroid Build Coastguard Worker PRINT_INPUT_PROPS = 1U << 6,
48*00c7fec1SAndroid Build Coastguard Worker PRINT_HID_DESCRIPTOR = 1U << 7,
49*00c7fec1SAndroid Build Coastguard Worker
50*00c7fec1SAndroid Build Coastguard Worker PRINT_ALL_INFO = (1U << 8) - 1,
51*00c7fec1SAndroid Build Coastguard Worker
52*00c7fec1SAndroid Build Coastguard Worker PRINT_LABELS = 1U << 16,
53*00c7fec1SAndroid Build Coastguard Worker };
54*00c7fec1SAndroid Build Coastguard Worker
get_label(const struct label * labels,int value)55*00c7fec1SAndroid Build Coastguard Worker static const char *get_label(const struct label *labels, int value)
56*00c7fec1SAndroid Build Coastguard Worker {
57*00c7fec1SAndroid Build Coastguard Worker while(labels->name && value != labels->value) {
58*00c7fec1SAndroid Build Coastguard Worker labels++;
59*00c7fec1SAndroid Build Coastguard Worker }
60*00c7fec1SAndroid Build Coastguard Worker return labels->name;
61*00c7fec1SAndroid Build Coastguard Worker }
62*00c7fec1SAndroid Build Coastguard Worker
print_input_props(int fd)63*00c7fec1SAndroid Build Coastguard Worker static int print_input_props(int fd)
64*00c7fec1SAndroid Build Coastguard Worker {
65*00c7fec1SAndroid Build Coastguard Worker uint8_t bits[INPUT_PROP_CNT / 8];
66*00c7fec1SAndroid Build Coastguard Worker int i, j;
67*00c7fec1SAndroid Build Coastguard Worker int res;
68*00c7fec1SAndroid Build Coastguard Worker int count;
69*00c7fec1SAndroid Build Coastguard Worker const char *bit_label;
70*00c7fec1SAndroid Build Coastguard Worker
71*00c7fec1SAndroid Build Coastguard Worker printf(" input props:\n");
72*00c7fec1SAndroid Build Coastguard Worker res = ioctl(fd, EVIOCGPROP(sizeof(bits)), bits);
73*00c7fec1SAndroid Build Coastguard Worker if(res < 0) {
74*00c7fec1SAndroid Build Coastguard Worker printf(" <not available\n");
75*00c7fec1SAndroid Build Coastguard Worker return 1;
76*00c7fec1SAndroid Build Coastguard Worker }
77*00c7fec1SAndroid Build Coastguard Worker count = 0;
78*00c7fec1SAndroid Build Coastguard Worker for(i = 0; i < res; i++) {
79*00c7fec1SAndroid Build Coastguard Worker for(j = 0; j < 8; j++) {
80*00c7fec1SAndroid Build Coastguard Worker if (bits[i] & 1 << j) {
81*00c7fec1SAndroid Build Coastguard Worker bit_label = get_label(input_prop_labels, i * 8 + j);
82*00c7fec1SAndroid Build Coastguard Worker if(bit_label)
83*00c7fec1SAndroid Build Coastguard Worker printf(" %s\n", bit_label);
84*00c7fec1SAndroid Build Coastguard Worker else
85*00c7fec1SAndroid Build Coastguard Worker printf(" %04x\n", i * 8 + j);
86*00c7fec1SAndroid Build Coastguard Worker count++;
87*00c7fec1SAndroid Build Coastguard Worker }
88*00c7fec1SAndroid Build Coastguard Worker }
89*00c7fec1SAndroid Build Coastguard Worker }
90*00c7fec1SAndroid Build Coastguard Worker if (!count)
91*00c7fec1SAndroid Build Coastguard Worker printf(" <none>\n");
92*00c7fec1SAndroid Build Coastguard Worker return 0;
93*00c7fec1SAndroid Build Coastguard Worker }
94*00c7fec1SAndroid Build Coastguard Worker
print_possible_events(int fd,int print_flags)95*00c7fec1SAndroid Build Coastguard Worker static int print_possible_events(int fd, int print_flags)
96*00c7fec1SAndroid Build Coastguard Worker {
97*00c7fec1SAndroid Build Coastguard Worker uint8_t *bits = NULL;
98*00c7fec1SAndroid Build Coastguard Worker ssize_t bits_size = 0;
99*00c7fec1SAndroid Build Coastguard Worker const char* label;
100*00c7fec1SAndroid Build Coastguard Worker int i, j, k;
101*00c7fec1SAndroid Build Coastguard Worker int res, res2;
102*00c7fec1SAndroid Build Coastguard Worker struct label* bit_labels;
103*00c7fec1SAndroid Build Coastguard Worker const char *bit_label;
104*00c7fec1SAndroid Build Coastguard Worker
105*00c7fec1SAndroid Build Coastguard Worker printf(" events:\n");
106*00c7fec1SAndroid Build Coastguard Worker for(i = EV_KEY; i <= EV_MAX; i++) { // skip EV_SYN since we cannot query its available codes
107*00c7fec1SAndroid Build Coastguard Worker int count = 0;
108*00c7fec1SAndroid Build Coastguard Worker while(1) {
109*00c7fec1SAndroid Build Coastguard Worker res = ioctl(fd, EVIOCGBIT(i, bits_size), bits);
110*00c7fec1SAndroid Build Coastguard Worker if(res < bits_size)
111*00c7fec1SAndroid Build Coastguard Worker break;
112*00c7fec1SAndroid Build Coastguard Worker bits_size = res + 16;
113*00c7fec1SAndroid Build Coastguard Worker bits = realloc(bits, bits_size * 2);
114*00c7fec1SAndroid Build Coastguard Worker if (bits == NULL) err(1, "failed to allocate buffer of size %zd", bits_size);
115*00c7fec1SAndroid Build Coastguard Worker }
116*00c7fec1SAndroid Build Coastguard Worker res2 = 0;
117*00c7fec1SAndroid Build Coastguard Worker switch(i) {
118*00c7fec1SAndroid Build Coastguard Worker case EV_KEY:
119*00c7fec1SAndroid Build Coastguard Worker res2 = ioctl(fd, EVIOCGKEY(res), bits + bits_size);
120*00c7fec1SAndroid Build Coastguard Worker label = "KEY";
121*00c7fec1SAndroid Build Coastguard Worker bit_labels = key_labels;
122*00c7fec1SAndroid Build Coastguard Worker break;
123*00c7fec1SAndroid Build Coastguard Worker case EV_REL:
124*00c7fec1SAndroid Build Coastguard Worker label = "REL";
125*00c7fec1SAndroid Build Coastguard Worker bit_labels = rel_labels;
126*00c7fec1SAndroid Build Coastguard Worker break;
127*00c7fec1SAndroid Build Coastguard Worker case EV_ABS:
128*00c7fec1SAndroid Build Coastguard Worker label = "ABS";
129*00c7fec1SAndroid Build Coastguard Worker bit_labels = abs_labels;
130*00c7fec1SAndroid Build Coastguard Worker break;
131*00c7fec1SAndroid Build Coastguard Worker case EV_MSC:
132*00c7fec1SAndroid Build Coastguard Worker label = "MSC";
133*00c7fec1SAndroid Build Coastguard Worker bit_labels = msc_labels;
134*00c7fec1SAndroid Build Coastguard Worker break;
135*00c7fec1SAndroid Build Coastguard Worker case EV_LED:
136*00c7fec1SAndroid Build Coastguard Worker res2 = ioctl(fd, EVIOCGLED(res), bits + bits_size);
137*00c7fec1SAndroid Build Coastguard Worker label = "LED";
138*00c7fec1SAndroid Build Coastguard Worker bit_labels = led_labels;
139*00c7fec1SAndroid Build Coastguard Worker break;
140*00c7fec1SAndroid Build Coastguard Worker case EV_SND:
141*00c7fec1SAndroid Build Coastguard Worker res2 = ioctl(fd, EVIOCGSND(res), bits + bits_size);
142*00c7fec1SAndroid Build Coastguard Worker label = "SND";
143*00c7fec1SAndroid Build Coastguard Worker bit_labels = snd_labels;
144*00c7fec1SAndroid Build Coastguard Worker break;
145*00c7fec1SAndroid Build Coastguard Worker case EV_SW:
146*00c7fec1SAndroid Build Coastguard Worker res2 = ioctl(fd, EVIOCGSW(bits_size), bits + bits_size);
147*00c7fec1SAndroid Build Coastguard Worker label = "SW ";
148*00c7fec1SAndroid Build Coastguard Worker bit_labels = sw_labels;
149*00c7fec1SAndroid Build Coastguard Worker break;
150*00c7fec1SAndroid Build Coastguard Worker case EV_REP:
151*00c7fec1SAndroid Build Coastguard Worker label = "REP";
152*00c7fec1SAndroid Build Coastguard Worker bit_labels = rep_labels;
153*00c7fec1SAndroid Build Coastguard Worker break;
154*00c7fec1SAndroid Build Coastguard Worker case EV_FF:
155*00c7fec1SAndroid Build Coastguard Worker label = "FF ";
156*00c7fec1SAndroid Build Coastguard Worker bit_labels = ff_labels;
157*00c7fec1SAndroid Build Coastguard Worker break;
158*00c7fec1SAndroid Build Coastguard Worker case EV_PWR:
159*00c7fec1SAndroid Build Coastguard Worker label = "PWR";
160*00c7fec1SAndroid Build Coastguard Worker bit_labels = NULL;
161*00c7fec1SAndroid Build Coastguard Worker break;
162*00c7fec1SAndroid Build Coastguard Worker case EV_FF_STATUS:
163*00c7fec1SAndroid Build Coastguard Worker label = "FFS";
164*00c7fec1SAndroid Build Coastguard Worker bit_labels = ff_status_labels;
165*00c7fec1SAndroid Build Coastguard Worker break;
166*00c7fec1SAndroid Build Coastguard Worker default:
167*00c7fec1SAndroid Build Coastguard Worker res2 = 0;
168*00c7fec1SAndroid Build Coastguard Worker label = "???";
169*00c7fec1SAndroid Build Coastguard Worker bit_labels = NULL;
170*00c7fec1SAndroid Build Coastguard Worker }
171*00c7fec1SAndroid Build Coastguard Worker for(j = 0; j < res; j++) {
172*00c7fec1SAndroid Build Coastguard Worker for(k = 0; k < 8; k++)
173*00c7fec1SAndroid Build Coastguard Worker if(bits[j] & 1 << k) {
174*00c7fec1SAndroid Build Coastguard Worker char down;
175*00c7fec1SAndroid Build Coastguard Worker if(j < res2 && (bits[j + bits_size] & 1 << k))
176*00c7fec1SAndroid Build Coastguard Worker down = '*';
177*00c7fec1SAndroid Build Coastguard Worker else
178*00c7fec1SAndroid Build Coastguard Worker down = ' ';
179*00c7fec1SAndroid Build Coastguard Worker if(count == 0)
180*00c7fec1SAndroid Build Coastguard Worker printf(" %s (%04x):", label, i);
181*00c7fec1SAndroid Build Coastguard Worker else if((count & (print_flags & PRINT_LABELS ? 0x3 : 0x7)) == 0 || i == EV_ABS)
182*00c7fec1SAndroid Build Coastguard Worker printf("\n ");
183*00c7fec1SAndroid Build Coastguard Worker if(bit_labels && (print_flags & PRINT_LABELS)) {
184*00c7fec1SAndroid Build Coastguard Worker bit_label = get_label(bit_labels, j * 8 + k);
185*00c7fec1SAndroid Build Coastguard Worker if(bit_label)
186*00c7fec1SAndroid Build Coastguard Worker printf(" %.20s%c%*s", bit_label, down, (int) (20 - strlen(bit_label)), "");
187*00c7fec1SAndroid Build Coastguard Worker else
188*00c7fec1SAndroid Build Coastguard Worker printf(" %04x%c ", j * 8 + k, down);
189*00c7fec1SAndroid Build Coastguard Worker } else {
190*00c7fec1SAndroid Build Coastguard Worker printf(" %04x%c", j * 8 + k, down);
191*00c7fec1SAndroid Build Coastguard Worker }
192*00c7fec1SAndroid Build Coastguard Worker if(i == EV_ABS) {
193*00c7fec1SAndroid Build Coastguard Worker struct input_absinfo abs;
194*00c7fec1SAndroid Build Coastguard Worker if(ioctl(fd, EVIOCGABS(j * 8 + k), &abs) == 0) {
195*00c7fec1SAndroid Build Coastguard Worker printf(" : value %d, min %d, max %d, fuzz %d, flat %d, resolution %d",
196*00c7fec1SAndroid Build Coastguard Worker abs.value, abs.minimum, abs.maximum, abs.fuzz, abs.flat,
197*00c7fec1SAndroid Build Coastguard Worker abs.resolution);
198*00c7fec1SAndroid Build Coastguard Worker }
199*00c7fec1SAndroid Build Coastguard Worker }
200*00c7fec1SAndroid Build Coastguard Worker count++;
201*00c7fec1SAndroid Build Coastguard Worker }
202*00c7fec1SAndroid Build Coastguard Worker }
203*00c7fec1SAndroid Build Coastguard Worker if(count)
204*00c7fec1SAndroid Build Coastguard Worker printf("\n");
205*00c7fec1SAndroid Build Coastguard Worker }
206*00c7fec1SAndroid Build Coastguard Worker free(bits);
207*00c7fec1SAndroid Build Coastguard Worker return 0;
208*00c7fec1SAndroid Build Coastguard Worker }
209*00c7fec1SAndroid Build Coastguard Worker
print_event(int type,int code,int value,int print_flags)210*00c7fec1SAndroid Build Coastguard Worker static void print_event(int type, int code, int value, int print_flags)
211*00c7fec1SAndroid Build Coastguard Worker {
212*00c7fec1SAndroid Build Coastguard Worker const char *type_label, *code_label, *value_label;
213*00c7fec1SAndroid Build Coastguard Worker
214*00c7fec1SAndroid Build Coastguard Worker if (print_flags & PRINT_LABELS) {
215*00c7fec1SAndroid Build Coastguard Worker type_label = get_label(ev_labels, type);
216*00c7fec1SAndroid Build Coastguard Worker code_label = NULL;
217*00c7fec1SAndroid Build Coastguard Worker value_label = NULL;
218*00c7fec1SAndroid Build Coastguard Worker
219*00c7fec1SAndroid Build Coastguard Worker switch(type) {
220*00c7fec1SAndroid Build Coastguard Worker case EV_SYN:
221*00c7fec1SAndroid Build Coastguard Worker code_label = get_label(syn_labels, code);
222*00c7fec1SAndroid Build Coastguard Worker break;
223*00c7fec1SAndroid Build Coastguard Worker case EV_KEY:
224*00c7fec1SAndroid Build Coastguard Worker code_label = get_label(key_labels, code);
225*00c7fec1SAndroid Build Coastguard Worker value_label = get_label(key_value_labels, value);
226*00c7fec1SAndroid Build Coastguard Worker break;
227*00c7fec1SAndroid Build Coastguard Worker case EV_REL:
228*00c7fec1SAndroid Build Coastguard Worker code_label = get_label(rel_labels, code);
229*00c7fec1SAndroid Build Coastguard Worker break;
230*00c7fec1SAndroid Build Coastguard Worker case EV_ABS:
231*00c7fec1SAndroid Build Coastguard Worker code_label = get_label(abs_labels, code);
232*00c7fec1SAndroid Build Coastguard Worker switch(code) {
233*00c7fec1SAndroid Build Coastguard Worker case ABS_MT_TOOL_TYPE:
234*00c7fec1SAndroid Build Coastguard Worker value_label = get_label(mt_tool_labels, value);
235*00c7fec1SAndroid Build Coastguard Worker }
236*00c7fec1SAndroid Build Coastguard Worker break;
237*00c7fec1SAndroid Build Coastguard Worker case EV_MSC:
238*00c7fec1SAndroid Build Coastguard Worker code_label = get_label(msc_labels, code);
239*00c7fec1SAndroid Build Coastguard Worker break;
240*00c7fec1SAndroid Build Coastguard Worker case EV_LED:
241*00c7fec1SAndroid Build Coastguard Worker code_label = get_label(led_labels, code);
242*00c7fec1SAndroid Build Coastguard Worker break;
243*00c7fec1SAndroid Build Coastguard Worker case EV_SND:
244*00c7fec1SAndroid Build Coastguard Worker code_label = get_label(snd_labels, code);
245*00c7fec1SAndroid Build Coastguard Worker break;
246*00c7fec1SAndroid Build Coastguard Worker case EV_SW:
247*00c7fec1SAndroid Build Coastguard Worker code_label = get_label(sw_labels, code);
248*00c7fec1SAndroid Build Coastguard Worker break;
249*00c7fec1SAndroid Build Coastguard Worker case EV_REP:
250*00c7fec1SAndroid Build Coastguard Worker code_label = get_label(rep_labels, code);
251*00c7fec1SAndroid Build Coastguard Worker break;
252*00c7fec1SAndroid Build Coastguard Worker case EV_FF:
253*00c7fec1SAndroid Build Coastguard Worker code_label = get_label(ff_labels, code);
254*00c7fec1SAndroid Build Coastguard Worker break;
255*00c7fec1SAndroid Build Coastguard Worker case EV_FF_STATUS:
256*00c7fec1SAndroid Build Coastguard Worker code_label = get_label(ff_status_labels, code);
257*00c7fec1SAndroid Build Coastguard Worker break;
258*00c7fec1SAndroid Build Coastguard Worker }
259*00c7fec1SAndroid Build Coastguard Worker
260*00c7fec1SAndroid Build Coastguard Worker if (type_label)
261*00c7fec1SAndroid Build Coastguard Worker printf("%-12.12s", type_label);
262*00c7fec1SAndroid Build Coastguard Worker else
263*00c7fec1SAndroid Build Coastguard Worker printf("%04x ", type);
264*00c7fec1SAndroid Build Coastguard Worker if (code_label)
265*00c7fec1SAndroid Build Coastguard Worker printf(" %-20.20s", code_label);
266*00c7fec1SAndroid Build Coastguard Worker else
267*00c7fec1SAndroid Build Coastguard Worker printf(" %04x ", code);
268*00c7fec1SAndroid Build Coastguard Worker if (value_label)
269*00c7fec1SAndroid Build Coastguard Worker printf(" %-20.20s", value_label);
270*00c7fec1SAndroid Build Coastguard Worker else
271*00c7fec1SAndroid Build Coastguard Worker printf(" %08x ", value);
272*00c7fec1SAndroid Build Coastguard Worker } else {
273*00c7fec1SAndroid Build Coastguard Worker printf("%04x %04x %08x", type, code, value);
274*00c7fec1SAndroid Build Coastguard Worker }
275*00c7fec1SAndroid Build Coastguard Worker }
276*00c7fec1SAndroid Build Coastguard Worker
print_hid_descriptor(int bus,int vendor,int product)277*00c7fec1SAndroid Build Coastguard Worker static void print_hid_descriptor(int bus, int vendor, int product)
278*00c7fec1SAndroid Build Coastguard Worker {
279*00c7fec1SAndroid Build Coastguard Worker const char *dirname = "/sys/kernel/debug/hid";
280*00c7fec1SAndroid Build Coastguard Worker char prefix[16];
281*00c7fec1SAndroid Build Coastguard Worker DIR *dir;
282*00c7fec1SAndroid Build Coastguard Worker struct dirent *de;
283*00c7fec1SAndroid Build Coastguard Worker char filename[PATH_MAX];
284*00c7fec1SAndroid Build Coastguard Worker FILE *file;
285*00c7fec1SAndroid Build Coastguard Worker char line[2048];
286*00c7fec1SAndroid Build Coastguard Worker
287*00c7fec1SAndroid Build Coastguard Worker snprintf(prefix, sizeof(prefix), "%04X:%04X:%04X.", bus, vendor, product);
288*00c7fec1SAndroid Build Coastguard Worker
289*00c7fec1SAndroid Build Coastguard Worker dir = opendir(dirname);
290*00c7fec1SAndroid Build Coastguard Worker if(dir == NULL)
291*00c7fec1SAndroid Build Coastguard Worker return;
292*00c7fec1SAndroid Build Coastguard Worker while((de = readdir(dir))) {
293*00c7fec1SAndroid Build Coastguard Worker if (strstr(de->d_name, prefix) == de->d_name) {
294*00c7fec1SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), "%s/%s/rdesc", dirname, de->d_name);
295*00c7fec1SAndroid Build Coastguard Worker
296*00c7fec1SAndroid Build Coastguard Worker file = fopen(filename, "r");
297*00c7fec1SAndroid Build Coastguard Worker if (file) {
298*00c7fec1SAndroid Build Coastguard Worker printf(" HID descriptor: %s\n\n", de->d_name);
299*00c7fec1SAndroid Build Coastguard Worker while (fgets(line, sizeof(line), file)) {
300*00c7fec1SAndroid Build Coastguard Worker fputs(" ", stdout);
301*00c7fec1SAndroid Build Coastguard Worker fputs(line, stdout);
302*00c7fec1SAndroid Build Coastguard Worker }
303*00c7fec1SAndroid Build Coastguard Worker fclose(file);
304*00c7fec1SAndroid Build Coastguard Worker puts("");
305*00c7fec1SAndroid Build Coastguard Worker }
306*00c7fec1SAndroid Build Coastguard Worker }
307*00c7fec1SAndroid Build Coastguard Worker }
308*00c7fec1SAndroid Build Coastguard Worker closedir(dir);
309*00c7fec1SAndroid Build Coastguard Worker }
310*00c7fec1SAndroid Build Coastguard Worker
open_device(const char * device,int print_flags)311*00c7fec1SAndroid Build Coastguard Worker static int open_device(const char *device, int print_flags)
312*00c7fec1SAndroid Build Coastguard Worker {
313*00c7fec1SAndroid Build Coastguard Worker int version;
314*00c7fec1SAndroid Build Coastguard Worker int fd;
315*00c7fec1SAndroid Build Coastguard Worker int clkid = CLOCK_MONOTONIC;
316*00c7fec1SAndroid Build Coastguard Worker struct pollfd *new_ufds;
317*00c7fec1SAndroid Build Coastguard Worker char **new_device_names;
318*00c7fec1SAndroid Build Coastguard Worker char name[80];
319*00c7fec1SAndroid Build Coastguard Worker char location[80];
320*00c7fec1SAndroid Build Coastguard Worker char idstr[80];
321*00c7fec1SAndroid Build Coastguard Worker struct input_id id;
322*00c7fec1SAndroid Build Coastguard Worker
323*00c7fec1SAndroid Build Coastguard Worker fd = open(device, O_RDONLY | O_CLOEXEC);
324*00c7fec1SAndroid Build Coastguard Worker if(fd < 0) {
325*00c7fec1SAndroid Build Coastguard Worker if(print_flags & PRINT_DEVICE_ERRORS)
326*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, "could not open %s, %s\n", device, strerror(errno));
327*00c7fec1SAndroid Build Coastguard Worker return -1;
328*00c7fec1SAndroid Build Coastguard Worker }
329*00c7fec1SAndroid Build Coastguard Worker
330*00c7fec1SAndroid Build Coastguard Worker if(ioctl(fd, EVIOCGVERSION, &version)) {
331*00c7fec1SAndroid Build Coastguard Worker if(print_flags & PRINT_DEVICE_ERRORS)
332*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, "could not get driver version for %s, %s\n", device, strerror(errno));
333*00c7fec1SAndroid Build Coastguard Worker return -1;
334*00c7fec1SAndroid Build Coastguard Worker }
335*00c7fec1SAndroid Build Coastguard Worker if(ioctl(fd, EVIOCGID, &id)) {
336*00c7fec1SAndroid Build Coastguard Worker if(print_flags & PRINT_DEVICE_ERRORS)
337*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, "could not get driver id for %s, %s\n", device, strerror(errno));
338*00c7fec1SAndroid Build Coastguard Worker return -1;
339*00c7fec1SAndroid Build Coastguard Worker }
340*00c7fec1SAndroid Build Coastguard Worker name[sizeof(name) - 1] = '\0';
341*00c7fec1SAndroid Build Coastguard Worker location[sizeof(location) - 1] = '\0';
342*00c7fec1SAndroid Build Coastguard Worker idstr[sizeof(idstr) - 1] = '\0';
343*00c7fec1SAndroid Build Coastguard Worker if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
344*00c7fec1SAndroid Build Coastguard Worker //fprintf(stderr, "could not get device name for %s, %s\n", device, strerror(errno));
345*00c7fec1SAndroid Build Coastguard Worker name[0] = '\0';
346*00c7fec1SAndroid Build Coastguard Worker }
347*00c7fec1SAndroid Build Coastguard Worker if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1) {
348*00c7fec1SAndroid Build Coastguard Worker //fprintf(stderr, "could not get location for %s, %s\n", device, strerror(errno));
349*00c7fec1SAndroid Build Coastguard Worker location[0] = '\0';
350*00c7fec1SAndroid Build Coastguard Worker }
351*00c7fec1SAndroid Build Coastguard Worker if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1) {
352*00c7fec1SAndroid Build Coastguard Worker //fprintf(stderr, "could not get idstring for %s, %s\n", device, strerror(errno));
353*00c7fec1SAndroid Build Coastguard Worker idstr[0] = '\0';
354*00c7fec1SAndroid Build Coastguard Worker }
355*00c7fec1SAndroid Build Coastguard Worker
356*00c7fec1SAndroid Build Coastguard Worker if (ioctl(fd, EVIOCSCLOCKID, &clkid) != 0) {
357*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, "Can't enable monotonic clock reporting: %s\n", strerror(errno));
358*00c7fec1SAndroid Build Coastguard Worker // a non-fatal error
359*00c7fec1SAndroid Build Coastguard Worker }
360*00c7fec1SAndroid Build Coastguard Worker
361*00c7fec1SAndroid Build Coastguard Worker new_ufds = realloc(ufds, sizeof(ufds[0]) * (nfds + 1));
362*00c7fec1SAndroid Build Coastguard Worker if(new_ufds == NULL) {
363*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, "out of memory\n");
364*00c7fec1SAndroid Build Coastguard Worker return -1;
365*00c7fec1SAndroid Build Coastguard Worker }
366*00c7fec1SAndroid Build Coastguard Worker ufds = new_ufds;
367*00c7fec1SAndroid Build Coastguard Worker new_device_names = realloc(device_names, sizeof(device_names[0]) * (nfds + 1));
368*00c7fec1SAndroid Build Coastguard Worker if(new_device_names == NULL) {
369*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, "out of memory\n");
370*00c7fec1SAndroid Build Coastguard Worker return -1;
371*00c7fec1SAndroid Build Coastguard Worker }
372*00c7fec1SAndroid Build Coastguard Worker device_names = new_device_names;
373*00c7fec1SAndroid Build Coastguard Worker
374*00c7fec1SAndroid Build Coastguard Worker if(print_flags & PRINT_DEVICE)
375*00c7fec1SAndroid Build Coastguard Worker printf("add device %d: %s\n", nfds, device);
376*00c7fec1SAndroid Build Coastguard Worker if(print_flags & PRINT_DEVICE_INFO)
377*00c7fec1SAndroid Build Coastguard Worker printf(" bus: %04x\n"
378*00c7fec1SAndroid Build Coastguard Worker " vendor %04x\n"
379*00c7fec1SAndroid Build Coastguard Worker " product %04x\n"
380*00c7fec1SAndroid Build Coastguard Worker " version %04x\n",
381*00c7fec1SAndroid Build Coastguard Worker id.bustype, id.vendor, id.product, id.version);
382*00c7fec1SAndroid Build Coastguard Worker if(print_flags & PRINT_DEVICE_NAME)
383*00c7fec1SAndroid Build Coastguard Worker printf(" name: \"%s\"\n", name);
384*00c7fec1SAndroid Build Coastguard Worker if(print_flags & PRINT_DEVICE_INFO)
385*00c7fec1SAndroid Build Coastguard Worker printf(" location: \"%s\"\n"
386*00c7fec1SAndroid Build Coastguard Worker " id: \"%s\"\n", location, idstr);
387*00c7fec1SAndroid Build Coastguard Worker if(print_flags & PRINT_VERSION)
388*00c7fec1SAndroid Build Coastguard Worker printf(" version: %d.%d.%d\n",
389*00c7fec1SAndroid Build Coastguard Worker version >> 16, (version >> 8) & 0xff, version & 0xff);
390*00c7fec1SAndroid Build Coastguard Worker
391*00c7fec1SAndroid Build Coastguard Worker if(print_flags & PRINT_POSSIBLE_EVENTS) {
392*00c7fec1SAndroid Build Coastguard Worker print_possible_events(fd, print_flags);
393*00c7fec1SAndroid Build Coastguard Worker }
394*00c7fec1SAndroid Build Coastguard Worker
395*00c7fec1SAndroid Build Coastguard Worker if(print_flags & PRINT_INPUT_PROPS) {
396*00c7fec1SAndroid Build Coastguard Worker print_input_props(fd);
397*00c7fec1SAndroid Build Coastguard Worker }
398*00c7fec1SAndroid Build Coastguard Worker if(print_flags & PRINT_HID_DESCRIPTOR) {
399*00c7fec1SAndroid Build Coastguard Worker print_hid_descriptor(id.bustype, id.vendor, id.product);
400*00c7fec1SAndroid Build Coastguard Worker }
401*00c7fec1SAndroid Build Coastguard Worker
402*00c7fec1SAndroid Build Coastguard Worker ufds[nfds].fd = fd;
403*00c7fec1SAndroid Build Coastguard Worker ufds[nfds].events = POLLIN;
404*00c7fec1SAndroid Build Coastguard Worker device_names[nfds] = strdup(device);
405*00c7fec1SAndroid Build Coastguard Worker nfds++;
406*00c7fec1SAndroid Build Coastguard Worker
407*00c7fec1SAndroid Build Coastguard Worker return 0;
408*00c7fec1SAndroid Build Coastguard Worker }
409*00c7fec1SAndroid Build Coastguard Worker
close_device(const char * device,int print_flags)410*00c7fec1SAndroid Build Coastguard Worker int close_device(const char *device, int print_flags)
411*00c7fec1SAndroid Build Coastguard Worker {
412*00c7fec1SAndroid Build Coastguard Worker int i;
413*00c7fec1SAndroid Build Coastguard Worker for(i = 1; i < nfds; i++) {
414*00c7fec1SAndroid Build Coastguard Worker if(strcmp(device_names[i], device) == 0) {
415*00c7fec1SAndroid Build Coastguard Worker int count = nfds - i - 1;
416*00c7fec1SAndroid Build Coastguard Worker if(print_flags & PRINT_DEVICE)
417*00c7fec1SAndroid Build Coastguard Worker printf("remove device %d: %s\n", i, device);
418*00c7fec1SAndroid Build Coastguard Worker free(device_names[i]);
419*00c7fec1SAndroid Build Coastguard Worker memmove(device_names + i, device_names + i + 1, sizeof(device_names[0]) * count);
420*00c7fec1SAndroid Build Coastguard Worker memmove(ufds + i, ufds + i + 1, sizeof(ufds[0]) * count);
421*00c7fec1SAndroid Build Coastguard Worker nfds--;
422*00c7fec1SAndroid Build Coastguard Worker return 0;
423*00c7fec1SAndroid Build Coastguard Worker }
424*00c7fec1SAndroid Build Coastguard Worker }
425*00c7fec1SAndroid Build Coastguard Worker if(print_flags & PRINT_DEVICE_ERRORS)
426*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, "remote device: %s not found\n", device);
427*00c7fec1SAndroid Build Coastguard Worker return -1;
428*00c7fec1SAndroid Build Coastguard Worker }
429*00c7fec1SAndroid Build Coastguard Worker
read_notify(const char * dirname,int nfd,int print_flags)430*00c7fec1SAndroid Build Coastguard Worker static int read_notify(const char *dirname, int nfd, int print_flags)
431*00c7fec1SAndroid Build Coastguard Worker {
432*00c7fec1SAndroid Build Coastguard Worker int res;
433*00c7fec1SAndroid Build Coastguard Worker char devname[PATH_MAX];
434*00c7fec1SAndroid Build Coastguard Worker char *filename;
435*00c7fec1SAndroid Build Coastguard Worker char event_buf[512];
436*00c7fec1SAndroid Build Coastguard Worker int event_size;
437*00c7fec1SAndroid Build Coastguard Worker int event_pos = 0;
438*00c7fec1SAndroid Build Coastguard Worker struct inotify_event *event;
439*00c7fec1SAndroid Build Coastguard Worker
440*00c7fec1SAndroid Build Coastguard Worker res = read(nfd, event_buf, sizeof(event_buf));
441*00c7fec1SAndroid Build Coastguard Worker if(res < (int)sizeof(*event)) {
442*00c7fec1SAndroid Build Coastguard Worker if(errno == EINTR)
443*00c7fec1SAndroid Build Coastguard Worker return 0;
444*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, "could not get inotify events, %s\n", strerror(errno));
445*00c7fec1SAndroid Build Coastguard Worker return 1;
446*00c7fec1SAndroid Build Coastguard Worker }
447*00c7fec1SAndroid Build Coastguard Worker //printf("got %d bytes of event information\n", res);
448*00c7fec1SAndroid Build Coastguard Worker
449*00c7fec1SAndroid Build Coastguard Worker strcpy(devname, dirname);
450*00c7fec1SAndroid Build Coastguard Worker filename = devname + strlen(devname);
451*00c7fec1SAndroid Build Coastguard Worker *filename++ = '/';
452*00c7fec1SAndroid Build Coastguard Worker
453*00c7fec1SAndroid Build Coastguard Worker while(res >= (int)sizeof(*event)) {
454*00c7fec1SAndroid Build Coastguard Worker event = (struct inotify_event *)(event_buf + event_pos);
455*00c7fec1SAndroid Build Coastguard Worker //printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : "");
456*00c7fec1SAndroid Build Coastguard Worker if(event->len) {
457*00c7fec1SAndroid Build Coastguard Worker strcpy(filename, event->name);
458*00c7fec1SAndroid Build Coastguard Worker if(event->mask & IN_CREATE) {
459*00c7fec1SAndroid Build Coastguard Worker open_device(devname, print_flags);
460*00c7fec1SAndroid Build Coastguard Worker }
461*00c7fec1SAndroid Build Coastguard Worker else {
462*00c7fec1SAndroid Build Coastguard Worker close_device(devname, print_flags);
463*00c7fec1SAndroid Build Coastguard Worker }
464*00c7fec1SAndroid Build Coastguard Worker }
465*00c7fec1SAndroid Build Coastguard Worker event_size = sizeof(*event) + event->len;
466*00c7fec1SAndroid Build Coastguard Worker res -= event_size;
467*00c7fec1SAndroid Build Coastguard Worker event_pos += event_size;
468*00c7fec1SAndroid Build Coastguard Worker }
469*00c7fec1SAndroid Build Coastguard Worker return 0;
470*00c7fec1SAndroid Build Coastguard Worker }
471*00c7fec1SAndroid Build Coastguard Worker
scan_dir(const char * dirname,int print_flags)472*00c7fec1SAndroid Build Coastguard Worker static int scan_dir(const char *dirname, int print_flags)
473*00c7fec1SAndroid Build Coastguard Worker {
474*00c7fec1SAndroid Build Coastguard Worker char devname[PATH_MAX];
475*00c7fec1SAndroid Build Coastguard Worker char *filename;
476*00c7fec1SAndroid Build Coastguard Worker DIR *dir;
477*00c7fec1SAndroid Build Coastguard Worker struct dirent *de;
478*00c7fec1SAndroid Build Coastguard Worker dir = opendir(dirname);
479*00c7fec1SAndroid Build Coastguard Worker if(dir == NULL)
480*00c7fec1SAndroid Build Coastguard Worker return -1;
481*00c7fec1SAndroid Build Coastguard Worker strcpy(devname, dirname);
482*00c7fec1SAndroid Build Coastguard Worker filename = devname + strlen(devname);
483*00c7fec1SAndroid Build Coastguard Worker *filename++ = '/';
484*00c7fec1SAndroid Build Coastguard Worker while((de = readdir(dir))) {
485*00c7fec1SAndroid Build Coastguard Worker if(de->d_name[0] == '.' &&
486*00c7fec1SAndroid Build Coastguard Worker (de->d_name[1] == '\0' ||
487*00c7fec1SAndroid Build Coastguard Worker (de->d_name[1] == '.' && de->d_name[2] == '\0')))
488*00c7fec1SAndroid Build Coastguard Worker continue;
489*00c7fec1SAndroid Build Coastguard Worker strcpy(filename, de->d_name);
490*00c7fec1SAndroid Build Coastguard Worker open_device(devname, print_flags);
491*00c7fec1SAndroid Build Coastguard Worker }
492*00c7fec1SAndroid Build Coastguard Worker closedir(dir);
493*00c7fec1SAndroid Build Coastguard Worker return 0;
494*00c7fec1SAndroid Build Coastguard Worker }
495*00c7fec1SAndroid Build Coastguard Worker
usage(char * name)496*00c7fec1SAndroid Build Coastguard Worker static void usage(char *name)
497*00c7fec1SAndroid Build Coastguard Worker {
498*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, "Usage: %s [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-d] [-p] [-i] [-l] [-q] [-c count] [-r] [device]\n", name);
499*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, " -t: show time stamps\n");
500*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, " -n: don't print newlines\n");
501*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, " -s: print switch states for given bits\n");
502*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, " -S: print all switch states\n");
503*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, " -v: verbosity mask (errs=1, dev=2, name=4, info=8, vers=16, pos. events=32, props=64)\n");
504*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, " -d: show HID descriptor, if available\n");
505*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, " -p: show possible events (errs, dev, name, pos. events)\n");
506*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, " -i: show all device info and possible events\n");
507*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, " -l: label event types and names in plain text\n");
508*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, " -q: quiet (clear verbosity mask)\n");
509*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, " -c: print given number of events then exit\n");
510*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, " -r: print rate events are received\n");
511*00c7fec1SAndroid Build Coastguard Worker }
512*00c7fec1SAndroid Build Coastguard Worker
getevent_main(int argc,char * argv[])513*00c7fec1SAndroid Build Coastguard Worker int getevent_main(int argc, char *argv[])
514*00c7fec1SAndroid Build Coastguard Worker {
515*00c7fec1SAndroid Build Coastguard Worker int c;
516*00c7fec1SAndroid Build Coastguard Worker int i;
517*00c7fec1SAndroid Build Coastguard Worker int res;
518*00c7fec1SAndroid Build Coastguard Worker int get_time = 0;
519*00c7fec1SAndroid Build Coastguard Worker int print_device = 0;
520*00c7fec1SAndroid Build Coastguard Worker char *newline = "\n";
521*00c7fec1SAndroid Build Coastguard Worker uint16_t get_switch = 0;
522*00c7fec1SAndroid Build Coastguard Worker struct input_event event;
523*00c7fec1SAndroid Build Coastguard Worker int print_flags = 0;
524*00c7fec1SAndroid Build Coastguard Worker int print_flags_set = 0;
525*00c7fec1SAndroid Build Coastguard Worker int dont_block = -1;
526*00c7fec1SAndroid Build Coastguard Worker int event_count = 0;
527*00c7fec1SAndroid Build Coastguard Worker int sync_rate = 0;
528*00c7fec1SAndroid Build Coastguard Worker int64_t last_sync_time = 0;
529*00c7fec1SAndroid Build Coastguard Worker const char *device = NULL;
530*00c7fec1SAndroid Build Coastguard Worker const char *device_path = "/dev/input";
531*00c7fec1SAndroid Build Coastguard Worker
532*00c7fec1SAndroid Build Coastguard Worker /* disable buffering on stdout */
533*00c7fec1SAndroid Build Coastguard Worker setbuf(stdout, NULL);
534*00c7fec1SAndroid Build Coastguard Worker
535*00c7fec1SAndroid Build Coastguard Worker opterr = 0;
536*00c7fec1SAndroid Build Coastguard Worker do {
537*00c7fec1SAndroid Build Coastguard Worker c = getopt(argc, argv, "tns:Sv::dpilqc:rh");
538*00c7fec1SAndroid Build Coastguard Worker if (c == EOF)
539*00c7fec1SAndroid Build Coastguard Worker break;
540*00c7fec1SAndroid Build Coastguard Worker switch (c) {
541*00c7fec1SAndroid Build Coastguard Worker case 't':
542*00c7fec1SAndroid Build Coastguard Worker get_time = 1;
543*00c7fec1SAndroid Build Coastguard Worker break;
544*00c7fec1SAndroid Build Coastguard Worker case 'n':
545*00c7fec1SAndroid Build Coastguard Worker newline = "";
546*00c7fec1SAndroid Build Coastguard Worker break;
547*00c7fec1SAndroid Build Coastguard Worker case 's':
548*00c7fec1SAndroid Build Coastguard Worker get_switch = strtoul(optarg, NULL, 0);
549*00c7fec1SAndroid Build Coastguard Worker if(dont_block == -1)
550*00c7fec1SAndroid Build Coastguard Worker dont_block = 1;
551*00c7fec1SAndroid Build Coastguard Worker break;
552*00c7fec1SAndroid Build Coastguard Worker case 'S':
553*00c7fec1SAndroid Build Coastguard Worker get_switch = ~0;
554*00c7fec1SAndroid Build Coastguard Worker if(dont_block == -1)
555*00c7fec1SAndroid Build Coastguard Worker dont_block = 1;
556*00c7fec1SAndroid Build Coastguard Worker break;
557*00c7fec1SAndroid Build Coastguard Worker case 'v':
558*00c7fec1SAndroid Build Coastguard Worker if(optarg)
559*00c7fec1SAndroid Build Coastguard Worker print_flags |= strtoul(optarg, NULL, 0);
560*00c7fec1SAndroid Build Coastguard Worker else
561*00c7fec1SAndroid Build Coastguard Worker print_flags |= PRINT_DEVICE | PRINT_DEVICE_NAME | PRINT_DEVICE_INFO | PRINT_VERSION;
562*00c7fec1SAndroid Build Coastguard Worker print_flags_set = 1;
563*00c7fec1SAndroid Build Coastguard Worker break;
564*00c7fec1SAndroid Build Coastguard Worker case 'd':
565*00c7fec1SAndroid Build Coastguard Worker print_flags |= PRINT_HID_DESCRIPTOR;
566*00c7fec1SAndroid Build Coastguard Worker break;
567*00c7fec1SAndroid Build Coastguard Worker case 'p':
568*00c7fec1SAndroid Build Coastguard Worker print_flags |= PRINT_DEVICE_ERRORS | PRINT_DEVICE
569*00c7fec1SAndroid Build Coastguard Worker | PRINT_DEVICE_NAME | PRINT_POSSIBLE_EVENTS | PRINT_INPUT_PROPS;
570*00c7fec1SAndroid Build Coastguard Worker print_flags_set = 1;
571*00c7fec1SAndroid Build Coastguard Worker if(dont_block == -1)
572*00c7fec1SAndroid Build Coastguard Worker dont_block = 1;
573*00c7fec1SAndroid Build Coastguard Worker break;
574*00c7fec1SAndroid Build Coastguard Worker case 'i':
575*00c7fec1SAndroid Build Coastguard Worker print_flags |= PRINT_ALL_INFO;
576*00c7fec1SAndroid Build Coastguard Worker print_flags_set = 1;
577*00c7fec1SAndroid Build Coastguard Worker if(dont_block == -1)
578*00c7fec1SAndroid Build Coastguard Worker dont_block = 1;
579*00c7fec1SAndroid Build Coastguard Worker break;
580*00c7fec1SAndroid Build Coastguard Worker case 'l':
581*00c7fec1SAndroid Build Coastguard Worker print_flags |= PRINT_LABELS;
582*00c7fec1SAndroid Build Coastguard Worker break;
583*00c7fec1SAndroid Build Coastguard Worker case 'q':
584*00c7fec1SAndroid Build Coastguard Worker print_flags_set = 1;
585*00c7fec1SAndroid Build Coastguard Worker break;
586*00c7fec1SAndroid Build Coastguard Worker case 'c':
587*00c7fec1SAndroid Build Coastguard Worker event_count = atoi(optarg);
588*00c7fec1SAndroid Build Coastguard Worker dont_block = 0;
589*00c7fec1SAndroid Build Coastguard Worker break;
590*00c7fec1SAndroid Build Coastguard Worker case 'r':
591*00c7fec1SAndroid Build Coastguard Worker sync_rate = 1;
592*00c7fec1SAndroid Build Coastguard Worker break;
593*00c7fec1SAndroid Build Coastguard Worker case '?':
594*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, "%s: invalid option -%c\n",
595*00c7fec1SAndroid Build Coastguard Worker argv[0], optopt);
596*00c7fec1SAndroid Build Coastguard Worker case 'h':
597*00c7fec1SAndroid Build Coastguard Worker usage(argv[0]);
598*00c7fec1SAndroid Build Coastguard Worker exit(1);
599*00c7fec1SAndroid Build Coastguard Worker }
600*00c7fec1SAndroid Build Coastguard Worker } while (1);
601*00c7fec1SAndroid Build Coastguard Worker if(dont_block == -1)
602*00c7fec1SAndroid Build Coastguard Worker dont_block = 0;
603*00c7fec1SAndroid Build Coastguard Worker
604*00c7fec1SAndroid Build Coastguard Worker if (optind + 1 == argc) {
605*00c7fec1SAndroid Build Coastguard Worker device = argv[optind];
606*00c7fec1SAndroid Build Coastguard Worker optind++;
607*00c7fec1SAndroid Build Coastguard Worker }
608*00c7fec1SAndroid Build Coastguard Worker if (optind != argc) {
609*00c7fec1SAndroid Build Coastguard Worker usage(argv[0]);
610*00c7fec1SAndroid Build Coastguard Worker exit(1);
611*00c7fec1SAndroid Build Coastguard Worker }
612*00c7fec1SAndroid Build Coastguard Worker nfds = 1;
613*00c7fec1SAndroid Build Coastguard Worker ufds = calloc(1, sizeof(ufds[0]));
614*00c7fec1SAndroid Build Coastguard Worker ufds[0].fd = inotify_init();
615*00c7fec1SAndroid Build Coastguard Worker ufds[0].events = POLLIN;
616*00c7fec1SAndroid Build Coastguard Worker if(device) {
617*00c7fec1SAndroid Build Coastguard Worker if(!print_flags_set)
618*00c7fec1SAndroid Build Coastguard Worker print_flags |= PRINT_DEVICE_ERRORS;
619*00c7fec1SAndroid Build Coastguard Worker res = open_device(device, print_flags);
620*00c7fec1SAndroid Build Coastguard Worker if(res < 0) {
621*00c7fec1SAndroid Build Coastguard Worker return 1;
622*00c7fec1SAndroid Build Coastguard Worker }
623*00c7fec1SAndroid Build Coastguard Worker } else {
624*00c7fec1SAndroid Build Coastguard Worker if(!print_flags_set)
625*00c7fec1SAndroid Build Coastguard Worker print_flags |= PRINT_DEVICE_ERRORS | PRINT_DEVICE | PRINT_DEVICE_NAME;
626*00c7fec1SAndroid Build Coastguard Worker print_device = 1;
627*00c7fec1SAndroid Build Coastguard Worker res = inotify_add_watch(ufds[0].fd, device_path, IN_DELETE | IN_CREATE);
628*00c7fec1SAndroid Build Coastguard Worker if(res < 0) {
629*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, "could not add watch for %s, %s\n", device_path, strerror(errno));
630*00c7fec1SAndroid Build Coastguard Worker return 1;
631*00c7fec1SAndroid Build Coastguard Worker }
632*00c7fec1SAndroid Build Coastguard Worker res = scan_dir(device_path, print_flags);
633*00c7fec1SAndroid Build Coastguard Worker if(res < 0) {
634*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, "scan dir failed for %s\n", device_path);
635*00c7fec1SAndroid Build Coastguard Worker return 1;
636*00c7fec1SAndroid Build Coastguard Worker }
637*00c7fec1SAndroid Build Coastguard Worker }
638*00c7fec1SAndroid Build Coastguard Worker
639*00c7fec1SAndroid Build Coastguard Worker if(get_switch) {
640*00c7fec1SAndroid Build Coastguard Worker for(i = 1; i < nfds; i++) {
641*00c7fec1SAndroid Build Coastguard Worker uint16_t sw;
642*00c7fec1SAndroid Build Coastguard Worker res = ioctl(ufds[i].fd, EVIOCGSW(1), &sw);
643*00c7fec1SAndroid Build Coastguard Worker if(res < 0) {
644*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, "could not get switch state, %s\n", strerror(errno));
645*00c7fec1SAndroid Build Coastguard Worker return 1;
646*00c7fec1SAndroid Build Coastguard Worker }
647*00c7fec1SAndroid Build Coastguard Worker sw &= get_switch;
648*00c7fec1SAndroid Build Coastguard Worker printf("%04x%s", sw, newline);
649*00c7fec1SAndroid Build Coastguard Worker }
650*00c7fec1SAndroid Build Coastguard Worker }
651*00c7fec1SAndroid Build Coastguard Worker
652*00c7fec1SAndroid Build Coastguard Worker if(dont_block)
653*00c7fec1SAndroid Build Coastguard Worker return 0;
654*00c7fec1SAndroid Build Coastguard Worker
655*00c7fec1SAndroid Build Coastguard Worker while(1) {
656*00c7fec1SAndroid Build Coastguard Worker //int pollres =
657*00c7fec1SAndroid Build Coastguard Worker poll(ufds, nfds, -1);
658*00c7fec1SAndroid Build Coastguard Worker //printf("poll %d, returned %d\n", nfds, pollres);
659*00c7fec1SAndroid Build Coastguard Worker if(ufds[0].revents & POLLIN) {
660*00c7fec1SAndroid Build Coastguard Worker read_notify(device_path, ufds[0].fd, print_flags);
661*00c7fec1SAndroid Build Coastguard Worker }
662*00c7fec1SAndroid Build Coastguard Worker for(i = 1; i < nfds; i++) {
663*00c7fec1SAndroid Build Coastguard Worker if(ufds[i].revents) {
664*00c7fec1SAndroid Build Coastguard Worker if(ufds[i].revents & POLLIN) {
665*00c7fec1SAndroid Build Coastguard Worker res = read(ufds[i].fd, &event, sizeof(event));
666*00c7fec1SAndroid Build Coastguard Worker if(res < (int)sizeof(event)) {
667*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, "could not get evdev event, %s\n", strerror(errno));
668*00c7fec1SAndroid Build Coastguard Worker return 1;
669*00c7fec1SAndroid Build Coastguard Worker }
670*00c7fec1SAndroid Build Coastguard Worker if(get_time) {
671*00c7fec1SAndroid Build Coastguard Worker printf("[%8ld.%06ld] ", event.time.tv_sec, event.time.tv_usec);
672*00c7fec1SAndroid Build Coastguard Worker }
673*00c7fec1SAndroid Build Coastguard Worker if(print_device)
674*00c7fec1SAndroid Build Coastguard Worker printf("%s: ", device_names[i]);
675*00c7fec1SAndroid Build Coastguard Worker print_event(event.type, event.code, event.value, print_flags);
676*00c7fec1SAndroid Build Coastguard Worker if(sync_rate && event.type == 0 && event.code == 0) {
677*00c7fec1SAndroid Build Coastguard Worker int64_t now = event.time.tv_sec * 1000000LL + event.time.tv_usec;
678*00c7fec1SAndroid Build Coastguard Worker if(last_sync_time)
679*00c7fec1SAndroid Build Coastguard Worker printf(" rate %lld", 1000000LL / (now - last_sync_time));
680*00c7fec1SAndroid Build Coastguard Worker last_sync_time = now;
681*00c7fec1SAndroid Build Coastguard Worker }
682*00c7fec1SAndroid Build Coastguard Worker printf("%s", newline);
683*00c7fec1SAndroid Build Coastguard Worker if(event_count && --event_count == 0)
684*00c7fec1SAndroid Build Coastguard Worker return 0;
685*00c7fec1SAndroid Build Coastguard Worker }
686*00c7fec1SAndroid Build Coastguard Worker }
687*00c7fec1SAndroid Build Coastguard Worker }
688*00c7fec1SAndroid Build Coastguard Worker }
689*00c7fec1SAndroid Build Coastguard Worker
690*00c7fec1SAndroid Build Coastguard Worker return 0;
691*00c7fec1SAndroid Build Coastguard Worker }
692