XListDev.c 9.02 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
/************************************************************

Copyright 1989, 1998  The Open Group

Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.

Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.

			All Rights Reserved

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Hewlett-Packard not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.

HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

********************************************************/

/***********************************************************************
 *
 * XListInputDevices - Request the server to return a list of 
 *			 available input devices.
 *
 */
53 54 55
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
56

57 58 59 60 61 62
#include <X11/extensions/XI.h>
#include <X11/extensions/XIproto.h>
#include <X11/Xlibint.h>
#include <X11/extensions/XInput.h>
#include <X11/extensions/extutil.h>
#include "XIint.h"
63
#include <limits.h>
64

65 66 67 68 69 70 71 72 73 74 75
/* Calculate length field to a multiples of sizeof(XID). XIDs are typedefs
 * to ulong and thus may be 8 bytes on some platforms. This can trigger a
 * SIGBUS if a class ends up not being 8-aligned (e.g. after XAxisInfo).
 */
static int pad_to_xid(int base_size)
{
    int padsize = sizeof(XID);

    return ((base_size + padsize - 1)/padsize) * padsize;
}

76
static size_t
77
SizeClassInfo(xAnyClassPtr *any, size_t len, int num_classes)
78 79 80 81 82 83
{
    int size = 0;
    int j;
    for (j = 0; j < num_classes; j++) {
        switch ((*any)->class) {
            case KeyClass:
84
                size += pad_to_xid(sizeof(XKeyInfo));
85 86
                break;
            case ButtonClass:
87
                size += pad_to_xid(sizeof(XButtonInfo));
88 89 90 91 92
                break;
            case ValuatorClass:
                {
                    xValuatorInfoPtr v;

93 94
                    if (len < sizeof(v))
                        return 0;
95
                    v = (xValuatorInfoPtr) *any;
96 97
                    size += pad_to_xid(sizeof(XValuatorInfo) +
                        (v->num_axes * sizeof(XAxisInfo)));
98 99 100 101 102
                    break;
                }
            default:
                break;
        }
103 104
        if ((*any)->length > len)
            return 0;
105 106 107 108 109 110
        *any = (xAnyClassPtr) ((char *)(*any) + (*any)->length);
    }

    return size;
}

111
static void
112 113
ParseClassInfo(xAnyClassPtr *any, XAnyClassPtr *Any, int num_classes)
{
Peter Hutterer's avatar
Peter Hutterer committed
114
    int j;
115 116 117 118 119 120 121 122 123

    for (j = 0; j < num_classes; j++) {
        switch ((*any)->class) {
            case KeyClass:
                {
                    XKeyInfoPtr K = (XKeyInfoPtr) *Any;
                    xKeyInfoPtr k = (xKeyInfoPtr) *any;

                    K->class = KeyClass;
124
                    K->length = pad_to_xid(sizeof(XKeyInfo));
125 126 127 128 129 130 131 132 133 134 135
                    K->min_keycode = k->min_keycode;
                    K->max_keycode = k->max_keycode;
                    K->num_keys = k->num_keys;
                    break;
                }
            case ButtonClass:
                {
                    XButtonInfoPtr B = (XButtonInfoPtr) *Any;
                    xButtonInfoPtr b = (xButtonInfoPtr) *any;

                    B->class = ButtonClass;
136
                    B->length = pad_to_xid(sizeof(XButtonInfo));
137 138 139 140 141
                    B->num_buttons = b->num_buttons;
                    break;
                }
            case ValuatorClass:
                {
Peter Hutterer's avatar
Peter Hutterer committed
142
                    int k;
143 144 145 146 147 148
                    XValuatorInfoPtr V = (XValuatorInfoPtr) *Any;
                    xValuatorInfoPtr v = (xValuatorInfoPtr) *any;
                    XAxisInfoPtr A;
                    xAxisInfoPtr a;

                    V->class = ValuatorClass;
149 150
                    V->length = pad_to_xid(sizeof(XValuatorInfo) +
                        (v->num_axes * sizeof(XAxisInfo)));
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
                    V->num_axes = v->num_axes;
                    V->motion_buffer = v->motion_buffer_size;
                    V->mode = v->mode;
                    A = (XAxisInfoPtr) ((char *)V + sizeof(XValuatorInfo));
                    V->axes = A;
                    a = (xAxisInfoPtr) ((char *)(*any) + sizeof(xValuatorInfo));
                    for (k = 0; k < (int)v->num_axes; k++, a++, A++) {
                        A->min_value = a->min_value;
                        A->max_value = a->max_value;
                        A->resolution = a->resolution;
                    }
                    break;
                }
            default:
                break;
        }
        *any = (xAnyClassPtr) ((char *)(*any) + (*any)->length);
        *Any = (XAnyClassPtr) ((char *)(*Any) + (*Any)->length);
    }
}

172
XDeviceInfo *
173 174 175
XListInputDevices(
    register Display	*dpy,
    int			*ndevices)
Daniel Stone's avatar
Daniel Stone committed
176
{
177
    size_t s, size;
Daniel Stone's avatar
Daniel Stone committed
178 179 180 181 182 183 184
    xListInputDevicesReq *req;
    xListInputDevicesReply rep;
    xDeviceInfo *list, *slist = NULL;
    XDeviceInfo *sclist = NULL;
    XDeviceInfo *clist = NULL;
    xAnyClassPtr any, sav_any;
    XAnyClassPtr Any;
185
    char *end = NULL;
186
    unsigned char *nptr, *Nptr;
187
    int i;
188
    unsigned long rlen;
Daniel Stone's avatar
Daniel Stone committed
189 190 191
    XExtDisplayInfo *info = XInput_find_display(dpy);

    LockDisplay(dpy);
192
    if (_XiCheckExtInit(dpy, XInput_Initial_Release, info) == -1)
193 194
	return ((XDeviceInfo *) NULL);

Daniel Stone's avatar
Daniel Stone committed
195
    GetReq(ListInputDevices, req);
196 197 198
    req->reqType = info->codes->major_opcode;
    req->ReqType = X_ListInputDevices;

Daniel Stone's avatar
Daniel Stone committed
199
    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
200 201 202
	UnlockDisplay(dpy);
	SyncHandle();
	return (XDeviceInfo *) NULL;
Daniel Stone's avatar
Daniel Stone committed
203
    }
204

Daniel Stone's avatar
Daniel Stone committed
205 206
    if ((*ndevices = rep.ndevices)) {	/* at least 1 input device */
	size = *ndevices * sizeof(XDeviceInfo);
207 208 209 210
	if (rep.length < (INT_MAX >> 2)) {
	    rlen = rep.length << 2;	/* multiply length by 4    */
	    slist = list = Xmalloc(rlen);
	}
Daniel Stone's avatar
Daniel Stone committed
211
	if (!slist) {
212
	    _XEatDataWords(dpy, rep.length);
213 214 215
	    UnlockDisplay(dpy);
	    SyncHandle();
	    return (XDeviceInfo *) NULL;
Daniel Stone's avatar
Daniel Stone committed
216 217
	}
	_XRead(dpy, (char *)list, rlen);
218

Daniel Stone's avatar
Daniel Stone committed
219
	any = (xAnyClassPtr) ((char *)list + (*ndevices * sizeof(xDeviceInfo)));
220
	sav_any = any;
221
	end = (char *)list + rlen;
Daniel Stone's avatar
Daniel Stone committed
222
	for (i = 0; i < *ndevices; i++, list++) {
223 224 225 226
            s = SizeClassInfo(&any, end - (char *)any, (int)list->num_classes);
            if (!s)
                goto out;
            size += s;
Daniel Stone's avatar
Daniel Stone committed
227
	}
228

229
	Nptr = ((unsigned char *)list) + rlen;
230
	for (i = 0, nptr = (unsigned char *)any; i < *ndevices; i++) {
231 232
	    if (nptr >= Nptr)
		goto out;
Daniel Stone's avatar
Daniel Stone committed
233
	    size += *nptr + 1;
234
	    nptr += (*nptr + 1);
Daniel Stone's avatar
Daniel Stone committed
235
	}
236

Daniel Stone's avatar
Daniel Stone committed
237 238 239
	clist = (XDeviceInfoPtr) Xmalloc(size);
	if (!clist) {
	    XFree((char *)slist);
240 241 242
	    UnlockDisplay(dpy);
	    SyncHandle();
	    return (XDeviceInfo *) NULL;
Daniel Stone's avatar
Daniel Stone committed
243
	}
244
	sclist = clist;
Daniel Stone's avatar
Daniel Stone committed
245 246
	Any = (XAnyClassPtr) ((char *)clist +
			      (*ndevices * sizeof(XDeviceInfo)));
247 248
	list = slist;
	any = sav_any;
Daniel Stone's avatar
Daniel Stone committed
249 250
	for (i = 0; i < *ndevices; i++, list++, clist++) {
	    clist->type = list->type;
251 252
	    clist->id = list->id;
	    clist->use = list->use;
253
	    clist->num_classes = list->num_classes;
254
	    clist->inputclassinfo = Any;
255 256

            ParseClassInfo(&any, &Any, (int)list->num_classes);
Daniel Stone's avatar
Daniel Stone committed
257
	}
258 259

	clist = sclist;
260 261
	nptr = (unsigned char *)any;
	Nptr = (unsigned char *)Any;
Daniel Stone's avatar
Daniel Stone committed
262 263 264
	for (i = 0; i < *ndevices; i++, clist++) {
	    clist->name = (char *)Nptr;
	    memcpy(Nptr, nptr + 1, *nptr);
265 266 267 268
	    Nptr += (*nptr);
	    *Nptr++ = '\0';
	    nptr += (*nptr + 1);
	}
Daniel Stone's avatar
Daniel Stone committed
269
    }
270

271
  out:
Daniel Stone's avatar
Daniel Stone committed
272
    XFree((char *)slist);
273 274 275
    UnlockDisplay(dpy);
    SyncHandle();
    return (sclist);
Daniel Stone's avatar
Daniel Stone committed
276
}
277 278 279 280 281 282 283

/***********************************************************************
 *
 * Free the list of input devices.
 *
 */

Daniel Stone's avatar
Daniel Stone committed
284
void
285
XFreeDeviceList(XDeviceInfo *list)
Daniel Stone's avatar
Daniel Stone committed
286 287 288
{
    if (list != NULL) {
	XFree((char *)list);
289
    }
Daniel Stone's avatar
Daniel Stone committed
290
}