1b1297603Smrg/* 2b1297603Smrg * Copyright 1996 by Frederic Lepied, France. <Frederic.Lepied@sugix.frmug.org> 3b1297603Smrg * 4b1297603Smrg * Permission to use, copy, modify, distribute, and sell this software and its 5b1297603Smrg * documentation for any purpose is hereby granted without fee, provided that 6b1297603Smrg * the above copyright notice appear in all copies and that both that 7b1297603Smrg * copyright notice and this permission notice appear in supporting 85b944e2aSmrg * documentation, and that the name of the authors not be used in 9b1297603Smrg * advertising or publicity pertaining to distribution of the software without 105b944e2aSmrg * specific, written prior permission. The authors make no 11b1297603Smrg * representations about the suitability of this software for any purpose. It 12b1297603Smrg * is provided "as is" without express or implied warranty. 13b1297603Smrg * 145b944e2aSmrg * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15b1297603Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 165b944e2aSmrg * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17b1297603Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18b1297603Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19b1297603Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20b1297603Smrg * PERFORMANCE OF THIS SOFTWARE. 21b1297603Smrg * 22b1297603Smrg */ 23b1297603Smrg 24b1297603Smrg#include "xinput.h" 25b1297603Smrg#include <string.h> 260309d3b3Smrg 270309d3b3Smrgenum print_format { 280309d3b3Smrg FORMAT_NONE, 290309d3b3Smrg FORMAT_SHORT, 300309d3b3Smrg FORMAT_LONG, 310309d3b3Smrg FORMAT_NAME, 320309d3b3Smrg FORMAT_ID, 330309d3b3Smrg}; 340309d3b3Smrg 35b1297603Smrg 36b1297603Smrgstatic void 370309d3b3Smrgprint_info(Display* dpy, XDeviceInfo *info, enum print_format format) 38b1297603Smrg{ 39b1297603Smrg int i,j; 40b1297603Smrg XAnyClassPtr any; 41b1297603Smrg XKeyInfoPtr k; 42b1297603Smrg XButtonInfoPtr b; 43b1297603Smrg XValuatorInfoPtr v; 44b1297603Smrg XAxisInfoPtr a; 45b1297603Smrg 460309d3b3Smrg if (format == FORMAT_NAME) 470309d3b3Smrg { 480309d3b3Smrg printf("%s\n", info->name); 490309d3b3Smrg return; 500309d3b3Smrg } else if (format == FORMAT_ID) 510309d3b3Smrg { 520309d3b3Smrg printf("%ld\n", info->id); 530309d3b3Smrg return; 540309d3b3Smrg } 550309d3b3Smrg 56b1297603Smrg printf("\"%s\"\tid=%ld\t[", info->name, info->id); 57b1297603Smrg 58b1297603Smrg switch (info->use) { 59b1297603Smrg case IsXPointer: 60b1297603Smrg printf("XPointer"); 61b1297603Smrg break; 62b1297603Smrg case IsXKeyboard: 63b1297603Smrg printf("XKeyboard"); 64b1297603Smrg break; 65b1297603Smrg case IsXExtensionDevice: 66b1297603Smrg printf("XExtensionDevice"); 67b1297603Smrg break; 68b1297603Smrg case IsXExtensionKeyboard: 69b1297603Smrg printf("XExtensionKeyboard"); 70b1297603Smrg break; 71b1297603Smrg case IsXExtensionPointer: 72b1297603Smrg printf("XExtensionPointer"); 73b1297603Smrg break; 74b1297603Smrg default: 75b1297603Smrg printf("Unknown class"); 76b1297603Smrg break; 77b1297603Smrg } 78b1297603Smrg printf("]\n"); 79b1297603Smrg 800309d3b3Smrg if (format == FORMAT_SHORT) 81b1297603Smrg return; 82b1297603Smrg 8333734831Smrg if (info->type != None) { 8433734831Smrg char *type = XGetAtomName(dpy, info->type); 8533734831Smrg printf("\tType is %s\n", type); 8633734831Smrg XFree(type); 8733734831Smrg } 88d3263506Smrg 89b1297603Smrg if (info->num_classes > 0) { 90b1297603Smrg any = (XAnyClassPtr) (info->inputclassinfo); 91b1297603Smrg for (i=0; i<info->num_classes; i++) { 92b1297603Smrg switch (any->class) { 93b1297603Smrg case KeyClass: 94b1297603Smrg k = (XKeyInfoPtr) any; 95b1297603Smrg printf("\tNum_keys is %d\n", k->num_keys); 96b1297603Smrg printf("\tMin_keycode is %d\n", k->min_keycode); 97b1297603Smrg printf("\tMax_keycode is %d\n", k->max_keycode); 98b1297603Smrg break; 99b1297603Smrg 100b1297603Smrg case ButtonClass: 101b1297603Smrg b = (XButtonInfoPtr) any; 102b1297603Smrg printf("\tNum_buttons is %d\n", b->num_buttons); 103b1297603Smrg break; 104b1297603Smrg 105b1297603Smrg case ValuatorClass: 106b1297603Smrg v = (XValuatorInfoPtr) any; 107b1297603Smrg a = (XAxisInfoPtr) ((char *) v + 108b1297603Smrg sizeof (XValuatorInfo)); 109b1297603Smrg printf("\tNum_axes is %d\n", v->num_axes); 110b1297603Smrg printf("\tMode is %s\n", (v->mode == Absolute) ? "Absolute" : "Relative"); 111b1297603Smrg printf("\tMotion_buffer is %ld\n", v->motion_buffer); 112b1297603Smrg for (j=0; j<v->num_axes; j++, a++) { 113b1297603Smrg printf("\tAxis %d :\n", j); 114b1297603Smrg printf("\t\tMin_value is %d\n", a->min_value); 115b1297603Smrg printf("\t\tMax_value is %d\n", a->max_value); 116b1297603Smrg printf ("\t\tResolution is %d\n", a->resolution); 117b1297603Smrg } 118b1297603Smrg break; 119b1297603Smrg default: 120b1297603Smrg printf ("unknown class\n"); 121b1297603Smrg } 122b1297603Smrg any = (XAnyClassPtr) ((char *) any + any->length); 123b1297603Smrg } 124b1297603Smrg } 125b1297603Smrg} 126b1297603Smrg 12753719b08Smrgstatic int list_xi1(Display *display, 1280309d3b3Smrg enum print_format format) 129b1297603Smrg{ 130b1297603Smrg XDeviceInfo *info; 131b1297603Smrg int loop; 13253719b08Smrg int num_devices; 133b1297603Smrg 13453719b08Smrg info = XListInputDevices(display, &num_devices); 13553719b08Smrg for(loop=0; loop<num_devices; loop++) { 1360309d3b3Smrg print_info(display, info+loop, format); 13753719b08Smrg } 13853719b08Smrg return EXIT_SUCCESS; 13953719b08Smrg} 140b1297603Smrg 141a570218aSmrg#if HAVE_XI2 14253719b08Smrg/* also used from test_xi2.c */ 14353719b08Smrgvoid 14453719b08Smrgprint_classes_xi2(Display* display, XIAnyClassInfo **classes, 14553719b08Smrg int num_classes) 14653719b08Smrg{ 14753719b08Smrg int i, j; 1485b944e2aSmrg 14953719b08Smrg printf("\tReporting %d classes:\n", num_classes); 15053719b08Smrg for (i = 0; i < num_classes; i++) 15153719b08Smrg { 1520309d3b3Smrg printf("\t\tClass originated from: %d. Type: ", classes[i]->sourceid); 15353719b08Smrg switch(classes[i]->type) 1545b944e2aSmrg { 15553719b08Smrg case XIButtonClass: 15653719b08Smrg { 15753719b08Smrg XIButtonClassInfo *b = (XIButtonClassInfo*)classes[i]; 15853719b08Smrg char *name; 1590309d3b3Smrg printf("XIButtonClass\n"); 16053719b08Smrg printf("\t\tButtons supported: %d\n", b->num_buttons); 16153719b08Smrg printf("\t\tButton labels:"); 16253719b08Smrg for (j = 0; j < b->num_buttons; j++) 16353719b08Smrg { 16453719b08Smrg name = (b->labels[j]) ? XGetAtomName(display, b->labels[j]) : NULL; 1650309d3b3Smrg if (name) 1660309d3b3Smrg printf(" \"%s\"", name); 1670309d3b3Smrg else 1680309d3b3Smrg printf(" None"); 16953719b08Smrg XFree(name); 17053719b08Smrg } 17153719b08Smrg printf("\n"); 17253719b08Smrg printf("\t\tButton state:"); 17353719b08Smrg for (j = 0; j < b->state.mask_len * 8; j++) 17453719b08Smrg if (XIMaskIsSet(b->state.mask, j)) 17553719b08Smrg printf(" %d", j); 17653719b08Smrg printf("\n"); 17753719b08Smrg 17853719b08Smrg } 17953719b08Smrg break; 18053719b08Smrg case XIKeyClass: 18153719b08Smrg { 18253719b08Smrg XIKeyClassInfo *k = (XIKeyClassInfo*)classes[i]; 1830309d3b3Smrg printf("XIKeyClass\n"); 18453719b08Smrg printf("\t\tKeycodes supported: %d\n", k->num_keycodes); 18553719b08Smrg } 18653719b08Smrg break; 18753719b08Smrg case XIValuatorClass: 18853719b08Smrg { 18953719b08Smrg XIValuatorClassInfo *v = (XIValuatorClassInfo*)classes[i]; 19053719b08Smrg char *name = v->label ? XGetAtomName(display, v->label) : NULL; 19153719b08Smrg 1920309d3b3Smrg /* Bug in X servers 1.7..1.8.1, mode was | OutOfProximity */ 19354e0bb33Smrg v->mode &= DeviceMode; 19454e0bb33Smrg 1950309d3b3Smrg printf("XIValuatorClass\n"); 19653719b08Smrg printf("\t\tDetail for Valuator %d:\n", v->number); 19753719b08Smrg printf("\t\t Label: %s\n", (name) ? name : "None"); 19853719b08Smrg printf("\t\t Range: %f - %f\n", v->min, v->max); 19953719b08Smrg printf("\t\t Resolution: %d units/m\n", v->resolution); 20053719b08Smrg printf("\t\t Mode: %s\n", v->mode == Absolute ? "absolute" : 20153719b08Smrg "relative"); 20253719b08Smrg if (v->mode == Absolute) 20353719b08Smrg printf("\t\t Current value: %f\n", v->value); 20453719b08Smrg XFree(name); 20553719b08Smrg } 20653719b08Smrg break; 2070309d3b3Smrg#if HAVE_XI21 2080309d3b3Smrg case XIScrollClass: 2090309d3b3Smrg { 2100309d3b3Smrg XIScrollClassInfo *s = (XIScrollClassInfo*)classes[i]; 2110309d3b3Smrg 2120309d3b3Smrg printf("XIScrollClass\n"); 2130309d3b3Smrg printf("\t\tScroll info for Valuator %d\n", s->number); 2140309d3b3Smrg printf("\t\t type: %d (%s)\n", s->scroll_type, 2150309d3b3Smrg (s->scroll_type == XIScrollTypeHorizontal) ? "horizontal" : 2160309d3b3Smrg (s->scroll_type == XIScrollTypeVertical) ? "vertical" : "unknown"); 2170309d3b3Smrg printf("\t\t increment: %f\n", s->increment); 2180309d3b3Smrg printf("\t\t flags: 0x%x", s->flags); 2190309d3b3Smrg if (s->flags) { 2200309d3b3Smrg printf(" ("); 2210309d3b3Smrg if (s->flags & XIScrollFlagNoEmulation) 2220309d3b3Smrg printf(" no-emulation "); 2230309d3b3Smrg if (s->flags & XIScrollFlagPreferred) 2240309d3b3Smrg printf(" preferred "); 2250309d3b3Smrg printf(")"); 2260309d3b3Smrg } 2270309d3b3Smrg printf("\n"); 2280309d3b3Smrg } 2290309d3b3Smrg break; 2300309d3b3Smrg#endif 2310309d3b3Smrg#if HAVE_XI22 2320309d3b3Smrg case XITouchClass: 2330309d3b3Smrg { 2340309d3b3Smrg XITouchClassInfo *t = (XITouchClassInfo*)classes[i]; 2350309d3b3Smrg 2360309d3b3Smrg printf("XITouchClass\n"); 2370309d3b3Smrg printf("\t\tTouch mode: %s\n", 2380309d3b3Smrg (t->mode == XIDirectTouch) ? "direct" : "dependent"); 2390309d3b3Smrg printf("\t\tMax number of touches: %d\n", t->num_touches); 2400309d3b3Smrg } 2410309d3b3Smrg#endif 2425b944e2aSmrg } 24353719b08Smrg } 2445b944e2aSmrg 24553719b08Smrg printf("\n"); 24653719b08Smrg} 2475b944e2aSmrg 24853719b08Smrgstatic void 2490309d3b3Smrgprint_info_xi2(Display* display, XIDeviceInfo *dev, enum print_format format) 25053719b08Smrg{ 2510309d3b3Smrg if (format == FORMAT_NAME) 2520309d3b3Smrg { 2530309d3b3Smrg printf("%s\n", dev->name); 2540309d3b3Smrg return; 2550309d3b3Smrg } else if (format == FORMAT_ID) 2560309d3b3Smrg { 2570309d3b3Smrg printf("%d\n", dev->deviceid); 2580309d3b3Smrg return; 2590309d3b3Smrg } 2600309d3b3Smrg 26153719b08Smrg printf("%-40s\tid=%d\t[", dev->name, dev->deviceid); 26253719b08Smrg switch(dev->use) 26353719b08Smrg { 26453719b08Smrg case XIMasterPointer: 26553719b08Smrg printf("master pointer (%d)]\n", dev->attachment); 26653719b08Smrg break; 26753719b08Smrg case XIMasterKeyboard: 26853719b08Smrg printf("master keyboard (%d)]\n", dev->attachment); 26953719b08Smrg break; 27053719b08Smrg case XISlavePointer: 27153719b08Smrg printf("slave pointer (%d)]\n", dev->attachment); 27253719b08Smrg break; 27353719b08Smrg case XISlaveKeyboard: 27453719b08Smrg printf("slave keyboard (%d)]\n", dev->attachment); 27553719b08Smrg break; 27653719b08Smrg case XIFloatingSlave: 27753719b08Smrg printf("floating slave]\n"); 27853719b08Smrg break; 27953719b08Smrg } 28053719b08Smrg 2810309d3b3Smrg if (format == FORMAT_SHORT) 28253719b08Smrg return; 28353719b08Smrg 28453719b08Smrg if (!dev->enabled) 28553719b08Smrg printf("\tThis device is disabled\n"); 28653719b08Smrg 28753719b08Smrg print_classes_xi2(display, dev->classes, dev->num_classes); 28853719b08Smrg} 28953719b08Smrg 29053719b08Smrg 29153719b08Smrgstatic int 29253719b08Smrglist_xi2(Display *display, 2930309d3b3Smrg enum print_format format) 29453719b08Smrg{ 29553719b08Smrg int ndevices; 29653719b08Smrg int i, j; 29753719b08Smrg XIDeviceInfo *info, *dev; 29853719b08Smrg 29953719b08Smrg info = XIQueryDevice(display, XIAllDevices, &ndevices); 30053719b08Smrg 30153719b08Smrg for(i = 0; i < ndevices; i++) 30253719b08Smrg { 30353719b08Smrg dev = &info[i]; 30453719b08Smrg if (dev->use == XIMasterPointer || dev->use == XIMasterKeyboard) 30553719b08Smrg { 3060309d3b3Smrg if (format == FORMAT_SHORT || format == FORMAT_LONG) 3070309d3b3Smrg { 3080309d3b3Smrg if (dev->use == XIMasterPointer) 3090309d3b3Smrg printf("⎡ "); 3100309d3b3Smrg else 3110309d3b3Smrg printf("⎣ "); 3120309d3b3Smrg } 31353719b08Smrg 3140309d3b3Smrg print_info_xi2(display, dev, format); 31553719b08Smrg for (j = 0; j < ndevices; j++) 3165b944e2aSmrg { 31753719b08Smrg XIDeviceInfo* sd = &info[j]; 31853719b08Smrg 31953719b08Smrg if ((sd->use == XISlavePointer || sd->use == XISlaveKeyboard) && 32053719b08Smrg (sd->attachment == dev->deviceid)) 3215b944e2aSmrg { 3220309d3b3Smrg if (format == FORMAT_SHORT || format == FORMAT_LONG) 3230309d3b3Smrg printf("%s ↳ ", dev->use == XIMasterPointer ? "⎜" : " "); 3240309d3b3Smrg print_info_xi2(display, sd, format); 3255b944e2aSmrg } 3265b944e2aSmrg } 32753719b08Smrg } 32853719b08Smrg } 32953719b08Smrg 33053719b08Smrg for (i = 0; i < ndevices; i++) 33153719b08Smrg { 33253719b08Smrg dev = &info[i]; 33353719b08Smrg if (dev->use == XIFloatingSlave) 33453719b08Smrg { 33553719b08Smrg printf("∼ "); 3360309d3b3Smrg print_info_xi2(display, dev, format); 33753719b08Smrg } 33853719b08Smrg } 33953719b08Smrg 34053719b08Smrg 34153719b08Smrg XIFreeDeviceInfo(info); 34253719b08Smrg return EXIT_SUCCESS; 34353719b08Smrg} 3445b944e2aSmrg#endif 345b1297603Smrg 34653719b08Smrgint 34753719b08Smrglist(Display *display, 34853719b08Smrg int argc, 34953719b08Smrg char *argv[], 35053719b08Smrg char *name, 35153719b08Smrg char *desc) 35253719b08Smrg{ 3530309d3b3Smrg enum print_format format = FORMAT_NONE; 3540309d3b3Smrg int arg_dev = 1; 3550309d3b3Smrg 3560309d3b3Smrg if (argc >= 1) 3570309d3b3Smrg { 3580309d3b3Smrg if (strcmp(argv[0], "--short") == 0) 3590309d3b3Smrg format = FORMAT_SHORT; 3600309d3b3Smrg else if (strcmp(argv[0], "--long") == 0) 3610309d3b3Smrg format = FORMAT_LONG; 3620309d3b3Smrg else if (strcmp(argv[0], "--name-only") == 0) 3630309d3b3Smrg format = FORMAT_NAME; 3640309d3b3Smrg else if (strcmp(argv[0], "--id-only") == 0) 3650309d3b3Smrg format = FORMAT_ID; 3660309d3b3Smrg else 3670309d3b3Smrg arg_dev--; 3680309d3b3Smrg } 369b1297603Smrg 37053719b08Smrg if (argc > arg_dev) 37153719b08Smrg { 3720309d3b3Smrg if (format == FORMAT_NONE) 3730309d3b3Smrg format = FORMAT_LONG; 374a570218aSmrg#if HAVE_XI2 37553719b08Smrg if (xinput_version(display) == XI_2_Major) 37653719b08Smrg { 37753719b08Smrg XIDeviceInfo *info = xi2_find_device_info(display, argv[arg_dev]); 37853719b08Smrg 37953719b08Smrg if (!info) { 38053719b08Smrg fprintf(stderr, "unable to find device %s\n", argv[arg_dev]); 38153719b08Smrg return EXIT_FAILURE; 38253719b08Smrg } else { 3830309d3b3Smrg print_info_xi2(display, info, format); 38453719b08Smrg return EXIT_SUCCESS; 38553719b08Smrg } 38653719b08Smrg } else 38753719b08Smrg#endif 38853719b08Smrg { 38953719b08Smrg XDeviceInfo *info = find_device_info(display, argv[arg_dev], False); 39053719b08Smrg 39153719b08Smrg if (!info) { 39253719b08Smrg fprintf(stderr, "unable to find device %s\n", argv[arg_dev]); 39353719b08Smrg return EXIT_FAILURE; 39453719b08Smrg } else { 3950309d3b3Smrg print_info(display, info, format); 39653719b08Smrg return EXIT_SUCCESS; 39753719b08Smrg } 39853719b08Smrg } 39953719b08Smrg } else { 4000309d3b3Smrg if (format == FORMAT_NONE) 4010309d3b3Smrg format = FORMAT_SHORT; 402a570218aSmrg#if HAVE_XI2 40353719b08Smrg if (xinput_version(display) == XI_2_Major) 4040309d3b3Smrg return list_xi2(display, format); 40553719b08Smrg#endif 4060309d3b3Smrg return list_xi1(display, format); 407b1297603Smrg } 408b1297603Smrg} 409b1297603Smrg 410b1297603Smrg/* end of list.c */ 411