1706f2543Smrg/* 2706f2543Smrg * Copyright 2001,2002 Red Hat Inc., Durham, North Carolina. 3706f2543Smrg * 4706f2543Smrg * All Rights Reserved. 5706f2543Smrg * 6706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining 7706f2543Smrg * a copy of this software and associated documentation files (the 8706f2543Smrg * "Software"), to deal in the Software without restriction, including 9706f2543Smrg * without limitation on the rights to use, copy, modify, merge, 10706f2543Smrg * publish, distribute, sublicense, and/or sell copies of the Software, 11706f2543Smrg * and to permit persons to whom the Software is furnished to do so, 12706f2543Smrg * subject to the following conditions: 13706f2543Smrg * 14706f2543Smrg * The above copyright notice and this permission notice (including the 15706f2543Smrg * next paragraph) shall be included in all copies or substantial 16706f2543Smrg * portions of the Software. 17706f2543Smrg * 18706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19706f2543Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20706f2543Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21706f2543Smrg * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS 22706f2543Smrg * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23706f2543Smrg * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24706f2543Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25706f2543Smrg * SOFTWARE. 26706f2543Smrg */ 27706f2543Smrg 28706f2543Smrg/* 29706f2543Smrg * Authors: 30706f2543Smrg * Rickard E. (Rik) Faith <faith@redhat.com> 31706f2543Smrg * 32706f2543Smrg */ 33706f2543Smrg 34706f2543Smrg#include <stdio.h> 35706f2543Smrg#include <stdlib.h> 36706f2543Smrg#include <string.h> 37706f2543Smrg#include <X11/Xlib.h> 38706f2543Smrg#include <X11/XKBlib.h> 39706f2543Smrg#include <X11/extensions/XInput.h> 40706f2543Smrg#include <X11/extensions/XKB.h> 41706f2543Smrg#include <X11/extensions/XKBstr.h> 42706f2543Smrg#include <X11/extensions/dmxext.h> 43706f2543Smrg#include <sys/time.h> 44706f2543Smrg 45706f2543Smrgstatic const char *core(DMXInputAttributes *iinf) 46706f2543Smrg{ 47706f2543Smrg if (iinf->isCore) return "core"; 48706f2543Smrg else if (iinf->sendsCore) return "extension (sends core events)"; 49706f2543Smrg else return "extension"; 50706f2543Smrg} 51706f2543Smrg 52706f2543Smrgstatic void printdmxinfo(Display *display, int id) 53706f2543Smrg{ 54706f2543Smrg int event_base; 55706f2543Smrg int error_base; 56706f2543Smrg int major_version, minor_version, patch_version; 57706f2543Smrg DMXInputAttributes iinf; 58706f2543Smrg Display *backend; 59706f2543Smrg char *backendname = NULL; 60706f2543Smrg 61706f2543Smrg if (!DMXQueryExtension(display, &event_base, &error_base)) return; 62706f2543Smrg if (!DMXQueryVersion(display, &major_version, &minor_version, 63706f2543Smrg &patch_version)) return; 64706f2543Smrg if (major_version == 1 && minor_version == 0) return; /* too old */ 65706f2543Smrg if (!DMXGetInputAttributes(display, id, &iinf)) return; 66706f2543Smrg 67706f2543Smrg printf(" DMX Information: "); 68706f2543Smrg if (iinf.detached) printf("detached "); 69706f2543Smrg else printf("active "); 70706f2543Smrg switch (iinf.inputType) { 71706f2543Smrg case DMXLocalInputType: 72706f2543Smrg printf("local, %s", core(&iinf)); 73706f2543Smrg break; 74706f2543Smrg case DMXConsoleInputType: 75706f2543Smrg printf("console %s, %s", iinf.name, core(&iinf)); 76706f2543Smrg break; 77706f2543Smrg case DMXBackendInputType: 78706f2543Smrg if (iinf.physicalId >= 0) { 79706f2543Smrg if ((backend = XOpenDisplay(iinf.name))) { 80706f2543Smrg XExtensionVersion *ext = XGetExtensionVersion(backend, INAME); 81706f2543Smrg if (ext && ext != (XExtensionVersion *)NoSuchExtension) { 82706f2543Smrg int count, i; 83706f2543Smrg XDeviceInfo *devInfo = XListInputDevices(backend, &count); 84706f2543Smrg if (devInfo) { 85706f2543Smrg for (i = 0; i < count; i++) { 86706f2543Smrg if ((unsigned)iinf.physicalId == devInfo[i].id 87706f2543Smrg && devInfo[i].name) { 88706f2543Smrg backendname = strdup(devInfo[i].name); 89706f2543Smrg break; 90706f2543Smrg } 91706f2543Smrg } 92706f2543Smrg XFreeDeviceList(devInfo); 93706f2543Smrg } 94706f2543Smrg } 95706f2543Smrg XCloseDisplay(backend); 96706f2543Smrg } 97706f2543Smrg } 98706f2543Smrg printf("backend o%d/%s",iinf.physicalScreen, iinf.name); 99706f2543Smrg if (iinf.physicalId >= 0) printf("/id%d", iinf.physicalId); 100706f2543Smrg if (backendname) { 101706f2543Smrg printf("=%s", backendname); 102706f2543Smrg free(backendname); 103706f2543Smrg } 104706f2543Smrg printf(" %s", core(&iinf)); 105706f2543Smrg break; 106706f2543Smrg } 107706f2543Smrg printf("\n"); 108706f2543Smrg} 109706f2543Smrg 110706f2543Smrgint main(int argc, char **argv) 111706f2543Smrg{ 112706f2543Smrg Display *display = NULL; 113706f2543Smrg int device = -1; 114706f2543Smrg int newmouse = -1; 115706f2543Smrg int newkbd = -1; 116706f2543Smrg int count; 117706f2543Smrg int i, j; 118706f2543Smrg XDeviceInfo *devInfo; 119706f2543Smrg XExtensionVersion *ext; 120706f2543Smrg 121706f2543Smrg if (argc == 2 || argc == 3 || argc == 4 || argc == 5) { 122706f2543Smrg if (!(display = XOpenDisplay(argv[1]))) { 123706f2543Smrg printf("Cannot open display %s\n", argv[1]); 124706f2543Smrg return -1; 125706f2543Smrg } 126706f2543Smrg if (argc >= 3) device = strtol(argv[2], NULL, 0); 127706f2543Smrg if (argc >= 4) newmouse = strtol(argv[3], NULL, 0); 128706f2543Smrg if (argc >= 5) newkbd = strtol(argv[4], NULL, 0); 129706f2543Smrg } else { 130706f2543Smrg printf("Usage: %s display [device] [newmouse] [newkbd]\n", argv[0]); 131706f2543Smrg return -1; 132706f2543Smrg } 133706f2543Smrg 134706f2543Smrg if (!display && !(display = XOpenDisplay(NULL))) { 135706f2543Smrg printf("Cannot open default display\n"); 136706f2543Smrg return -1; 137706f2543Smrg } 138706f2543Smrg 139706f2543Smrg ext = XGetExtensionVersion(display, INAME); 140706f2543Smrg if (!ext || ext == (XExtensionVersion *)NoSuchExtension) { 141706f2543Smrg printf("No XInputExtension\n"); 142706f2543Smrg return -1; 143706f2543Smrg } 144706f2543Smrg printf("%s version %d.%d\n", 145706f2543Smrg INAME, ext->major_version, ext->minor_version); 146706f2543Smrg 147706f2543Smrg if (!(devInfo = XListInputDevices(display, &count)) || !count) { 148706f2543Smrg printf("Cannot list devices\n"); 149706f2543Smrg return -1; 150706f2543Smrg } 151706f2543Smrg 152706f2543Smrg for (i = 0; i < count; i++) { 153706f2543Smrg XAnyClassPtr any; 154706f2543Smrg const char *kind = "Unknown"; 155706f2543Smrg int has_key = 0; 156706f2543Smrg 157706f2543Smrg switch (devInfo[i].use) { 158706f2543Smrg case IsXPointer: kind = "XPointer"; break; 159706f2543Smrg case IsXKeyboard: kind = "XKeyboard"; break; 160706f2543Smrg case IsXExtensionDevice: kind = "XExtensionDevice"; break; 161706f2543Smrg } 162706f2543Smrg printf("%2lu %-20.20s %-16.16s", 163706f2543Smrg (long unsigned)devInfo[i].id, 164706f2543Smrg devInfo[i].name ? devInfo[i].name : "", kind); 165706f2543Smrg 166706f2543Smrg for (j = 0, any = devInfo[i].inputclassinfo; 167706f2543Smrg j < devInfo[i].num_classes; 168706f2543Smrg any = (XAnyClassPtr)((char *)any + any->length), j++) { 169706f2543Smrg const char *class = "unk"; 170706f2543Smrg switch (any->class) { 171706f2543Smrg case KeyClass: class = "key"; ++has_key; break; 172706f2543Smrg case ButtonClass: class = "btn"; break; 173706f2543Smrg case ValuatorClass: class = "val"; break; 174706f2543Smrg case FeedbackClass: class = "fdb"; break; 175706f2543Smrg case ProximityClass: class = "prx"; break; 176706f2543Smrg case FocusClass: class = "foc"; break; 177706f2543Smrg case OtherClass: class = "oth"; break; 178706f2543Smrg } 179706f2543Smrg printf(" %s", class); 180706f2543Smrg } 181706f2543Smrg printf("\n"); 182706f2543Smrg printdmxinfo(display, i); 183706f2543Smrg 184706f2543Smrg if (has_key) { 185706f2543Smrg XkbDescPtr xkb; 186706f2543Smrg if ((xkb = XkbGetKeyboard(display, 187706f2543Smrg XkbAllComponentsMask, 188706f2543Smrg devInfo[i].id))) { 189706f2543Smrg printf(" Xkb Information:\n"); 190706f2543Smrg printf(" Device id = %d\n", xkb->device_spec); 191706f2543Smrg printf(" Min keycode = 0x%02x\n", xkb->min_key_code); 192706f2543Smrg printf(" Max keycode = 0x%02x\n", xkb->max_key_code); 193706f2543Smrg#define PRINTNAME(x) \ 194706f2543Smrg printf(" %s = %s\n", \ 195706f2543Smrg #x, xkb->names->x ? XGetAtomName(display, xkb->names->x) : "") 196706f2543Smrg PRINTNAME(keycodes); 197706f2543Smrg PRINTNAME(geometry); 198706f2543Smrg PRINTNAME(symbols); 199706f2543Smrg PRINTNAME(types); 200706f2543Smrg PRINTNAME(compat); 201706f2543Smrg } 202706f2543Smrg } 203706f2543Smrg } 204706f2543Smrg 205706f2543Smrg if (newmouse >= 0) { 206706f2543Smrg XDevice *dev; 207706f2543Smrg 208706f2543Smrg printf("Trying to make device %d core mouse\n", newmouse); 209706f2543Smrg dev = XOpenDevice(display, devInfo[newmouse].id); 210706f2543Smrg printf("Status = %d\n", 211706f2543Smrg XChangePointerDevice(display, dev, 0, 1)); 212706f2543Smrg return 0; 213706f2543Smrg } 214706f2543Smrg 215706f2543Smrg if (newkbd >= 0) { 216706f2543Smrg XDevice *dev; 217706f2543Smrg 218706f2543Smrg printf("Trying to make device %d core keyboard\n", newkbd); 219706f2543Smrg dev = XOpenDevice(display, devInfo[newkbd].id); 220706f2543Smrg printf("Status = %d\n", 221706f2543Smrg XChangeKeyboardDevice(display, dev)); 222706f2543Smrg return 0; 223706f2543Smrg } 224706f2543Smrg 225706f2543Smrg 226706f2543Smrg if (device >=0){ 227706f2543Smrg#define MAX_EVENTS 100 228706f2543Smrg int cnt = 0; 229706f2543Smrg XDevice *dev; 230706f2543Smrg XEventClass event_list[MAX_EVENTS]; 231706f2543Smrg int event_type[MAX_EVENTS]; 232706f2543Smrg const char *names[MAX_EVENTS]; 233706f2543Smrg int total = 0; 234706f2543Smrg 235706f2543Smrg#define ADD(type) \ 236706f2543Smrg if (cnt >= MAX_EVENTS) abort(); \ 237706f2543Smrg names[cnt] = #type; \ 238706f2543Smrg type(dev, event_type[cnt], event_list[cnt]); \ 239706f2543Smrg if (event_type[cnt]) ++cnt 240706f2543Smrg 241706f2543Smrg 242706f2543Smrg dev = XOpenDevice(display, devInfo[device].id); 243706f2543Smrg ADD(DeviceKeyPress); 244706f2543Smrg ADD(DeviceKeyRelease); 245706f2543Smrg ADD(DeviceButtonPress); 246706f2543Smrg ADD(DeviceButtonRelease); 247706f2543Smrg ADD(DeviceMotionNotify); 248706f2543Smrg ADD(DeviceFocusIn); 249706f2543Smrg ADD(DeviceFocusOut); 250706f2543Smrg ADD(ProximityIn); 251706f2543Smrg ADD(ProximityOut); 252706f2543Smrg ADD(DeviceStateNotify); 253706f2543Smrg ADD(DeviceMappingNotify); 254706f2543Smrg ADD(ChangeDeviceNotify); 255706f2543Smrg 256706f2543Smrg for (i = 0; i < cnt; i++) { 257706f2543Smrg printf("Waiting for %s events of type %d (%lu) on 0x%08lx\n", 258706f2543Smrg names[i], 259706f2543Smrg event_type[i], (unsigned long)event_list[i], 260706f2543Smrg (long unsigned)DefaultRootWindow(display)); 261706f2543Smrg } 262706f2543Smrg XSelectExtensionEvent(display, DefaultRootWindow(display), 263706f2543Smrg event_list, cnt); 264706f2543Smrg 265706f2543Smrg for (;;) { 266706f2543Smrg XEvent event; 267706f2543Smrg XNextEvent(display, &event); 268706f2543Smrg for (i = 0; i < cnt; i++) { 269706f2543Smrg XDeviceMotionEvent *e = (XDeviceMotionEvent *)&event; 270706f2543Smrg XDeviceButtonEvent *b = (XDeviceButtonEvent *)&event; 271706f2543Smrg if (event.type == event_type[i]) { 272706f2543Smrg printf("%s id=%lu (%d @ %d,%d; s=0x%04x, d=%d, t=%lu)" 273706f2543Smrg " axes_count=%d first=%d %d %d %d %d %d %d\n", 274706f2543Smrg names[i], 275706f2543Smrg (long unsigned)e->deviceid, 276706f2543Smrg e->type, 277706f2543Smrg e->x, e->y, 278706f2543Smrg e->device_state, 279706f2543Smrg b->button, 280706f2543Smrg (long unsigned)b->time, 281706f2543Smrg e->axes_count, 282706f2543Smrg e->first_axis, 283706f2543Smrg e->axis_data[0], 284706f2543Smrg e->axis_data[1], 285706f2543Smrg e->axis_data[2], 286706f2543Smrg e->axis_data[3], 287706f2543Smrg e->axis_data[4], 288706f2543Smrg e->axis_data[5]); 289706f2543Smrg } 290706f2543Smrg } 291706f2543Smrg ++total; 292706f2543Smrg#if 0 293706f2543Smrg /* Used to check motion history for 294706f2543Smrg * extension devices. */ 295706f2543Smrg if (!(total % 10)) { 296706f2543Smrg XDeviceTimeCoord *tc; 297706f2543Smrg int n, m, a; 298706f2543Smrg struct timeval tv; 299706f2543Smrg unsigned long ms; 300706f2543Smrg gettimeofday(&tv, NULL); 301706f2543Smrg ms = tv.tv_sec * 1000 + tv.tv_usec / 1000; 302706f2543Smrg tc = XGetDeviceMotionEvents(display, dev, ms-1000, ms, 303706f2543Smrg &n, &m, &a); 304706f2543Smrg printf("Got %d events of mode %s with %d axes\n", 305706f2543Smrg n, m == Absolute ? "Absolute" : "Relative", a); 306706f2543Smrg for (i = 0; i < n && i < 10; i++) { 307706f2543Smrg printf(" %d: %lu %d %d\n", 308706f2543Smrg i, tc[i].time, tc[i].data[0], tc[i].data[1]); 309706f2543Smrg } 310706f2543Smrg XFreeDeviceMotionEvents(tc); 311706f2543Smrg } 312706f2543Smrg#endif 313706f2543Smrg } 314706f2543Smrg } 315706f2543Smrg 316706f2543Smrg XCloseDisplay(display); 317706f2543Smrg return 0; 318706f2543Smrg} 319