XListDev.c revision f1ee322d
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
64/* Calculate length field to a multiples of sizeof(XID). XIDs are typedefs
65 * to ulong and thus may be 8 bytes on some platforms. This can trigger a
66 * SIGBUS if a class ends up not being 8-aligned (e.g. after XAxisInfo).
67 */
68static int pad_to_xid(int base_size)
69{
70    int padsize = sizeof(XID);
71
72    return ((base_size + padsize - 1)/padsize) * padsize;
73}
74
75static int
76SizeClassInfo(xAnyClassPtr *any, int num_classes)
77{
78    int size = 0;
79    int j;
80    for (j = 0; j < num_classes; j++) {
81        switch ((*any)->class) {
82            case KeyClass:
83                size += pad_to_xid(sizeof(XKeyInfo));
84                break;
85            case ButtonClass:
86                size += pad_to_xid(sizeof(XButtonInfo));
87                break;
88            case ValuatorClass:
89                {
90                    xValuatorInfoPtr v;
91
92                    v = (xValuatorInfoPtr) *any;
93                    size += pad_to_xid(sizeof(XValuatorInfo) +
94                        (v->num_axes * sizeof(XAxisInfo)));
95                    break;
96                }
97            default:
98                break;
99        }
100        *any = (xAnyClassPtr) ((char *)(*any) + (*any)->length);
101    }
102
103    return size;
104}
105
106static void
107ParseClassInfo(xAnyClassPtr *any, XAnyClassPtr *Any, int num_classes)
108{
109    int j;
110
111    for (j = 0; j < num_classes; j++) {
112        switch ((*any)->class) {
113            case KeyClass:
114                {
115                    XKeyInfoPtr K = (XKeyInfoPtr) *Any;
116                    xKeyInfoPtr k = (xKeyInfoPtr) *any;
117
118                    K->class = KeyClass;
119                    K->length = pad_to_xid(sizeof(XKeyInfo));
120                    K->min_keycode = k->min_keycode;
121                    K->max_keycode = k->max_keycode;
122                    K->num_keys = k->num_keys;
123                    break;
124                }
125            case ButtonClass:
126                {
127                    XButtonInfoPtr B = (XButtonInfoPtr) *Any;
128                    xButtonInfoPtr b = (xButtonInfoPtr) *any;
129
130                    B->class = ButtonClass;
131                    B->length = pad_to_xid(sizeof(XButtonInfo));
132                    B->num_buttons = b->num_buttons;
133                    break;
134                }
135            case ValuatorClass:
136                {
137                    int k;
138                    XValuatorInfoPtr V = (XValuatorInfoPtr) *Any;
139                    xValuatorInfoPtr v = (xValuatorInfoPtr) *any;
140                    XAxisInfoPtr A;
141                    xAxisInfoPtr a;
142
143                    V->class = ValuatorClass;
144                    V->length = pad_to_xid(sizeof(XValuatorInfo) +
145                        (v->num_axes * sizeof(XAxisInfo)));
146                    V->num_axes = v->num_axes;
147                    V->motion_buffer = v->motion_buffer_size;
148                    V->mode = v->mode;
149                    A = (XAxisInfoPtr) ((char *)V + sizeof(XValuatorInfo));
150                    V->axes = A;
151                    a = (xAxisInfoPtr) ((char *)(*any) + sizeof(xValuatorInfo));
152                    for (k = 0; k < (int)v->num_axes; k++, a++, A++) {
153                        A->min_value = a->min_value;
154                        A->max_value = a->max_value;
155                        A->resolution = a->resolution;
156                    }
157                    break;
158                }
159            default:
160                break;
161        }
162        *any = (xAnyClassPtr) ((char *)(*any) + (*any)->length);
163        *Any = (XAnyClassPtr) ((char *)(*Any) + (*Any)->length);
164    }
165}
166
167XDeviceInfo *
168XListInputDevices(
169    register Display	*dpy,
170    int			*ndevices)
171{
172    int size;
173    xListInputDevicesReq *req;
174    xListInputDevicesReply rep;
175    xDeviceInfo *list, *slist = NULL;
176    XDeviceInfo *sclist = NULL;
177    XDeviceInfo *clist = NULL;
178    xAnyClassPtr any, sav_any;
179    XAnyClassPtr Any;
180    char *nptr, *Nptr;
181    int i;
182    long rlen;
183    XExtDisplayInfo *info = XInput_find_display(dpy);
184
185    LockDisplay(dpy);
186    if (_XiCheckExtInit(dpy, XInput_Initial_Release, info) == -1)
187	return ((XDeviceInfo *) NULL);
188
189    GetReq(ListInputDevices, req);
190    req->reqType = info->codes->major_opcode;
191    req->ReqType = X_ListInputDevices;
192
193    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
194	UnlockDisplay(dpy);
195	SyncHandle();
196	return (XDeviceInfo *) NULL;
197    }
198
199    if ((*ndevices = rep.ndevices)) {	/* at least 1 input device */
200	size = *ndevices * sizeof(XDeviceInfo);
201	rlen = rep.length << 2;	/* multiply length by 4    */
202	list = (xDeviceInfo *) Xmalloc(rlen);
203	slist = list;
204	if (!slist) {
205	    _XEatData(dpy, (unsigned long)rlen);
206	    UnlockDisplay(dpy);
207	    SyncHandle();
208	    return (XDeviceInfo *) NULL;
209	}
210	_XRead(dpy, (char *)list, rlen);
211
212	any = (xAnyClassPtr) ((char *)list + (*ndevices * sizeof(xDeviceInfo)));
213	sav_any = any;
214	for (i = 0; i < *ndevices; i++, list++) {
215            size += SizeClassInfo(&any, (int)list->num_classes);
216	}
217
218	for (i = 0, nptr = (char *)any; i < *ndevices; i++) {
219	    size += *nptr + 1;
220	    nptr += (*nptr + 1);
221	}
222
223	clist = (XDeviceInfoPtr) Xmalloc(size);
224	if (!clist) {
225	    XFree((char *)slist);
226	    UnlockDisplay(dpy);
227	    SyncHandle();
228	    return (XDeviceInfo *) NULL;
229	}
230	sclist = clist;
231	Any = (XAnyClassPtr) ((char *)clist +
232			      (*ndevices * sizeof(XDeviceInfo)));
233	list = slist;
234	any = sav_any;
235	for (i = 0; i < *ndevices; i++, list++, clist++) {
236	    clist->type = list->type;
237	    clist->id = list->id;
238	    clist->use = list->use;
239	    clist->num_classes = list->num_classes;
240	    clist->inputclassinfo = Any;
241
242            ParseClassInfo(&any, &Any, (int)list->num_classes);
243	}
244
245	clist = sclist;
246	nptr = (char *)any;
247	Nptr = (char *)Any;
248	for (i = 0; i < *ndevices; i++, clist++) {
249	    clist->name = (char *)Nptr;
250	    memcpy(Nptr, nptr + 1, *nptr);
251	    Nptr += (*nptr);
252	    *Nptr++ = '\0';
253	    nptr += (*nptr + 1);
254	}
255    }
256
257    XFree((char *)slist);
258    UnlockDisplay(dpy);
259    SyncHandle();
260    return (sclist);
261}
262
263/***********************************************************************
264 *
265 * Free the list of input devices.
266 *
267 */
268
269void
270XFreeDeviceList(XDeviceInfo *list)
271{
272    if (list != NULL) {
273	XFree((char *)list);
274    }
275}
276