15b944e2aSmrg/* 20309d3b3Smrg * Copyright © 2007 Peter Hutterer 30309d3b3Smrg * Copyright © 2009 Red Hat, Inc. 45b944e2aSmrg * 50309d3b3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 60309d3b3Smrg * copy of this software and associated documentation files (the "Software"), 70309d3b3Smrg * to deal in the Software without restriction, including without limitation 80309d3b3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 90309d3b3Smrg * and/or sell copies of the Software, and to permit persons to whom the 100309d3b3Smrg * Software is furnished to do so, subject to the following conditions: 115b944e2aSmrg * 120309d3b3Smrg * The above copyright notice and this permission notice (including the next 130309d3b3Smrg * paragraph) shall be included in all copies or substantial portions of the 140309d3b3Smrg * Software. 155b944e2aSmrg * 160309d3b3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 170309d3b3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 180309d3b3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 190309d3b3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 200309d3b3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 210309d3b3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 220309d3b3Smrg * DEALINGS IN THE SOFTWARE. 235b944e2aSmrg */ 245b944e2aSmrg 255b944e2aSmrg#include <ctype.h> 265b944e2aSmrg#include <string.h> 275b944e2aSmrg#include <stdlib.h> 285b944e2aSmrg#include <stdint.h> 295b944e2aSmrg#include <X11/Xatom.h> 305b944e2aSmrg#include <X11/extensions/XIproto.h> 315b944e2aSmrg 325b944e2aSmrg#include "xinput.h" 335b944e2aSmrg 3453719b08Smrgstatic Atom parse_atom(Display *dpy, char *name) { 3553719b08Smrg Bool is_atom = True; 3653719b08Smrg int i; 3753719b08Smrg 3853719b08Smrg for (i = 0; name[i] != '\0'; i++) { 3953719b08Smrg if (!isdigit(name[i])) { 4053719b08Smrg is_atom = False; 4153719b08Smrg break; 4253719b08Smrg } 4353719b08Smrg } 4453719b08Smrg 4553719b08Smrg if (is_atom) 4653719b08Smrg return atoi(name); 4753719b08Smrg else 4853719b08Smrg return XInternAtom(dpy, name, False); 4953719b08Smrg} 5053719b08Smrg 515b944e2aSmrgstatic void 525b944e2aSmrgprint_property(Display *dpy, XDevice* dev, Atom property) 535b944e2aSmrg{ 545b944e2aSmrg Atom act_type; 555b944e2aSmrg char *name; 565b944e2aSmrg int act_format; 575b944e2aSmrg unsigned long nitems, bytes_after; 585b944e2aSmrg unsigned char *data, *ptr; 590309d3b3Smrg int j, done = False, size = 0; 605b944e2aSmrg 615b944e2aSmrg name = XGetAtomName(dpy, property); 625b944e2aSmrg printf("\t%s (%ld):\t", name, property); 6333734831Smrg XFree(name); 645b944e2aSmrg 655b944e2aSmrg if (XGetDeviceProperty(dpy, dev, property, 0, 1000, False, 665b944e2aSmrg AnyPropertyType, &act_type, &act_format, 675b944e2aSmrg &nitems, &bytes_after, &data) == Success) 685b944e2aSmrg { 69d3263506Smrg Atom float_atom = XInternAtom(dpy, "FLOAT", True); 705b944e2aSmrg 715b944e2aSmrg ptr = data; 72d3263506Smrg 7353719b08Smrg if (nitems == 0) 7453719b08Smrg printf("<no items>"); 7553719b08Smrg 76d3263506Smrg switch(act_format) 77d3263506Smrg { 78d3263506Smrg case 8: size = sizeof(char); break; 79d3263506Smrg case 16: size = sizeof(short); break; 80d3263506Smrg case 32: size = sizeof(long); break; 81d3263506Smrg } 825b944e2aSmrg 835b944e2aSmrg for (j = 0; j < nitems; j++) 845b944e2aSmrg { 855b944e2aSmrg switch(act_type) 865b944e2aSmrg { 875b944e2aSmrg case XA_INTEGER: 885b944e2aSmrg switch(act_format) 895b944e2aSmrg { 905b944e2aSmrg case 8: 91d3263506Smrg printf("%d", *((char*)ptr)); 925b944e2aSmrg break; 935b944e2aSmrg case 16: 94d3263506Smrg printf("%d", *((short*)ptr)); 955b944e2aSmrg break; 965b944e2aSmrg case 32: 97d3263506Smrg printf("%ld", *((long*)ptr)); 985b944e2aSmrg break; 995b944e2aSmrg } 1005b944e2aSmrg break; 1010309d3b3Smrg case XA_CARDINAL: 1020309d3b3Smrg switch(act_format) 1030309d3b3Smrg { 1040309d3b3Smrg case 8: 1050309d3b3Smrg printf("%u", *((unsigned char*)ptr)); 1060309d3b3Smrg break; 1070309d3b3Smrg case 16: 1080309d3b3Smrg printf("%u", *((unsigned short*)ptr)); 1090309d3b3Smrg break; 1100309d3b3Smrg case 32: 1110309d3b3Smrg printf("%lu", *((unsigned long*)ptr)); 1120309d3b3Smrg break; 1130309d3b3Smrg } 1140309d3b3Smrg break; 1155b944e2aSmrg case XA_STRING: 116d3263506Smrg if (act_format != 8) 117d3263506Smrg { 118d3263506Smrg printf("Unknown string format.\n"); 119d3263506Smrg done = True; 120d3263506Smrg break; 121d3263506Smrg } 122d3263506Smrg printf("\"%s\"", ptr); 123d3263506Smrg j += strlen((char*)ptr); /* The loop's j++ jumps over the 124d3263506Smrg terminating 0 */ 125d3263506Smrg ptr += strlen((char*)ptr); /* ptr += size below jumps over 126d3263506Smrg the terminating 0 */ 1275b944e2aSmrg break; 1285b944e2aSmrg case XA_ATOM: 12953719b08Smrg { 13053719b08Smrg Atom a = *(Atom*)ptr; 13133734831Smrg name = (a) ? XGetAtomName(dpy, a) : NULL; 13233734831Smrg printf("\"%s\" (%d)", name ? name : "None", (int)a); 13333734831Smrg XFree(name); 13453719b08Smrg break; 13553719b08Smrg } 1365b944e2aSmrg default: 1375b944e2aSmrg if (float_atom != None && act_type == float_atom) 1385b944e2aSmrg { 139d3263506Smrg printf("%f", *((float*)ptr)); 1405b944e2aSmrg break; 1415b944e2aSmrg } 1425b944e2aSmrg 14333734831Smrg name = XGetAtomName(dpy, act_type); 14433734831Smrg printf("\t... of unknown type '%s'\n", name); 14533734831Smrg XFree(name); 146d3263506Smrg done = True; 1475b944e2aSmrg break; 1485b944e2aSmrg } 1495b944e2aSmrg 150d3263506Smrg ptr += size; 1515b944e2aSmrg 152d3263506Smrg if (done == True) 1535b944e2aSmrg break; 15453719b08Smrg if (j < nitems - 1) 15553719b08Smrg printf(", "); 1565b944e2aSmrg } 1575b944e2aSmrg printf("\n"); 1585b944e2aSmrg XFree(data); 1595b944e2aSmrg } else 1605b944e2aSmrg printf("\tFetch failure\n"); 1615b944e2aSmrg 1625b944e2aSmrg} 1635b944e2aSmrg 16453719b08Smrgstatic int 16553719b08Smrglist_props_xi1(Display *dpy, int argc, char** argv, char* name, char *desc) 1665b944e2aSmrg{ 1675b944e2aSmrg XDeviceInfo *info; 1685b944e2aSmrg XDevice *dev; 1695b944e2aSmrg int i; 1705b944e2aSmrg int nprops; 1715b944e2aSmrg Atom *props; 172e73734d1Smrg int rc = EXIT_SUCCESS; 1735b944e2aSmrg 1745b944e2aSmrg if (argc == 0) 1755b944e2aSmrg { 1765b944e2aSmrg fprintf(stderr, "Usage: xinput %s %s\n", name, desc); 1775b944e2aSmrg return EXIT_FAILURE; 1785b944e2aSmrg } 1795b944e2aSmrg 1805b944e2aSmrg for (i = 0; i < argc; i++) 1815b944e2aSmrg { 1825b944e2aSmrg info = find_device_info(dpy, argv[i], False); 1835b944e2aSmrg if (!info) 1845b944e2aSmrg { 1850309d3b3Smrg fprintf(stderr, "unable to find device '%s'\n", argv[i]); 186e73734d1Smrg rc = EXIT_FAILURE; 1875b944e2aSmrg continue; 1885b944e2aSmrg } 1895b944e2aSmrg 1905b944e2aSmrg dev = XOpenDevice(dpy, info->id); 1915b944e2aSmrg if (!dev) 1925b944e2aSmrg { 1935b944e2aSmrg fprintf(stderr, "unable to open device '%s'\n", info->name); 194e73734d1Smrg rc = EXIT_FAILURE; 1955b944e2aSmrg continue; 1965b944e2aSmrg } 1975b944e2aSmrg 1985b944e2aSmrg props = XListDeviceProperties(dpy, dev, &nprops); 1995b944e2aSmrg if (!nprops) 2005b944e2aSmrg { 2015b944e2aSmrg printf("Device '%s' does not report any properties.\n", info->name); 2025b944e2aSmrg continue; 2035b944e2aSmrg } 2045b944e2aSmrg 2055b944e2aSmrg printf("Device '%s':\n", info->name); 2065b944e2aSmrg while(nprops--) 2075b944e2aSmrg { 2085b944e2aSmrg print_property(dpy, dev, props[nprops]); 2095b944e2aSmrg } 2105b944e2aSmrg 2115b944e2aSmrg XFree(props); 2125b944e2aSmrg XCloseDevice(dpy, dev); 2135b944e2aSmrg } 214e73734d1Smrg return rc; 2155b944e2aSmrg} 2165b944e2aSmrg 21753719b08Smrg 21853719b08Smrgint watch_props(Display *dpy, int argc, char** argv, char* n, char *desc) 2195b944e2aSmrg{ 2205b944e2aSmrg XDevice *dev; 22153719b08Smrg XDeviceInfo *info; 22253719b08Smrg XEvent ev; 22353719b08Smrg XDevicePropertyNotifyEvent *dpev; 2245b944e2aSmrg char *name; 22553719b08Smrg int type_prop; 22653719b08Smrg XEventClass cls_prop; 2275b944e2aSmrg 22853719b08Smrg if (list_props(dpy, argc, argv, n, desc) != EXIT_SUCCESS) 2295b944e2aSmrg return EXIT_FAILURE; 2305b944e2aSmrg 2315b944e2aSmrg info = find_device_info(dpy, argv[0], False); 2325b944e2aSmrg if (!info) 2335b944e2aSmrg { 2340309d3b3Smrg fprintf(stderr, "unable to find device '%s'\n", argv[0]); 2355b944e2aSmrg return EXIT_FAILURE; 2365b944e2aSmrg } 2375b944e2aSmrg 2385b944e2aSmrg dev = XOpenDevice(dpy, info->id); 2395b944e2aSmrg if (!dev) 2405b944e2aSmrg { 24153719b08Smrg fprintf(stderr, "unable to open device '%s'\n", info->name); 2425b944e2aSmrg return EXIT_FAILURE; 2435b944e2aSmrg } 2445b944e2aSmrg 24553719b08Smrg DevicePropertyNotify(dev, type_prop, cls_prop); 24653719b08Smrg XSelectExtensionEvent(dpy, DefaultRootWindow(dpy), &cls_prop, 1); 2475b944e2aSmrg 24853719b08Smrg while(1) 24953719b08Smrg { 25053719b08Smrg XNextEvent(dpy, &ev); 25153719b08Smrg 25253719b08Smrg dpev = (XDevicePropertyNotifyEvent*)&ev; 25353719b08Smrg if (dpev->type != type_prop) 25453719b08Smrg continue; 25553719b08Smrg 25653719b08Smrg name = XGetAtomName(dpy, dpev->atom); 25753719b08Smrg printf("Property '%s' changed.\n", name); 25833734831Smrg XFree(name); 25953719b08Smrg print_property(dpy, dev, dpev->atom); 2605b944e2aSmrg } 2615b944e2aSmrg 26253719b08Smrg XCloseDevice(dpy, dev); 26353719b08Smrg} 2645b944e2aSmrg 26553719b08Smrgstatic int 26653719b08Smrgdelete_prop_xi1(Display *dpy, int argc, char** argv, char* n, char *desc) 26753719b08Smrg{ 26853719b08Smrg XDevice *dev; 26953719b08Smrg XDeviceInfo *info; 27053719b08Smrg char *name; 27153719b08Smrg Atom prop; 27253719b08Smrg 27320f5670eSmrg if (argc < 2) 27420f5670eSmrg { 27520f5670eSmrg fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 27620f5670eSmrg return EXIT_FAILURE; 27720f5670eSmrg } 27820f5670eSmrg 27953719b08Smrg info = find_device_info(dpy, argv[0], False); 28053719b08Smrg if (!info) 2815b944e2aSmrg { 2820309d3b3Smrg fprintf(stderr, "unable to find device '%s'\n", argv[0]); 2835b944e2aSmrg return EXIT_FAILURE; 2845b944e2aSmrg } 2855b944e2aSmrg 28653719b08Smrg dev = XOpenDevice(dpy, info->id); 28753719b08Smrg if (!dev) 2885b944e2aSmrg { 28953719b08Smrg fprintf(stderr, "unable to open device '%s'\n", info->name); 29053719b08Smrg return EXIT_FAILURE; 2915b944e2aSmrg } 2925b944e2aSmrg 29353719b08Smrg name = argv[1]; 29453719b08Smrg 29553719b08Smrg prop = parse_atom(dpy, name); 29653719b08Smrg 29753719b08Smrg XDeleteDeviceProperty(dpy, dev, prop); 2985b944e2aSmrg 2995b944e2aSmrg XCloseDevice(dpy, dev); 3005b944e2aSmrg return EXIT_SUCCESS; 3015b944e2aSmrg} 3025b944e2aSmrg 30353719b08Smrgstatic int 30453719b08Smrgdo_set_prop_xi1(Display *dpy, Atom type, int format, int argc, char **argv, char *n, char *desc) 3055b944e2aSmrg{ 30653719b08Smrg XDeviceInfo *info; 30753719b08Smrg XDevice *dev; 30853719b08Smrg Atom prop; 30953719b08Smrg Atom old_type; 31053719b08Smrg char *name; 31153719b08Smrg int i; 31253719b08Smrg Atom float_atom; 31353719b08Smrg int old_format, nelements = 0; 31453719b08Smrg unsigned long act_nitems, bytes_after; 31553719b08Smrg char *endptr; 31653719b08Smrg union { 31753719b08Smrg unsigned char *c; 31853719b08Smrg short *s; 31953719b08Smrg long *l; 32053719b08Smrg Atom *a; 32153719b08Smrg } data; 3225b944e2aSmrg 32353719b08Smrg if (argc < 3) 3245b944e2aSmrg { 3255b944e2aSmrg fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 3265b944e2aSmrg return EXIT_FAILURE; 3275b944e2aSmrg } 3285b944e2aSmrg 3295b944e2aSmrg info = find_device_info(dpy, argv[0], False); 3305b944e2aSmrg if (!info) 3315b944e2aSmrg { 3320309d3b3Smrg fprintf(stderr, "unable to find device '%s'\n", argv[0]); 3335b944e2aSmrg return EXIT_FAILURE; 3345b944e2aSmrg } 3355b944e2aSmrg 3365b944e2aSmrg dev = XOpenDevice(dpy, info->id); 3375b944e2aSmrg if (!dev) 3385b944e2aSmrg { 3390309d3b3Smrg fprintf(stderr, "unable to open device '%s'\n", argv[0]); 3405b944e2aSmrg return EXIT_FAILURE; 3415b944e2aSmrg } 3425b944e2aSmrg 3435b944e2aSmrg name = argv[1]; 3445b944e2aSmrg 34553719b08Smrg prop = parse_atom(dpy, name); 34653719b08Smrg 34753719b08Smrg if (prop == None) { 3480309d3b3Smrg fprintf(stderr, "invalid property '%s'\n", name); 34953719b08Smrg return EXIT_FAILURE; 3505b944e2aSmrg } 3515b944e2aSmrg 35253719b08Smrg float_atom = XInternAtom(dpy, "FLOAT", False); 3535b944e2aSmrg 3545b944e2aSmrg nelements = argc - 2; 35553719b08Smrg if (type == None || format == 0) { 35653719b08Smrg if (XGetDeviceProperty(dpy, dev, prop, 0, 0, False, AnyPropertyType, 35753719b08Smrg &old_type, &old_format, &act_nitems, 35853719b08Smrg &bytes_after, &data.c) != Success) { 3590309d3b3Smrg fprintf(stderr, "failed to get property type and format for '%s'\n", 36053719b08Smrg name); 36153719b08Smrg return EXIT_FAILURE; 36253719b08Smrg } else { 36353719b08Smrg if (type == None) 36453719b08Smrg type = old_type; 36553719b08Smrg if (format == 0) 36653719b08Smrg format = old_format; 36753719b08Smrg } 3685b944e2aSmrg 36953719b08Smrg XFree(data.c); 3705b944e2aSmrg } 3715b944e2aSmrg 37253719b08Smrg if (type == None) { 3730309d3b3Smrg fprintf(stderr, "property '%s' doesn't exist, you need to specify " 37453719b08Smrg "its type and format\n", name); 37553719b08Smrg return EXIT_FAILURE; 3765b944e2aSmrg } 3775b944e2aSmrg 37853719b08Smrg data.c = calloc(nelements, sizeof(long)); 37953719b08Smrg 3805b944e2aSmrg for (i = 0; i < nelements; i++) 3815b944e2aSmrg { 3820309d3b3Smrg if (type == XA_INTEGER || type == XA_CARDINAL) { 38353719b08Smrg switch (format) 38453719b08Smrg { 38553719b08Smrg case 8: 38653719b08Smrg data.c[i] = atoi(argv[2 + i]); 38753719b08Smrg break; 38853719b08Smrg case 16: 38953719b08Smrg data.s[i] = atoi(argv[2 + i]); 39053719b08Smrg break; 39153719b08Smrg case 32: 39253719b08Smrg data.l[i] = atoi(argv[2 + i]); 39353719b08Smrg break; 39453719b08Smrg default: 3950309d3b3Smrg fprintf(stderr, "unexpected size for property '%s'", name); 39653719b08Smrg return EXIT_FAILURE; 39753719b08Smrg } 39853719b08Smrg } else if (type == float_atom) { 39953719b08Smrg if (format != 32) { 4000309d3b3Smrg fprintf(stderr, "unexpected format %d for property '%s'\n", 40153719b08Smrg format, name); 40253719b08Smrg return EXIT_FAILURE; 40353719b08Smrg } 40453719b08Smrg *(float *)(data.l + i) = strtod(argv[2 + i], &endptr); 40553719b08Smrg if (endptr == argv[2 + i]) { 4060309d3b3Smrg fprintf(stderr, "argument '%s' could not be parsed\n", argv[2 + i]); 40753719b08Smrg return EXIT_FAILURE; 40853719b08Smrg } 40953719b08Smrg } else if (type == XA_ATOM) { 41053719b08Smrg if (format != 32) { 4110309d3b3Smrg fprintf(stderr, "unexpected format %d for property '%s'\n", 41253719b08Smrg format, name); 41353719b08Smrg return EXIT_FAILURE; 41453719b08Smrg } 41553719b08Smrg data.a[i] = parse_atom(dpy, argv[2 + i]); 41653719b08Smrg } else { 4170309d3b3Smrg fprintf(stderr, "unexpected type for property '%s'\n", name); 41853719b08Smrg return EXIT_FAILURE; 41953719b08Smrg } 4205b944e2aSmrg } 4215b944e2aSmrg 42253719b08Smrg XChangeDeviceProperty(dpy, dev, prop, type, format, PropModeReplace, 42353719b08Smrg data.c, nelements); 42453719b08Smrg free(data.c); 4255b944e2aSmrg XCloseDevice(dpy, dev); 4265b944e2aSmrg return EXIT_SUCCESS; 4275b944e2aSmrg} 4285b944e2aSmrg 42953719b08Smrg#if HAVE_XI2 43053719b08Smrgstatic void 43153719b08Smrgprint_property_xi2(Display *dpy, int deviceid, Atom property) 4325b944e2aSmrg{ 43353719b08Smrg Atom act_type; 43453719b08Smrg char *name; 43553719b08Smrg int act_format; 43653719b08Smrg unsigned long nitems, bytes_after; 43753719b08Smrg unsigned char *data, *ptr; 43853719b08Smrg int j, done = False; 4395b944e2aSmrg 44053719b08Smrg name = XGetAtomName(dpy, property); 44153719b08Smrg printf("\t%s (%ld):\t", name, property); 44233734831Smrg XFree(name); 4435b944e2aSmrg 44453719b08Smrg if (XIGetProperty(dpy, deviceid, property, 0, 1000, False, 44553719b08Smrg AnyPropertyType, &act_type, &act_format, 44653719b08Smrg &nitems, &bytes_after, &data) == Success) 4475b944e2aSmrg { 44853719b08Smrg Atom float_atom = XInternAtom(dpy, "FLOAT", True); 4495b944e2aSmrg 45053719b08Smrg ptr = data; 45153719b08Smrg 45253719b08Smrg if (nitems == 0) 45353719b08Smrg printf("<no items>"); 45453719b08Smrg 45553719b08Smrg for (j = 0; j < nitems; j++) 45653719b08Smrg { 45753719b08Smrg switch(act_type) 45853719b08Smrg { 45953719b08Smrg case XA_INTEGER: 46053719b08Smrg switch(act_format) 46153719b08Smrg { 46253719b08Smrg case 8: 46353719b08Smrg printf("%d", *((int8_t*)ptr)); 46453719b08Smrg break; 46553719b08Smrg case 16: 46653719b08Smrg printf("%d", *((int16_t*)ptr)); 46753719b08Smrg break; 46853719b08Smrg case 32: 46953719b08Smrg printf("%d", *((int32_t*)ptr)); 47053719b08Smrg break; 47153719b08Smrg } 47253719b08Smrg break; 4730309d3b3Smrg case XA_CARDINAL: 4740309d3b3Smrg switch(act_format) 4750309d3b3Smrg { 4760309d3b3Smrg case 8: 4770309d3b3Smrg printf("%u", *((uint8_t*)ptr)); 4780309d3b3Smrg break; 4790309d3b3Smrg case 16: 4800309d3b3Smrg printf("%u", *((uint16_t*)ptr)); 4810309d3b3Smrg break; 4820309d3b3Smrg case 32: 4830309d3b3Smrg printf("%u", *((uint32_t*)ptr)); 4840309d3b3Smrg break; 4850309d3b3Smrg } 4860309d3b3Smrg break; 48753719b08Smrg case XA_STRING: 48853719b08Smrg if (act_format != 8) 48953719b08Smrg { 49053719b08Smrg printf("Unknown string format.\n"); 49153719b08Smrg done = True; 49253719b08Smrg break; 49353719b08Smrg } 49453719b08Smrg printf("\"%s\"", ptr); 49553719b08Smrg j += strlen((char*)ptr); /* The loop's j++ jumps over the 49653719b08Smrg terminating 0 */ 49753719b08Smrg ptr += strlen((char*)ptr); /* ptr += size below jumps over 49853719b08Smrg the terminating 0 */ 49953719b08Smrg break; 50053719b08Smrg case XA_ATOM: 50153719b08Smrg { 502cea37944Smrg Atom a = *(uint32_t*)ptr; 50333734831Smrg name = (a) ? XGetAtomName(dpy, a) : NULL; 50433734831Smrg printf("\"%s\" (%ld)", name ? name : "None", a); 50533734831Smrg XFree(name); 50653719b08Smrg break; 50753719b08Smrg } 50853719b08Smrg break; 50953719b08Smrg default: 51053719b08Smrg if (float_atom != None && act_type == float_atom) 51153719b08Smrg { 51253719b08Smrg printf("%f", *((float*)ptr)); 51353719b08Smrg break; 51453719b08Smrg } 51553719b08Smrg 51633734831Smrg name = XGetAtomName(dpy, act_type); 51733734831Smrg printf("\t... of unknown type %s\n", name); 51833734831Smrg XFree(name); 51953719b08Smrg done = True; 52053719b08Smrg break; 52153719b08Smrg } 52253719b08Smrg 52353719b08Smrg ptr += act_format/8; 52453719b08Smrg 52553719b08Smrg if (done == True) 52653719b08Smrg break; 52753719b08Smrg if (j < nitems - 1) 52853719b08Smrg printf(", "); 52953719b08Smrg } 53053719b08Smrg printf("\n"); 53153719b08Smrg XFree(data); 53253719b08Smrg } else 53353719b08Smrg printf("\tFetch failure\n"); 53453719b08Smrg 53553719b08Smrg} 53653719b08Smrg 53753719b08Smrgstatic int 53853719b08Smrglist_props_xi2(Display *dpy, int argc, char** argv, char* name, char *desc) 53953719b08Smrg{ 54053719b08Smrg XIDeviceInfo *info; 54153719b08Smrg int i; 54253719b08Smrg int nprops; 54353719b08Smrg Atom *props; 544e73734d1Smrg int rc = EXIT_SUCCESS; 54553719b08Smrg 54653719b08Smrg if (argc == 0) 5475b944e2aSmrg { 54853719b08Smrg fprintf(stderr, "Usage: xinput %s %s\n", name, desc); 5495b944e2aSmrg return EXIT_FAILURE; 5505b944e2aSmrg } 5515b944e2aSmrg 55253719b08Smrg for (i = 0; i < argc; i++) 5535b944e2aSmrg { 55453719b08Smrg info = xi2_find_device_info(dpy, argv[i]); 55553719b08Smrg if (!info) 55653719b08Smrg { 55753719b08Smrg fprintf(stderr, "unable to find device %s\n", argv[i]); 558e73734d1Smrg rc = EXIT_FAILURE; 55953719b08Smrg continue; 56053719b08Smrg } 5615b944e2aSmrg 56253719b08Smrg props = XIListProperties(dpy, info->deviceid, &nprops); 56353719b08Smrg if (!nprops) 56453719b08Smrg { 56553719b08Smrg printf("Device '%s' does not report any properties.\n", info->name); 5665b944e2aSmrg continue; 56753719b08Smrg } 5685b944e2aSmrg 56953719b08Smrg printf("Device '%s':\n", info->name); 57053719b08Smrg while(nprops--) 57153719b08Smrg { 57253719b08Smrg print_property_xi2(dpy, info->deviceid, props[nprops]); 57353719b08Smrg } 5745b944e2aSmrg 57553719b08Smrg XFree(props); 57653719b08Smrg } 577e73734d1Smrg return rc; 5785b944e2aSmrg} 5795b944e2aSmrg 58053719b08Smrgstatic int 58153719b08Smrgdelete_prop_xi2(Display *dpy, int argc, char** argv, char* n, char *desc) 5825b944e2aSmrg{ 58353719b08Smrg XIDeviceInfo *info; 5845b944e2aSmrg char *name; 5855b944e2aSmrg Atom prop; 5865b944e2aSmrg 58720f5670eSmrg if (argc < 2) 58820f5670eSmrg { 58920f5670eSmrg fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 59020f5670eSmrg return EXIT_FAILURE; 59120f5670eSmrg } 59220f5670eSmrg 59353719b08Smrg info = xi2_find_device_info(dpy, argv[0]); 5945b944e2aSmrg if (!info) 5955b944e2aSmrg { 5965b944e2aSmrg fprintf(stderr, "unable to find device %s\n", argv[0]); 5975b944e2aSmrg return EXIT_FAILURE; 5985b944e2aSmrg } 5995b944e2aSmrg 6005b944e2aSmrg name = argv[1]; 6015b944e2aSmrg 60253719b08Smrg prop = parse_atom(dpy, name); 6035b944e2aSmrg 60453719b08Smrg XIDeleteProperty(dpy, info->deviceid, prop); 6055b944e2aSmrg 6065b944e2aSmrg return EXIT_SUCCESS; 6075b944e2aSmrg} 6085b944e2aSmrg 60953719b08Smrgstatic int 61053719b08Smrgdo_set_prop_xi2(Display *dpy, Atom type, int format, int argc, char **argv, char *n, char *desc) 6115b944e2aSmrg{ 61253719b08Smrg XIDeviceInfo *info; 61353719b08Smrg Atom prop; 61453719b08Smrg Atom old_type; 61553719b08Smrg char *name; 61653719b08Smrg int i; 61753719b08Smrg Atom float_atom; 61853719b08Smrg int old_format, nelements = 0; 61953719b08Smrg unsigned long act_nitems, bytes_after; 62053719b08Smrg char *endptr; 62153719b08Smrg union { 62253719b08Smrg unsigned char *c; 62353719b08Smrg int16_t *s; 62453719b08Smrg int32_t *l; 625a570218aSmrg } data = { NULL }; 626a570218aSmrg int rc = EXIT_FAILURE; 6275b944e2aSmrg 6285b944e2aSmrg if (argc < 3) 6295b944e2aSmrg { 6305b944e2aSmrg fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 631a570218aSmrg goto out; 6325b944e2aSmrg } 6335b944e2aSmrg 63453719b08Smrg info = xi2_find_device_info(dpy, argv[0]); 6355b944e2aSmrg if (!info) 6365b944e2aSmrg { 6375b944e2aSmrg fprintf(stderr, "unable to find device %s\n", argv[0]); 638a570218aSmrg goto out; 6395b944e2aSmrg } 6405b944e2aSmrg 64153719b08Smrg name = argv[1]; 64253719b08Smrg 64353719b08Smrg prop = parse_atom(dpy, name); 64453719b08Smrg 64553719b08Smrg if (prop == None) { 6460309d3b3Smrg fprintf(stderr, "invalid property '%s'\n", name); 647a570218aSmrg goto out; 6485b944e2aSmrg } 6495b944e2aSmrg 65053719b08Smrg float_atom = XInternAtom(dpy, "FLOAT", False); 6515b944e2aSmrg 65253719b08Smrg nelements = argc - 2; 65353719b08Smrg if (type == None || format == 0) { 65453719b08Smrg if (XIGetProperty(dpy, info->deviceid, prop, 0, 0, False, 65553719b08Smrg AnyPropertyType, &old_type, &old_format, &act_nitems, 65653719b08Smrg &bytes_after, &data.c) != Success) { 6570309d3b3Smrg fprintf(stderr, "failed to get property type and format for '%s'\n", 65853719b08Smrg name); 659a570218aSmrg goto out; 66053719b08Smrg } else { 66153719b08Smrg if (type == None) 66253719b08Smrg type = old_type; 66353719b08Smrg if (format == 0) 66453719b08Smrg format = old_format; 66553719b08Smrg } 66653719b08Smrg 66753719b08Smrg XFree(data.c); 6685b944e2aSmrg } 6695b944e2aSmrg 67053719b08Smrg if (type == None) { 6710309d3b3Smrg fprintf(stderr, "property '%s' doesn't exist, you need to specify " 67253719b08Smrg "its type and format\n", name); 673a570218aSmrg goto out; 67453719b08Smrg } 67553719b08Smrg 67653719b08Smrg data.c = calloc(nelements, sizeof(int32_t)); 6775b944e2aSmrg 6785b944e2aSmrg for (i = 0; i < nelements; i++) 6795b944e2aSmrg { 6800309d3b3Smrg if (type == XA_INTEGER || type == XA_CARDINAL) { 68153719b08Smrg switch (format) 68253719b08Smrg { 68353719b08Smrg case 8: 68453719b08Smrg data.c[i] = atoi(argv[2 + i]); 68553719b08Smrg break; 68653719b08Smrg case 16: 68753719b08Smrg data.s[i] = atoi(argv[2 + i]); 68853719b08Smrg break; 68953719b08Smrg case 32: 69053719b08Smrg data.l[i] = atoi(argv[2 + i]); 69153719b08Smrg break; 69253719b08Smrg default: 69353719b08Smrg fprintf(stderr, "unexpected size for property %s", name); 694a570218aSmrg goto out; 69553719b08Smrg } 69653719b08Smrg } else if (type == float_atom) { 69753719b08Smrg if (format != 32) { 6980309d3b3Smrg fprintf(stderr, "unexpected format %d for property '%s'\n", 69953719b08Smrg format, name); 700a570218aSmrg goto out; 70153719b08Smrg } 70253719b08Smrg *(float *)(data.l + i) = strtod(argv[2 + i], &endptr); 70353719b08Smrg if (endptr == argv[2 + i]) { 70453719b08Smrg fprintf(stderr, "argument %s could not be parsed\n", argv[2 + i]); 705a570218aSmrg goto out; 7065b944e2aSmrg } 70753719b08Smrg } else if (type == XA_ATOM) { 70853719b08Smrg if (format != 32) { 7090309d3b3Smrg fprintf(stderr, "unexpected format %d for property '%s'\n", 71053719b08Smrg format, name); 711a570218aSmrg goto out; 71253719b08Smrg } 71353719b08Smrg data.l[i] = parse_atom(dpy, argv[2 + i]); 71453719b08Smrg } else { 7150309d3b3Smrg fprintf(stderr, "unexpected type for property '%s'\n", name); 716a570218aSmrg goto out; 7175b944e2aSmrg } 71853719b08Smrg } 7195b944e2aSmrg 72053719b08Smrg XIChangeProperty(dpy, info->deviceid, prop, type, format, PropModeReplace, 72153719b08Smrg data.c, nelements); 722a570218aSmrg rc = EXIT_SUCCESS; 723a570218aSmrgout: 72453719b08Smrg free(data.c); 725a570218aSmrg return rc; 72653719b08Smrg} 72753719b08Smrg#endif 72853719b08Smrg 72953719b08Smrgint list_props(Display *display, int argc, char *argv[], char *name, 73053719b08Smrg char *desc) 73153719b08Smrg{ 732a570218aSmrg#if HAVE_XI2 73353719b08Smrg if (xinput_version(display) == XI_2_Major) 73453719b08Smrg return list_props_xi2(display, argc, argv, name, desc); 73553719b08Smrg#endif 73653719b08Smrg return list_props_xi1(display, argc, argv, name, desc); 73753719b08Smrg 73853719b08Smrg} 73953719b08Smrg 74053719b08Smrgint delete_prop(Display *display, int argc, char *argv[], char *name, 74153719b08Smrg char *desc) 74253719b08Smrg{ 743a570218aSmrg#if HAVE_XI2 74453719b08Smrg if (xinput_version(display) == XI_2_Major) 74553719b08Smrg return delete_prop_xi2(display, argc, argv, name, desc); 74653719b08Smrg#endif 74753719b08Smrg return delete_prop_xi1(display, argc, argv, name, desc); 74853719b08Smrg 74953719b08Smrg} 75053719b08Smrg 75153719b08Smrgstatic int 75253719b08Smrgdo_set_prop(Display *display, Atom type, int format, int argc, char *argv[], char *name, char *desc) 75353719b08Smrg{ 754a570218aSmrg#if HAVE_XI2 75553719b08Smrg if (xinput_version(display) == XI_2_Major) 75653719b08Smrg return do_set_prop_xi2(display, type, format, argc, argv, name, desc); 75753719b08Smrg#endif 75853719b08Smrg return do_set_prop_xi1(display, type, format, argc, argv, name, desc); 75953719b08Smrg} 76053719b08Smrg 76153719b08Smrgint 76253719b08Smrgset_atom_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 76353719b08Smrg{ 76453719b08Smrg return do_set_prop(dpy, XA_ATOM, 32, argc, argv, n, desc); 76553719b08Smrg} 76653719b08Smrg 76753719b08Smrgint 76853719b08Smrgset_int_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 76953719b08Smrg{ 77053719b08Smrg int i; 77153719b08Smrg int format; 77253719b08Smrg 77353719b08Smrg if (argc < 3) 77453719b08Smrg { 77553719b08Smrg fprintf(stderr, "Usage: xinput %s %s\n", n, desc); 77653719b08Smrg return EXIT_FAILURE; 7775b944e2aSmrg } 7785b944e2aSmrg 77953719b08Smrg format = atoi(argv[2]); 78053719b08Smrg if (format != 8 && format != 16 && format != 32) 78153719b08Smrg { 78253719b08Smrg fprintf(stderr, "Invalid format %d\n", format); 78353719b08Smrg return EXIT_FAILURE; 78453719b08Smrg } 7855b944e2aSmrg 78653719b08Smrg for (i = 3; i < argc; i++) 78753719b08Smrg argv[i - 1] = argv[i]; 78853719b08Smrg 78953719b08Smrg return do_set_prop(dpy, XA_INTEGER, format, argc - 1, argv, n, desc); 7905b944e2aSmrg} 7915b944e2aSmrg 79253719b08Smrgint 79353719b08Smrgset_float_prop(Display *dpy, int argc, char** argv, char* n, char *desc) 79453719b08Smrg{ 79553719b08Smrg Atom float_atom = XInternAtom(dpy, "FLOAT", False); 79653719b08Smrg 79753719b08Smrg if (sizeof(float) != 4) 79853719b08Smrg { 79953719b08Smrg fprintf(stderr, "sane FP required\n"); 80053719b08Smrg return EXIT_FAILURE; 80153719b08Smrg } 80253719b08Smrg 80353719b08Smrg return do_set_prop(dpy, float_atom, 32, argc, argv, n, desc); 80453719b08Smrg} 8055b944e2aSmrg 80653719b08Smrgint set_prop(Display *display, int argc, char *argv[], char *name, 80753719b08Smrg char *desc) 80853719b08Smrg{ 80953719b08Smrg Atom type = None; 81053719b08Smrg int format = 0; 81153719b08Smrg int i = 0, j; 81253719b08Smrg 81353719b08Smrg while (i < argc) { 81453719b08Smrg char *option = strchr(argv[i], '='); 81553719b08Smrg /* skip non-option arguments */ 81653719b08Smrg if (strncmp(argv[i], "--", 2) || !option) { 81753719b08Smrg i++; 81853719b08Smrg continue; 81953719b08Smrg } 82053719b08Smrg 82153719b08Smrg if (!strncmp(argv[i], "--type=", strlen("--type="))) { 82253719b08Smrg if (!strcmp(option + 1, "int")) { 82353719b08Smrg type = XA_INTEGER; 82453719b08Smrg } else if (!strcmp(option + 1, "float")) { 82553719b08Smrg type = XInternAtom(display, "FLOAT", False); 82653719b08Smrg format = 32; 82753719b08Smrg } else if (!strcmp(option + 1, "atom")) { 82853719b08Smrg type = XA_ATOM; 82953719b08Smrg format = 32; 83053719b08Smrg } else { 83153719b08Smrg fprintf(stderr, "unknown property type %s\n", option + 1); 83253719b08Smrg return EXIT_FAILURE; 83353719b08Smrg } 83453719b08Smrg } else if (!strncmp(argv[i], "--format=", strlen("--format="))) { 83553719b08Smrg format = atoi(option + 1); 83653719b08Smrg if (format != 8 && format != 16 && format != 32) { 8370309d3b3Smrg fprintf(stderr, "invalid property format '%s'\n", option + 1); 83853719b08Smrg return EXIT_FAILURE; 83953719b08Smrg } 84053719b08Smrg } else { 8410309d3b3Smrg fprintf(stderr, "invalid option '%s'\n", argv[i]); 84253719b08Smrg return EXIT_FAILURE; 84353719b08Smrg } 84453719b08Smrg 84553719b08Smrg for (j = i; j + 1 < argc; j++) 84653719b08Smrg argv[j] = argv[j + 1]; 84753719b08Smrg argc--; 84853719b08Smrg } 84953719b08Smrg 85053719b08Smrg return do_set_prop(display, type, format, argc, argv, name, desc); 85153719b08Smrg} 8520309d3b3Smrg 8530309d3b3Smrgint disable(Display *display, int argc, char *argv[], char *name, char *desc) 8540309d3b3Smrg{ 855e73734d1Smrg char *new_argv[3] = { NULL, "Device Enabled", "0" }; 856e73734d1Smrg 857e73734d1Smrg if (argc != 1) { 858e73734d1Smrg fprintf(stderr, "Usage: xinput %s %s\n", name, desc); 859e73734d1Smrg return EXIT_FAILURE; 860e73734d1Smrg } 861e73734d1Smrg 862e73734d1Smrg new_argv[0] = argv[0]; 863e73734d1Smrg 8640309d3b3Smrg return set_prop(display, 3, new_argv, name, desc); 8650309d3b3Smrg} 8660309d3b3Smrg 8670309d3b3Smrgint enable(Display *display, int argc, char *argv[], char *name, char *desc) 8680309d3b3Smrg{ 869e73734d1Smrg char *new_argv[3] = { NULL, "Device Enabled", "1" }; 870e73734d1Smrg 871e73734d1Smrg if (argc != 1) { 872e73734d1Smrg fprintf(stderr, "Usage: xinput %s %s\n", name, desc); 873e73734d1Smrg return EXIT_FAILURE; 874e73734d1Smrg } 875e73734d1Smrg 876e73734d1Smrg new_argv[0] = argv[0]; 877e73734d1Smrg 8780309d3b3Smrg return set_prop(display, 3, new_argv, name, desc); 8790309d3b3Smrg} 880