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