XListDev.c revision 190694da
1/************************************************************
2
3Copyright 1989, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
26
27			All Rights Reserved
28
29Permission to use, copy, modify, and distribute this software and its
30documentation for any purpose and without fee is hereby granted,
31provided that the above copyright notice appear in all copies and that
32both that copyright notice and this permission notice appear in
33supporting documentation, and that the name of Hewlett-Packard not be
34used in advertising or publicity pertaining to distribution of the
35software without specific, written prior permission.
36
37HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43SOFTWARE.
44
45********************************************************/
46
47/***********************************************************************
48 *
49 * XListInputDevices - Request the server to return a list of
50 *			 available input devices.
51 *
52 */
53#ifdef HAVE_CONFIG_H
54#include <config.h>
55#endif
56
57#include <X11/extensions/XI.h>
58#include <X11/extensions/XIproto.h>
59#include <X11/Xlibint.h>
60#include <X11/extensions/XInput.h>
61#include <X11/extensions/extutil.h>
62#include "XIint.h"
63#include <limits.h>
64
65/* Calculate length field to a multiples of sizeof(XID). XIDs are typedefs
66 * to ulong and thus may be 8 bytes on some platforms. This can trigger a
67 * SIGBUS if a class ends up not being 8-aligned (e.g. after XAxisInfo).
68 */
69static int pad_to_xid(int base_size)
70{
71    int padsize = sizeof(XID);
72
73    return ((base_size + padsize - 1)/padsize) * padsize;
74}
75
76static size_t
77SizeClassInfo(xAnyClassPtr *any, int num_classes)
78{
79    int size = 0;
80    int j;
81    for (j = 0; j < num_classes; j++) {
82        switch ((*any)->class) {
83            case KeyClass:
84                size += pad_to_xid(sizeof(XKeyInfo));
85                break;
86            case ButtonClass:
87                size += pad_to_xid(sizeof(XButtonInfo));
88                break;
89            case ValuatorClass:
90                {
91                    xValuatorInfoPtr v;
92
93                    v = (xValuatorInfoPtr) *any;
94                    size += pad_to_xid(sizeof(XValuatorInfo) +
95                        (v->num_axes * sizeof(XAxisInfo)));
96                    break;
97                }
98            default:
99                break;
100        }
101        *any = (xAnyClassPtr) ((char *)(*any) + (*any)->length);
102    }
103
104    return size;
105}
106
107static void
108ParseClassInfo(xAnyClassPtr *any, XAnyClassPtr *Any, int num_classes)
109{
110    int j;
111
112    for (j = 0; j < num_classes; j++) {
113        switch ((*any)->class) {
114            case KeyClass:
115                {
116                    XKeyInfoPtr K = (XKeyInfoPtr) *Any;
117                    xKeyInfoPtr k = (xKeyInfoPtr) *any;
118
119                    K->class = KeyClass;
120                    K->length = pad_to_xid(sizeof(XKeyInfo));
121                    K->min_keycode = k->min_keycode;
122                    K->max_keycode = k->max_keycode;
123                    K->num_keys = k->num_keys;
124                    break;
125                }
126            case ButtonClass:
127                {
128                    XButtonInfoPtr B = (XButtonInfoPtr) *Any;
129                    xButtonInfoPtr b = (xButtonInfoPtr) *any;
130
131                    B->class = ButtonClass;
132                    B->length = pad_to_xid(sizeof(XButtonInfo));
133                    B->num_buttons = b->num_buttons;
134                    break;
135                }
136            case ValuatorClass:
137                {
138                    int k;
139                    XValuatorInfoPtr V = (XValuatorInfoPtr) *Any;
140                    xValuatorInfoPtr v = (xValuatorInfoPtr) *any;
141                    XAxisInfoPtr A;
142                    xAxisInfoPtr a;
143
144                    V->class = ValuatorClass;
145                    V->length = pad_to_xid(sizeof(XValuatorInfo) +
146                        (v->num_axes * sizeof(XAxisInfo)));
147                    V->num_axes = v->num_axes;
148                    V->motion_buffer = v->motion_buffer_size;
149                    V->mode = v->mode;
150                    A = (XAxisInfoPtr) ((char *)V + sizeof(XValuatorInfo));
151                    V->axes = A;
152                    a = (xAxisInfoPtr) ((char *)(*any) + sizeof(xValuatorInfo));
153                    for (k = 0; k < (int)v->num_axes; k++, a++, A++) {
154                        A->min_value = a->min_value;
155                        A->max_value = a->max_value;
156                        A->resolution = a->resolution;
157                    }
158                    break;
159                }
160            default:
161                break;
162        }
163        *any = (xAnyClassPtr) ((char *)(*any) + (*any)->length);
164        *Any = (XAnyClassPtr) ((char *)(*Any) + (*Any)->length);
165    }
166}
167
168XDeviceInfo *
169XListInputDevices(
170    register Display	*dpy,
171    int			*ndevices)
172{
173    size_t size;
174    xListInputDevicesReq *req;
175    xListInputDevicesReply rep;
176    xDeviceInfo *list, *slist = NULL;
177    XDeviceInfo *sclist = NULL;
178    XDeviceInfo *clist = NULL;
179    xAnyClassPtr any, sav_any;
180    XAnyClassPtr Any;
181    unsigned char *nptr, *Nptr;
182    int i;
183    unsigned long rlen;
184    XExtDisplayInfo *info = XInput_find_display(dpy);
185
186    LockDisplay(dpy);
187    if (_XiCheckExtInit(dpy, XInput_Initial_Release, info) == -1)
188	return ((XDeviceInfo *) NULL);
189
190    GetReq(ListInputDevices, req);
191    req->reqType = info->codes->major_opcode;
192    req->ReqType = X_ListInputDevices;
193
194    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
195	UnlockDisplay(dpy);
196	SyncHandle();
197	return (XDeviceInfo *) NULL;
198    }
199
200    if ((*ndevices = rep.ndevices)) {	/* at least 1 input device */
201	size = *ndevices * sizeof(XDeviceInfo);
202	if (rep.length < (INT_MAX >> 2)) {
203	    rlen = rep.length << 2;	/* multiply length by 4    */
204	    slist = list = Xmalloc(rlen);
205	}
206	if (!slist) {
207	    _XEatData(dpy, (unsigned long)rlen);
208	    UnlockDisplay(dpy);
209	    SyncHandle();
210	    return (XDeviceInfo *) NULL;
211	}
212	_XRead(dpy, (char *)list, rlen);
213
214	any = (xAnyClassPtr) ((char *)list + (*ndevices * sizeof(xDeviceInfo)));
215	sav_any = any;
216	for (i = 0; i < *ndevices; i++, list++) {
217            size += SizeClassInfo(&any, (int)list->num_classes);
218	}
219
220	Nptr = ((unsigned char *)list) + rlen + 1;
221	for (i = 0, nptr = (unsigned char *)any; i < *ndevices; i++) {
222	    size += *nptr + 1;
223	    nptr += (*nptr + 1);
224	    if (nptr > Nptr)
225		goto out;
226	}
227
228	clist = (XDeviceInfoPtr) Xmalloc(size);
229	if (!clist) {
230	    XFree((char *)slist);
231	    UnlockDisplay(dpy);
232	    SyncHandle();
233	    return (XDeviceInfo *) NULL;
234	}
235	sclist = clist;
236	Any = (XAnyClassPtr) ((char *)clist +
237			      (*ndevices * sizeof(XDeviceInfo)));
238	list = slist;
239	any = sav_any;
240	for (i = 0; i < *ndevices; i++, list++, clist++) {
241	    clist->type = list->type;
242	    clist->id = list->id;
243	    clist->use = list->use;
244	    clist->num_classes = list->num_classes;
245	    clist->inputclassinfo = Any;
246
247            ParseClassInfo(&any, &Any, (int)list->num_classes);
248	}
249
250	clist = sclist;
251	nptr = (unsigned char *)any;
252	Nptr = (unsigned char *)Any;
253	for (i = 0; i < *ndevices; i++, clist++) {
254	    clist->name = (char *)Nptr;
255	    memcpy(Nptr, nptr + 1, *nptr);
256	    Nptr += (*nptr);
257	    *Nptr++ = '\0';
258	    nptr += (*nptr + 1);
259	}
260    }
261
262  out:
263    XFree((char *)slist);
264    UnlockDisplay(dpy);
265    SyncHandle();
266    return (sclist);
267}
268
269/***********************************************************************
270 *
271 * Free the list of input devices.
272 *
273 */
274
275void
276XFreeDeviceList(XDeviceInfo *list)
277{
278    if (list != NULL) {
279	XFree((char *)list);
280    }
281}
282