1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright 2001,2002 Red Hat Inc., Durham, North Carolina.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * All Rights Reserved.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person obtaining
7*4882a593Smuzhiyun * a copy of this software and associated documentation files (the
8*4882a593Smuzhiyun * "Software"), to deal in the Software without restriction, including
9*4882a593Smuzhiyun * without limitation on the rights to use, copy, modify, merge,
10*4882a593Smuzhiyun * publish, distribute, sublicense, and/or sell copies of the Software,
11*4882a593Smuzhiyun * and to permit persons to whom the Software is furnished to do so,
12*4882a593Smuzhiyun * subject to the following conditions:
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun * The above copyright notice and this permission notice (including the
15*4882a593Smuzhiyun * next paragraph) shall be included in all copies or substantial
16*4882a593Smuzhiyun * portions of the Software.
17*4882a593Smuzhiyun *
18*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19*4882a593Smuzhiyun * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20*4882a593Smuzhiyun * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21*4882a593Smuzhiyun * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22*4882a593Smuzhiyun * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23*4882a593Smuzhiyun * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24*4882a593Smuzhiyun * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25*4882a593Smuzhiyun * SOFTWARE.
26*4882a593Smuzhiyun */
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun /*
29*4882a593Smuzhiyun * Authors:
30*4882a593Smuzhiyun * Rickard E. (Rik) Faith <faith@redhat.com>
31*4882a593Smuzhiyun *
32*4882a593Smuzhiyun */
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #include <stdio.h>
35*4882a593Smuzhiyun #include <stdlib.h>
36*4882a593Smuzhiyun #include <string.h>
37*4882a593Smuzhiyun #include <X11/Xlib.h>
38*4882a593Smuzhiyun #include <X11/XKBlib.h>
39*4882a593Smuzhiyun #include <X11/extensions/XInput.h>
40*4882a593Smuzhiyun #include <X11/extensions/XKB.h>
41*4882a593Smuzhiyun #include <X11/extensions/XKBstr.h>
42*4882a593Smuzhiyun #include <X11/extensions/dmxext.h>
43*4882a593Smuzhiyun #include <sys/time.h>
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun static const char *
core(DMXInputAttributes * iinf)46*4882a593Smuzhiyun core(DMXInputAttributes * iinf)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun if (iinf->isCore)
49*4882a593Smuzhiyun return "core";
50*4882a593Smuzhiyun else if (iinf->sendsCore)
51*4882a593Smuzhiyun return "extension (sends core events)";
52*4882a593Smuzhiyun else
53*4882a593Smuzhiyun return "extension";
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun static void
printdmxinfo(Display * display,int id)57*4882a593Smuzhiyun printdmxinfo(Display * display, int id)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun int event_base;
60*4882a593Smuzhiyun int error_base;
61*4882a593Smuzhiyun int major_version, minor_version, patch_version;
62*4882a593Smuzhiyun DMXInputAttributes iinf;
63*4882a593Smuzhiyun Display *backend;
64*4882a593Smuzhiyun char *backendname = NULL;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun if (!DMXQueryExtension(display, &event_base, &error_base))
67*4882a593Smuzhiyun return;
68*4882a593Smuzhiyun if (!DMXQueryVersion(display, &major_version, &minor_version,
69*4882a593Smuzhiyun &patch_version))
70*4882a593Smuzhiyun return;
71*4882a593Smuzhiyun if (major_version == 1 && minor_version == 0)
72*4882a593Smuzhiyun return; /* too old */
73*4882a593Smuzhiyun if (!DMXGetInputAttributes(display, id, &iinf))
74*4882a593Smuzhiyun return;
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun printf(" DMX Information: ");
77*4882a593Smuzhiyun if (iinf.detached)
78*4882a593Smuzhiyun printf("detached ");
79*4882a593Smuzhiyun else
80*4882a593Smuzhiyun printf("active ");
81*4882a593Smuzhiyun switch (iinf.inputType) {
82*4882a593Smuzhiyun case DMXLocalInputType:
83*4882a593Smuzhiyun printf("local, %s", core(&iinf));
84*4882a593Smuzhiyun break;
85*4882a593Smuzhiyun case DMXConsoleInputType:
86*4882a593Smuzhiyun printf("console %s, %s", iinf.name, core(&iinf));
87*4882a593Smuzhiyun break;
88*4882a593Smuzhiyun case DMXBackendInputType:
89*4882a593Smuzhiyun if (iinf.physicalId >= 0) {
90*4882a593Smuzhiyun if ((backend = XOpenDisplay(iinf.name))) {
91*4882a593Smuzhiyun XExtensionVersion *ext = XGetExtensionVersion(backend, INAME);
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun if (ext && ext != (XExtensionVersion *) NoSuchExtension) {
94*4882a593Smuzhiyun int count, i;
95*4882a593Smuzhiyun XDeviceInfo *devInfo = XListInputDevices(backend, &count);
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun if (devInfo) {
98*4882a593Smuzhiyun for (i = 0; i < count; i++) {
99*4882a593Smuzhiyun if ((unsigned) iinf.physicalId == devInfo[i].id
100*4882a593Smuzhiyun && devInfo[i].name) {
101*4882a593Smuzhiyun backendname = strdup(devInfo[i].name);
102*4882a593Smuzhiyun break;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun XFreeDeviceList(devInfo);
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun XCloseDisplay(backend);
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun printf("backend o%d/%s", iinf.physicalScreen, iinf.name);
112*4882a593Smuzhiyun if (iinf.physicalId >= 0)
113*4882a593Smuzhiyun printf("/id%d", iinf.physicalId);
114*4882a593Smuzhiyun if (backendname) {
115*4882a593Smuzhiyun printf("=%s", backendname);
116*4882a593Smuzhiyun free(backendname);
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun printf(" %s", core(&iinf));
119*4882a593Smuzhiyun break;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun printf("\n");
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun int
main(int argc,char ** argv)125*4882a593Smuzhiyun main(int argc, char **argv)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun Display *display = NULL;
128*4882a593Smuzhiyun int device = -1;
129*4882a593Smuzhiyun int newmouse = -1;
130*4882a593Smuzhiyun int newkbd = -1;
131*4882a593Smuzhiyun int count;
132*4882a593Smuzhiyun int i, j;
133*4882a593Smuzhiyun XDeviceInfo *devInfo;
134*4882a593Smuzhiyun XExtensionVersion *ext;
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun if (argc == 2 || argc == 3 || argc == 4 || argc == 5) {
137*4882a593Smuzhiyun if (!(display = XOpenDisplay(argv[1]))) {
138*4882a593Smuzhiyun printf("Cannot open display %s\n", argv[1]);
139*4882a593Smuzhiyun return -1;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun if (argc >= 3)
142*4882a593Smuzhiyun device = strtol(argv[2], NULL, 0);
143*4882a593Smuzhiyun if (argc >= 4)
144*4882a593Smuzhiyun newmouse = strtol(argv[3], NULL, 0);
145*4882a593Smuzhiyun if (argc >= 5)
146*4882a593Smuzhiyun newkbd = strtol(argv[4], NULL, 0);
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun else {
149*4882a593Smuzhiyun printf("Usage: %s display [device] [newmouse] [newkbd]\n", argv[0]);
150*4882a593Smuzhiyun return -1;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun if (!display && !(display = XOpenDisplay(NULL))) {
154*4882a593Smuzhiyun printf("Cannot open default display\n");
155*4882a593Smuzhiyun return -1;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun ext = XGetExtensionVersion(display, INAME);
159*4882a593Smuzhiyun if (!ext || ext == (XExtensionVersion *) NoSuchExtension) {
160*4882a593Smuzhiyun printf("No XInputExtension\n");
161*4882a593Smuzhiyun return -1;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun printf("%s version %d.%d\n", INAME, ext->major_version, ext->minor_version);
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun if (!(devInfo = XListInputDevices(display, &count)) || !count) {
166*4882a593Smuzhiyun printf("Cannot list devices\n");
167*4882a593Smuzhiyun return -1;
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun for (i = 0; i < count; i++) {
171*4882a593Smuzhiyun XAnyClassPtr any;
172*4882a593Smuzhiyun const char *kind = "Unknown";
173*4882a593Smuzhiyun int has_key = 0;
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun switch (devInfo[i].use) {
176*4882a593Smuzhiyun case IsXPointer:
177*4882a593Smuzhiyun kind = "XPointer";
178*4882a593Smuzhiyun break;
179*4882a593Smuzhiyun case IsXKeyboard:
180*4882a593Smuzhiyun kind = "XKeyboard";
181*4882a593Smuzhiyun break;
182*4882a593Smuzhiyun case IsXExtensionDevice:
183*4882a593Smuzhiyun kind = "XExtensionDevice";
184*4882a593Smuzhiyun break;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun printf("%2lu %-20.20s %-16.16s",
187*4882a593Smuzhiyun (long unsigned) devInfo[i].id,
188*4882a593Smuzhiyun devInfo[i].name ? devInfo[i].name : "", kind);
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun for (j = 0, any = devInfo[i].inputclassinfo;
191*4882a593Smuzhiyun j < devInfo[i].num_classes;
192*4882a593Smuzhiyun any = (XAnyClassPtr) ((char *) any + any->length), j++) {
193*4882a593Smuzhiyun const char *class = "unk";
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun switch (any->class) {
196*4882a593Smuzhiyun case KeyClass:
197*4882a593Smuzhiyun class = "key";
198*4882a593Smuzhiyun ++has_key;
199*4882a593Smuzhiyun break;
200*4882a593Smuzhiyun case ButtonClass:
201*4882a593Smuzhiyun class = "btn";
202*4882a593Smuzhiyun break;
203*4882a593Smuzhiyun case ValuatorClass:
204*4882a593Smuzhiyun class = "val";
205*4882a593Smuzhiyun break;
206*4882a593Smuzhiyun case FeedbackClass:
207*4882a593Smuzhiyun class = "fdb";
208*4882a593Smuzhiyun break;
209*4882a593Smuzhiyun case ProximityClass:
210*4882a593Smuzhiyun class = "prx";
211*4882a593Smuzhiyun break;
212*4882a593Smuzhiyun case FocusClass:
213*4882a593Smuzhiyun class = "foc";
214*4882a593Smuzhiyun break;
215*4882a593Smuzhiyun case OtherClass:
216*4882a593Smuzhiyun class = "oth";
217*4882a593Smuzhiyun break;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun printf(" %s", class);
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun printf("\n");
222*4882a593Smuzhiyun printdmxinfo(display, i);
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun if (has_key) {
225*4882a593Smuzhiyun XkbDescPtr xkb;
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun if ((xkb = XkbGetKeyboard(display,
228*4882a593Smuzhiyun XkbAllComponentsMask, devInfo[i].id))) {
229*4882a593Smuzhiyun printf(" Xkb Information:\n");
230*4882a593Smuzhiyun printf(" Device id = %d\n", xkb->device_spec);
231*4882a593Smuzhiyun printf(" Min keycode = 0x%02x\n", xkb->min_key_code);
232*4882a593Smuzhiyun printf(" Max keycode = 0x%02x\n", xkb->max_key_code);
233*4882a593Smuzhiyun #define PRINTNAME(x) \
234*4882a593Smuzhiyun printf(" %s = %s\n", \
235*4882a593Smuzhiyun #x, xkb->names->x ? XGetAtomName(display, xkb->names->x) : "")
236*4882a593Smuzhiyun PRINTNAME(keycodes);
237*4882a593Smuzhiyun PRINTNAME(geometry);
238*4882a593Smuzhiyun PRINTNAME(symbols);
239*4882a593Smuzhiyun PRINTNAME(types);
240*4882a593Smuzhiyun PRINTNAME(compat);
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun if (newmouse >= 0) {
246*4882a593Smuzhiyun XDevice *dev;
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun printf("Trying to make device %d core mouse\n", newmouse);
249*4882a593Smuzhiyun dev = XOpenDevice(display, devInfo[newmouse].id);
250*4882a593Smuzhiyun printf("Status = %d\n", XChangePointerDevice(display, dev, 0, 1));
251*4882a593Smuzhiyun return 0;
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun if (newkbd >= 0) {
255*4882a593Smuzhiyun XDevice *dev;
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun printf("Trying to make device %d core keyboard\n", newkbd);
258*4882a593Smuzhiyun dev = XOpenDevice(display, devInfo[newkbd].id);
259*4882a593Smuzhiyun printf("Status = %d\n", XChangeKeyboardDevice(display, dev));
260*4882a593Smuzhiyun return 0;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun if (device >= 0) {
264*4882a593Smuzhiyun #define MAX_EVENTS 100
265*4882a593Smuzhiyun int cnt = 0;
266*4882a593Smuzhiyun XDevice *dev;
267*4882a593Smuzhiyun XEventClass event_list[MAX_EVENTS];
268*4882a593Smuzhiyun int event_type[MAX_EVENTS];
269*4882a593Smuzhiyun const char *names[MAX_EVENTS];
270*4882a593Smuzhiyun int total = 0;
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun #define ADD(type) \
273*4882a593Smuzhiyun if (cnt >= MAX_EVENTS) abort(); \
274*4882a593Smuzhiyun names[cnt] = #type; \
275*4882a593Smuzhiyun type(dev, event_type[cnt], event_list[cnt]); \
276*4882a593Smuzhiyun if (event_type[cnt]) ++cnt
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun dev = XOpenDevice(display, devInfo[device].id);
279*4882a593Smuzhiyun ADD(DeviceKeyPress);
280*4882a593Smuzhiyun ADD(DeviceKeyRelease);
281*4882a593Smuzhiyun ADD(DeviceButtonPress);
282*4882a593Smuzhiyun ADD(DeviceButtonRelease);
283*4882a593Smuzhiyun ADD(DeviceMotionNotify);
284*4882a593Smuzhiyun ADD(DeviceFocusIn);
285*4882a593Smuzhiyun ADD(DeviceFocusOut);
286*4882a593Smuzhiyun ADD(ProximityIn);
287*4882a593Smuzhiyun ADD(ProximityOut);
288*4882a593Smuzhiyun ADD(DeviceStateNotify);
289*4882a593Smuzhiyun ADD(DeviceMappingNotify);
290*4882a593Smuzhiyun ADD(ChangeDeviceNotify);
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun for (i = 0; i < cnt; i++) {
293*4882a593Smuzhiyun printf("Waiting for %s events of type %d (%lu) on 0x%08lx\n",
294*4882a593Smuzhiyun names[i],
295*4882a593Smuzhiyun event_type[i], (unsigned long) event_list[i],
296*4882a593Smuzhiyun (long unsigned) DefaultRootWindow(display));
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun XSelectExtensionEvent(display, DefaultRootWindow(display),
299*4882a593Smuzhiyun event_list, cnt);
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun for (;;) {
302*4882a593Smuzhiyun XEvent event;
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun XNextEvent(display, &event);
305*4882a593Smuzhiyun for (i = 0; i < cnt; i++) {
306*4882a593Smuzhiyun XDeviceMotionEvent *e = (XDeviceMotionEvent *) &event;
307*4882a593Smuzhiyun XDeviceButtonEvent *b = (XDeviceButtonEvent *) &event;
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun if (event.type == event_type[i]) {
310*4882a593Smuzhiyun printf("%s id=%lu (%d @ %d,%d; s=0x%04x, d=%d, t=%lu)"
311*4882a593Smuzhiyun " axes_count=%d first=%d %d %d %d %d %d %d\n",
312*4882a593Smuzhiyun names[i],
313*4882a593Smuzhiyun (long unsigned) e->deviceid,
314*4882a593Smuzhiyun e->type,
315*4882a593Smuzhiyun e->x, e->y,
316*4882a593Smuzhiyun e->device_state,
317*4882a593Smuzhiyun b->button,
318*4882a593Smuzhiyun (long unsigned) b->time,
319*4882a593Smuzhiyun e->axes_count,
320*4882a593Smuzhiyun e->first_axis,
321*4882a593Smuzhiyun e->axis_data[0],
322*4882a593Smuzhiyun e->axis_data[1],
323*4882a593Smuzhiyun e->axis_data[2],
324*4882a593Smuzhiyun e->axis_data[3], e->axis_data[4], e->axis_data[5]);
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun ++total;
328*4882a593Smuzhiyun #if 0
329*4882a593Smuzhiyun /* Used to check motion history for
330*4882a593Smuzhiyun * extension devices. */
331*4882a593Smuzhiyun if (!(total % 10)) {
332*4882a593Smuzhiyun XDeviceTimeCoord *tc;
333*4882a593Smuzhiyun int n, m, a;
334*4882a593Smuzhiyun struct timeval tv;
335*4882a593Smuzhiyun unsigned long ms;
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun gettimeofday(&tv, NULL);
338*4882a593Smuzhiyun ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
339*4882a593Smuzhiyun tc = XGetDeviceMotionEvents(display, dev, ms - 1000, ms,
340*4882a593Smuzhiyun &n, &m, &a);
341*4882a593Smuzhiyun printf("Got %d events of mode %s with %d axes\n",
342*4882a593Smuzhiyun n, m == Absolute ? "Absolute" : "Relative", a);
343*4882a593Smuzhiyun for (i = 0; i < n && i < 10; i++) {
344*4882a593Smuzhiyun printf(" %d: %lu %d %d\n",
345*4882a593Smuzhiyun i, tc[i].time, tc[i].data[0], tc[i].data[1]);
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun XFreeDeviceMotionEvents(tc);
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun #endif
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun XCloseDisplay(display);
354*4882a593Smuzhiyun return 0;
355*4882a593Smuzhiyun }
356