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