XGetDCtl.c revision 64276682
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 * XGetDeviceControl - get the Device control state of an extension device.
50 *
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/Xlib.h>
61#include <X11/extensions/XInput.h>
62#include <X11/extensions/extutil.h>
63#include "XIint.h"
64#include <limits.h>
65
66XDeviceControl *
67XGetDeviceControl(
68    register Display	*dpy,
69    XDevice		*dev,
70    int			 control)
71{
72    XDeviceControl *Device = NULL;
73    XDeviceControl *Sav = NULL;
74    xDeviceState *d = NULL;
75    xDeviceState *sav = NULL;
76    xGetDeviceControlReq *req;
77    xGetDeviceControlReply rep;
78    XExtDisplayInfo *info = XInput_find_display(dpy);
79
80    LockDisplay(dpy);
81    if (_XiCheckExtInit(dpy, XInput_Add_XChangeDeviceControl, info) == -1)
82        return NULL;
83
84    GetReq(GetDeviceControl, req);
85    req->reqType = info->codes->major_opcode;
86    req->ReqType = X_GetDeviceControl;
87    req->deviceid = dev->device_id;
88    req->control = control;
89
90    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse))
91	goto out;
92
93    if (rep.length > 0) {
94	unsigned long nbytes;
95	size_t size = 0;
96	if (rep.length < (INT_MAX >> 2)) {
97	    nbytes = (unsigned long) rep.length << 2;
98	    d = Xmalloc(nbytes);
99	}
100	if (!d) {
101	    _XEatDataWords(dpy, rep.length);
102	    goto out;
103	}
104	sav = d;
105	_XRead(dpy, (char *)d, nbytes);
106
107        /* In theory, we should just be able to use d->length to get the size.
108         * Turns out that a number of X servers (up to and including server
109         * 1.4) sent the wrong length value down the wire. So to not break
110         * apps that run against older servers, we have to calculate the size
111         * manually.
112         */
113	switch (d->control) {
114	case DEVICE_RESOLUTION:
115	{
116	    xDeviceResolutionState *r;
117	    size_t val_size;
118
119	    r = (xDeviceResolutionState *) d;
120	    if (r->num_valuators >= (INT_MAX / (3 * sizeof(int))))
121		goto out;
122	    val_size = 3 * sizeof(int) * r->num_valuators;
123	    if ((sizeof(xDeviceResolutionState) + val_size) > nbytes)
124		goto out;
125	    size = sizeof(XDeviceResolutionState) + val_size;
126	    break;
127	}
128        case DEVICE_ABS_CALIB:
129        {
130            if (sizeof(xDeviceAbsCalibState) > nbytes)
131                goto out;
132            size = sizeof(XDeviceAbsCalibState);
133            break;
134        }
135        case DEVICE_ABS_AREA:
136        {
137            if (sizeof(xDeviceAbsAreaState) > nbytes)
138                goto out;
139            size = sizeof(XDeviceAbsAreaState);
140            break;
141        }
142        case DEVICE_CORE:
143        {
144            if (sizeof(xDeviceCoreState) > nbytes)
145                goto out;
146            size = sizeof(XDeviceCoreState);
147            break;
148        }
149	default:
150	    if (d->length > nbytes)
151		goto out;
152	    size = d->length;
153	    break;
154	}
155
156	Device = Xmalloc(size);
157	if (!Device)
158	    goto out;
159
160	Sav = Device;
161
162	d = sav;
163	switch (control) {
164	case DEVICE_RESOLUTION:
165	{
166	    int *iptr, *iptr2;
167	    xDeviceResolutionState *r;
168	    XDeviceResolutionState *R;
169	    unsigned int i;
170
171	    r = (xDeviceResolutionState *) d;
172	    R = (XDeviceResolutionState *) Device;
173
174	    R->control = DEVICE_RESOLUTION;
175	    R->length = sizeof(XDeviceResolutionState);
176	    R->num_valuators = r->num_valuators;
177	    iptr = (int *)(R + 1);
178	    iptr2 = (int *)(r + 1);
179	    R->resolutions = iptr;
180	    R->min_resolutions = iptr + R->num_valuators;
181	    R->max_resolutions = iptr + (2 * R->num_valuators);
182	    for (i = 0; i < (3 * R->num_valuators); i++)
183		*iptr++ = *iptr2++;
184	    break;
185	}
186        case DEVICE_ABS_CALIB:
187        {
188            xDeviceAbsCalibState *c = (xDeviceAbsCalibState *) d;
189            XDeviceAbsCalibState *C = (XDeviceAbsCalibState *) Device;
190
191            C->control = DEVICE_ABS_CALIB;
192            C->length = sizeof(XDeviceAbsCalibState);
193            C->min_x = c->min_x;
194            C->max_x = c->max_x;
195            C->min_y = c->min_y;
196            C->max_y = c->max_y;
197            C->flip_x = c->flip_x;
198            C->flip_y = c->flip_y;
199            C->rotation = c->rotation;
200            C->button_threshold = c->button_threshold;
201
202            break;
203        }
204        case DEVICE_ABS_AREA:
205        {
206            xDeviceAbsAreaState *a = (xDeviceAbsAreaState *) d;
207            XDeviceAbsAreaState *A = (XDeviceAbsAreaState *) Device;
208
209            A->control = DEVICE_ABS_AREA;
210            A->length = sizeof(XDeviceAbsAreaState);
211            A->offset_x = a->offset_x;
212            A->offset_y = a->offset_y;
213            A->width = a->width;
214            A->height = a->height;
215            A->screen = a->screen;
216            A->following = a->following;
217
218            break;
219        }
220        case DEVICE_CORE:
221        {
222            xDeviceCoreState *c = (xDeviceCoreState *) d;
223            XDeviceCoreState *C = (XDeviceCoreState *) Device;
224
225            C->control = DEVICE_CORE;
226            C->length = sizeof(XDeviceCoreState);
227            C->status = c->status;
228            C->iscore = c->iscore;
229
230            break;
231        }
232        case DEVICE_ENABLE:
233        {
234            xDeviceEnableState *e = (xDeviceEnableState *) d;
235            XDeviceEnableState *E = (XDeviceEnableState *) Device;
236
237            E->control = DEVICE_ENABLE;
238            E->length = sizeof(E);
239            E->enable = e->enable;
240
241            break;
242        }
243	default:
244	    break;
245	}
246    }
247out:
248    XFree(sav);
249
250    UnlockDisplay(dpy);
251    SyncHandle();
252    return (Sav);
253}
254
255void
256XFreeDeviceControl(XDeviceControl *control)
257{
258    XFree(control);
259}
260