1/* 2 * Copyright 1996 by Frederic Lepied, France. <Frederic.Lepied@sugix.frmug.org> 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of the authors not be used in 9 * advertising or publicity pertaining to distribution of the software without 10 * specific, written prior permission. The authors make no 11 * representations about the suitability of this software for any purpose. It 12 * is provided "as is" without express or implied warranty. 13 * 14 * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 * 22 */ 23 24#include "xinput.h" 25#include <string.h> 26 27enum print_format { 28 FORMAT_NONE, 29 FORMAT_SHORT, 30 FORMAT_LONG, 31 FORMAT_NAME, 32 FORMAT_ID, 33}; 34 35 36static void 37print_info(Display* dpy, XDeviceInfo *info, enum print_format format) 38{ 39 int i,j; 40 XAnyClassPtr any; 41 XKeyInfoPtr k; 42 XButtonInfoPtr b; 43 XValuatorInfoPtr v; 44 XAxisInfoPtr a; 45 46 if (format == FORMAT_NAME) 47 { 48 printf("%s\n", info->name); 49 return; 50 } else if (format == FORMAT_ID) 51 { 52 printf("%ld\n", info->id); 53 return; 54 } 55 56 printf("\"%s\"\tid=%ld\t[", info->name, info->id); 57 58 switch (info->use) { 59 case IsXPointer: 60 printf("XPointer"); 61 break; 62 case IsXKeyboard: 63 printf("XKeyboard"); 64 break; 65 case IsXExtensionDevice: 66 printf("XExtensionDevice"); 67 break; 68 case IsXExtensionKeyboard: 69 printf("XExtensionKeyboard"); 70 break; 71 case IsXExtensionPointer: 72 printf("XExtensionPointer"); 73 break; 74 default: 75 printf("Unknown class"); 76 break; 77 } 78 printf("]\n"); 79 80 if (format == FORMAT_SHORT) 81 return; 82 83 if (info->type != None) { 84 char *type = XGetAtomName(dpy, info->type); 85 printf("\tType is %s\n", type); 86 XFree(type); 87 } 88 89 if (info->num_classes > 0) { 90 any = (XAnyClassPtr) (info->inputclassinfo); 91 for (i=0; i<info->num_classes; i++) { 92 switch (any->class) { 93 case KeyClass: 94 k = (XKeyInfoPtr) any; 95 printf("\tNum_keys is %d\n", k->num_keys); 96 printf("\tMin_keycode is %d\n", k->min_keycode); 97 printf("\tMax_keycode is %d\n", k->max_keycode); 98 break; 99 100 case ButtonClass: 101 b = (XButtonInfoPtr) any; 102 printf("\tNum_buttons is %d\n", b->num_buttons); 103 break; 104 105 case ValuatorClass: 106 v = (XValuatorInfoPtr) any; 107 a = (XAxisInfoPtr) ((char *) v + 108 sizeof (XValuatorInfo)); 109 printf("\tNum_axes is %d\n", v->num_axes); 110 printf("\tMode is %s\n", (v->mode == Absolute) ? "Absolute" : "Relative"); 111 printf("\tMotion_buffer is %ld\n", v->motion_buffer); 112 for (j=0; j<v->num_axes; j++, a++) { 113 printf("\tAxis %d :\n", j); 114 printf("\t\tMin_value is %d\n", a->min_value); 115 printf("\t\tMax_value is %d\n", a->max_value); 116 printf ("\t\tResolution is %d\n", a->resolution); 117 } 118 break; 119 default: 120 printf ("unknown class\n"); 121 } 122 any = (XAnyClassPtr) ((char *) any + any->length); 123 } 124 } 125} 126 127static int list_xi1(Display *display, 128 enum print_format format) 129{ 130 XDeviceInfo *info; 131 int loop; 132 int num_devices; 133 134 info = XListInputDevices(display, &num_devices); 135 for(loop=0; loop<num_devices; loop++) { 136 print_info(display, info+loop, format); 137 } 138 return EXIT_SUCCESS; 139} 140 141#if HAVE_XI2 142/* also used from test_xi2.c */ 143void 144print_classes_xi2(Display* display, XIAnyClassInfo **classes, 145 int num_classes) 146{ 147 int i, j; 148 149 printf("\tReporting %d classes:\n", num_classes); 150 for (i = 0; i < num_classes; i++) 151 { 152 printf("\t\tClass originated from: %d. Type: ", classes[i]->sourceid); 153 switch(classes[i]->type) 154 { 155 case XIButtonClass: 156 { 157 XIButtonClassInfo *b = (XIButtonClassInfo*)classes[i]; 158 char *name; 159 printf("XIButtonClass\n"); 160 printf("\t\tButtons supported: %d\n", b->num_buttons); 161 printf("\t\tButton labels:"); 162 for (j = 0; j < b->num_buttons; j++) 163 { 164 name = (b->labels[j]) ? XGetAtomName(display, b->labels[j]) : NULL; 165 if (name) 166 printf(" \"%s\"", name); 167 else 168 printf(" None"); 169 XFree(name); 170 } 171 printf("\n"); 172 printf("\t\tButton state:"); 173 for (j = 0; j < b->state.mask_len * 8; j++) 174 if (XIMaskIsSet(b->state.mask, j)) 175 printf(" %d", j); 176 printf("\n"); 177 178 } 179 break; 180 case XIKeyClass: 181 { 182 XIKeyClassInfo *k = (XIKeyClassInfo*)classes[i]; 183 printf("XIKeyClass\n"); 184 printf("\t\tKeycodes supported: %d\n", k->num_keycodes); 185 } 186 break; 187 case XIValuatorClass: 188 { 189 XIValuatorClassInfo *v = (XIValuatorClassInfo*)classes[i]; 190 char *name = v->label ? XGetAtomName(display, v->label) : NULL; 191 192 /* Bug in X servers 1.7..1.8.1, mode was | OutOfProximity */ 193 v->mode &= DeviceMode; 194 195 printf("XIValuatorClass\n"); 196 printf("\t\tDetail for Valuator %d:\n", v->number); 197 printf("\t\t Label: %s\n", (name) ? name : "None"); 198 printf("\t\t Range: %f - %f\n", v->min, v->max); 199 printf("\t\t Resolution: %d units/m\n", v->resolution); 200 printf("\t\t Mode: %s\n", v->mode == Absolute ? "absolute" : 201 "relative"); 202 if (v->mode == Absolute) 203 printf("\t\t Current value: %f\n", v->value); 204 XFree(name); 205 } 206 break; 207#if HAVE_XI21 208 case XIScrollClass: 209 { 210 XIScrollClassInfo *s = (XIScrollClassInfo*)classes[i]; 211 212 printf("XIScrollClass\n"); 213 printf("\t\tScroll info for Valuator %d\n", s->number); 214 printf("\t\t type: %d (%s)\n", s->scroll_type, 215 (s->scroll_type == XIScrollTypeHorizontal) ? "horizontal" : 216 (s->scroll_type == XIScrollTypeVertical) ? "vertical" : "unknown"); 217 printf("\t\t increment: %f\n", s->increment); 218 printf("\t\t flags: 0x%x", s->flags); 219 if (s->flags) { 220 printf(" ("); 221 if (s->flags & XIScrollFlagNoEmulation) 222 printf(" no-emulation "); 223 if (s->flags & XIScrollFlagPreferred) 224 printf(" preferred "); 225 printf(")"); 226 } 227 printf("\n"); 228 } 229 break; 230#endif 231#if HAVE_XI22 232 case XITouchClass: 233 { 234 XITouchClassInfo *t = (XITouchClassInfo*)classes[i]; 235 236 printf("XITouchClass\n"); 237 printf("\t\tTouch mode: %s\n", 238 (t->mode == XIDirectTouch) ? "direct" : "dependent"); 239 printf("\t\tMax number of touches: %d\n", t->num_touches); 240 } 241#endif 242 } 243 } 244 245 printf("\n"); 246} 247 248static void 249print_info_xi2(Display* display, XIDeviceInfo *dev, enum print_format format) 250{ 251 if (format == FORMAT_NAME) 252 { 253 printf("%s\n", dev->name); 254 return; 255 } else if (format == FORMAT_ID) 256 { 257 printf("%d\n", dev->deviceid); 258 return; 259 } 260 261 printf("%-40s\tid=%d\t[", dev->name, dev->deviceid); 262 switch(dev->use) 263 { 264 case XIMasterPointer: 265 printf("master pointer (%d)]\n", dev->attachment); 266 break; 267 case XIMasterKeyboard: 268 printf("master keyboard (%d)]\n", dev->attachment); 269 break; 270 case XISlavePointer: 271 printf("slave pointer (%d)]\n", dev->attachment); 272 break; 273 case XISlaveKeyboard: 274 printf("slave keyboard (%d)]\n", dev->attachment); 275 break; 276 case XIFloatingSlave: 277 printf("floating slave]\n"); 278 break; 279 } 280 281 if (format == FORMAT_SHORT) 282 return; 283 284 if (!dev->enabled) 285 printf("\tThis device is disabled\n"); 286 287 print_classes_xi2(display, dev->classes, dev->num_classes); 288} 289 290 291static int 292list_xi2(Display *display, 293 enum print_format format) 294{ 295 int ndevices; 296 int i, j; 297 XIDeviceInfo *info, *dev; 298 299 info = XIQueryDevice(display, XIAllDevices, &ndevices); 300 301 for(i = 0; i < ndevices; i++) 302 { 303 dev = &info[i]; 304 if (dev->use == XIMasterPointer || dev->use == XIMasterKeyboard) 305 { 306 if (format == FORMAT_SHORT || format == FORMAT_LONG) 307 { 308 if (dev->use == XIMasterPointer) 309 printf("⎡ "); 310 else 311 printf("⎣ "); 312 } 313 314 print_info_xi2(display, dev, format); 315 for (j = 0; j < ndevices; j++) 316 { 317 XIDeviceInfo* sd = &info[j]; 318 319 if ((sd->use == XISlavePointer || sd->use == XISlaveKeyboard) && 320 (sd->attachment == dev->deviceid)) 321 { 322 if (format == FORMAT_SHORT || format == FORMAT_LONG) 323 printf("%s ↳ ", dev->use == XIMasterPointer ? "⎜" : " "); 324 print_info_xi2(display, sd, format); 325 } 326 } 327 } 328 } 329 330 for (i = 0; i < ndevices; i++) 331 { 332 dev = &info[i]; 333 if (dev->use == XIFloatingSlave) 334 { 335 printf("∼ "); 336 print_info_xi2(display, dev, format); 337 } 338 } 339 340 341 XIFreeDeviceInfo(info); 342 return EXIT_SUCCESS; 343} 344#endif 345 346int 347list(Display *display, 348 int argc, 349 char *argv[], 350 char *name, 351 char *desc) 352{ 353 enum print_format format = FORMAT_NONE; 354 int arg_dev = 1; 355 356 if (argc >= 1) 357 { 358 if (strcmp(argv[0], "--short") == 0) 359 format = FORMAT_SHORT; 360 else if (strcmp(argv[0], "--long") == 0) 361 format = FORMAT_LONG; 362 else if (strcmp(argv[0], "--name-only") == 0) 363 format = FORMAT_NAME; 364 else if (strcmp(argv[0], "--id-only") == 0) 365 format = FORMAT_ID; 366 else 367 arg_dev--; 368 } 369 370 if (argc > arg_dev) 371 { 372 if (format == FORMAT_NONE) 373 format = FORMAT_LONG; 374#if HAVE_XI2 375 if (xinput_version(display) == XI_2_Major) 376 { 377 XIDeviceInfo *info = xi2_find_device_info(display, argv[arg_dev]); 378 379 if (!info) { 380 fprintf(stderr, "unable to find device %s\n", argv[arg_dev]); 381 return EXIT_FAILURE; 382 } else { 383 print_info_xi2(display, info, format); 384 return EXIT_SUCCESS; 385 } 386 } else 387#endif 388 { 389 XDeviceInfo *info = find_device_info(display, argv[arg_dev], False); 390 391 if (!info) { 392 fprintf(stderr, "unable to find device %s\n", argv[arg_dev]); 393 return EXIT_FAILURE; 394 } else { 395 print_info(display, info, format); 396 return EXIT_SUCCESS; 397 } 398 } 399 } else { 400 if (format == FORMAT_NONE) 401 format = FORMAT_SHORT; 402#if HAVE_XI2 403 if (xinput_version(display) == XI_2_Major) 404 return list_xi2(display, format); 405#endif 406 return list_xi1(display, format); 407 } 408} 409 410/* end of list.c */ 411