xref: /aosp_15_r20/system/core/toolbox/getevent.c (revision 00c7fec1bb09f3284aad6a6f96d2f63dfc3650ad)
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