xref: /OK3568_Linux_fs/external/xserver/Xi/xiproperty.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright © 2006 Keith Packard
3*4882a593Smuzhiyun  * Copyright © 2008 Peter Hutterer
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining a
6*4882a593Smuzhiyun  * copy of this software and associated documentation files (the "Software"),
7*4882a593Smuzhiyun  * to deal in the Software without restriction, including without limitation
8*4882a593Smuzhiyun  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9*4882a593Smuzhiyun  * and/or sell copies of the Software, and to permit persons to whom the
10*4882a593Smuzhiyun  * Software is furnished to do so, subject to the following conditions:
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  * The above copyright notice and this permission notice (including the next
13*4882a593Smuzhiyun  * paragraph) shall be included in all copies or substantial portions of the
14*4882a593Smuzhiyun  * Software.
15*4882a593Smuzhiyun  *
16*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WAXIANTY OF ANY KIND, EXPRESS OR
17*4882a593Smuzhiyun  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WAXIANTIES OF MERCHANTABILITY,
18*4882a593Smuzhiyun  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19*4882a593Smuzhiyun  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*4882a593Smuzhiyun  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*4882a593Smuzhiyun  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22*4882a593Smuzhiyun  * DEALINGS IN THE SOFTWARE.
23*4882a593Smuzhiyun  *
24*4882a593Smuzhiyun  */
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun /* This code is a modified version of randr/rrproperty.c */
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
29*4882a593Smuzhiyun #include <dix-config.h>
30*4882a593Smuzhiyun #endif
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun #include "dix.h"
33*4882a593Smuzhiyun #include "inputstr.h"
34*4882a593Smuzhiyun #include <X11/extensions/XI.h>
35*4882a593Smuzhiyun #include <X11/Xatom.h>
36*4882a593Smuzhiyun #include <X11/extensions/XIproto.h>
37*4882a593Smuzhiyun #include <X11/extensions/XI2proto.h>
38*4882a593Smuzhiyun #include "exglobals.h"
39*4882a593Smuzhiyun #include "exevents.h"
40*4882a593Smuzhiyun #include "swaprep.h"
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun #include "xiproperty.h"
43*4882a593Smuzhiyun #include "xserver-properties.h"
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun /**
46*4882a593Smuzhiyun  * Properties used or alloced from inside the server.
47*4882a593Smuzhiyun  */
48*4882a593Smuzhiyun static struct dev_properties {
49*4882a593Smuzhiyun     Atom type;
50*4882a593Smuzhiyun     const char *name;
51*4882a593Smuzhiyun } dev_properties[] = {
52*4882a593Smuzhiyun     {0, XI_PROP_ENABLED},
53*4882a593Smuzhiyun     {0, XI_PROP_XTEST_DEVICE},
54*4882a593Smuzhiyun     {0, XATOM_FLOAT},
55*4882a593Smuzhiyun     {0, ACCEL_PROP_PROFILE_NUMBER},
56*4882a593Smuzhiyun     {0, ACCEL_PROP_CONSTANT_DECELERATION},
57*4882a593Smuzhiyun     {0, ACCEL_PROP_ADAPTIVE_DECELERATION},
58*4882a593Smuzhiyun     {0, ACCEL_PROP_VELOCITY_SCALING},
59*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP},
60*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_REL_X},
61*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_REL_Y},
62*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_REL_Z},
63*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_REL_RX},
64*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_REL_RY},
65*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_REL_RZ},
66*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_REL_HWHEEL},
67*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_REL_DIAL},
68*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_REL_WHEEL},
69*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_REL_MISC},
70*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_REL_VSCROLL},
71*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_REL_HSCROLL},
72*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_X},
73*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_Y},
74*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_Z},
75*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_RX},
76*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_RY},
77*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_RZ},
78*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_THROTTLE},
79*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_RUDDER},
80*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_WHEEL},
81*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_GAS},
82*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_BRAKE},
83*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_HAT0X},
84*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_HAT0Y},
85*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_HAT1X},
86*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_HAT1Y},
87*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_HAT2X},
88*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_HAT2Y},
89*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_HAT3X},
90*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_HAT3Y},
91*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_PRESSURE},
92*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_DISTANCE},
93*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_TILT_X},
94*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_TILT_Y},
95*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_TOOL_WIDTH},
96*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_VOLUME},
97*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR},
98*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR},
99*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_MT_WIDTH_MAJOR},
100*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_MT_WIDTH_MINOR},
101*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_MT_ORIENTATION},
102*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_MT_POSITION_X},
103*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_MT_POSITION_Y},
104*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_MT_TOOL_TYPE},
105*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_MT_BLOB_ID},
106*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_MT_TRACKING_ID},
107*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_MT_PRESSURE},
108*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_MT_DISTANCE},
109*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_MT_TOOL_X},
110*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_MT_TOOL_Y},
111*4882a593Smuzhiyun     {0, AXIS_LABEL_PROP_ABS_MISC},
112*4882a593Smuzhiyun     {0, BTN_LABEL_PROP},
113*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_UNKNOWN},
114*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_WHEEL_UP},
115*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_WHEEL_DOWN},
116*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_HWHEEL_LEFT},
117*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_HWHEEL_RIGHT},
118*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_0},
119*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_1},
120*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_2},
121*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_3},
122*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_4},
123*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_5},
124*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_6},
125*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_7},
126*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_8},
127*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_9},
128*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_LEFT},
129*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_RIGHT},
130*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_MIDDLE},
131*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_SIDE},
132*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_EXTRA},
133*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_FORWARD},
134*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_BACK},
135*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_TASK},
136*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_TRIGGER},
137*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_THUMB},
138*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_THUMB2},
139*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_TOP},
140*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_TOP2},
141*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_PINKIE},
142*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_BASE},
143*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_BASE2},
144*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_BASE3},
145*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_BASE4},
146*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_BASE5},
147*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_BASE6},
148*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_DEAD},
149*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_A},
150*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_B},
151*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_C},
152*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_X},
153*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_Y},
154*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_Z},
155*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_TL},
156*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_TR},
157*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_TL2},
158*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_TR2},
159*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_SELECT},
160*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_START},
161*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_MODE},
162*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_THUMBL},
163*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_THUMBR},
164*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_TOOL_PEN},
165*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_TOOL_RUBBER},
166*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_TOOL_BRUSH},
167*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_TOOL_PENCIL},
168*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_TOOL_AIRBRUSH},
169*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_TOOL_FINGER},
170*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_TOOL_MOUSE},
171*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_TOOL_LENS},
172*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_TOUCH},
173*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_STYLUS},
174*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_STYLUS2},
175*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_TOOL_DOUBLETAP},
176*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_TOOL_TRIPLETAP},
177*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_GEAR_DOWN},
178*4882a593Smuzhiyun     {0, BTN_LABEL_PROP_BTN_GEAR_UP},
179*4882a593Smuzhiyun     {0, XI_PROP_TRANSFORM}
180*4882a593Smuzhiyun };
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun static long XIPropHandlerID = 1;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun static void
send_property_event(DeviceIntPtr dev,Atom property,int what)185*4882a593Smuzhiyun send_property_event(DeviceIntPtr dev, Atom property, int what)
186*4882a593Smuzhiyun {
187*4882a593Smuzhiyun     int state = (what == XIPropertyDeleted) ? PropertyDelete : PropertyNewValue;
188*4882a593Smuzhiyun     devicePropertyNotify event = {
189*4882a593Smuzhiyun         .type = DevicePropertyNotify,
190*4882a593Smuzhiyun         .deviceid = dev->id,
191*4882a593Smuzhiyun         .state = state,
192*4882a593Smuzhiyun         .atom = property,
193*4882a593Smuzhiyun         .time = currentTime.milliseconds
194*4882a593Smuzhiyun     };
195*4882a593Smuzhiyun     xXIPropertyEvent xi2 = {
196*4882a593Smuzhiyun         .type = GenericEvent,
197*4882a593Smuzhiyun         .extension = IReqCode,
198*4882a593Smuzhiyun         .length = 0,
199*4882a593Smuzhiyun         .evtype = XI_PropertyEvent,
200*4882a593Smuzhiyun         .deviceid = dev->id,
201*4882a593Smuzhiyun         .time = currentTime.milliseconds,
202*4882a593Smuzhiyun         .property = property,
203*4882a593Smuzhiyun         .what = what
204*4882a593Smuzhiyun     };
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun     SendEventToAllWindows(dev, DevicePropertyNotifyMask, (xEvent *) &event, 1);
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun     SendEventToAllWindows(dev, GetEventFilter(dev, (xEvent *) &xi2),
209*4882a593Smuzhiyun                           (xEvent *) &xi2, 1);
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun static int
list_atoms(DeviceIntPtr dev,int * natoms,Atom ** atoms_return)213*4882a593Smuzhiyun list_atoms(DeviceIntPtr dev, int *natoms, Atom **atoms_return)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun     XIPropertyPtr prop;
216*4882a593Smuzhiyun     Atom *atoms = NULL;
217*4882a593Smuzhiyun     int nprops = 0;
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun     for (prop = dev->properties.properties; prop; prop = prop->next)
220*4882a593Smuzhiyun         nprops++;
221*4882a593Smuzhiyun     if (nprops) {
222*4882a593Smuzhiyun         Atom *a;
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun         atoms = xallocarray(nprops, sizeof(Atom));
225*4882a593Smuzhiyun         if (!atoms)
226*4882a593Smuzhiyun             return BadAlloc;
227*4882a593Smuzhiyun         a = atoms;
228*4882a593Smuzhiyun         for (prop = dev->properties.properties; prop; prop = prop->next, a++)
229*4882a593Smuzhiyun             *a = prop->propertyName;
230*4882a593Smuzhiyun     }
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun     *natoms = nprops;
233*4882a593Smuzhiyun     *atoms_return = atoms;
234*4882a593Smuzhiyun     return Success;
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun static int
get_property(ClientPtr client,DeviceIntPtr dev,Atom property,Atom type,BOOL delete,int offset,int length,int * bytes_after,Atom * type_return,int * format,int * nitems,int * length_return,char ** data)238*4882a593Smuzhiyun get_property(ClientPtr client, DeviceIntPtr dev, Atom property, Atom type,
239*4882a593Smuzhiyun              BOOL delete, int offset, int length,
240*4882a593Smuzhiyun              int *bytes_after, Atom *type_return, int *format, int *nitems,
241*4882a593Smuzhiyun              int *length_return, char **data)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun     unsigned long n, len, ind;
244*4882a593Smuzhiyun     int rc;
245*4882a593Smuzhiyun     XIPropertyPtr prop;
246*4882a593Smuzhiyun     XIPropertyValuePtr prop_value;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun     if (!ValidAtom(property)) {
249*4882a593Smuzhiyun         client->errorValue = property;
250*4882a593Smuzhiyun         return BadAtom;
251*4882a593Smuzhiyun     }
252*4882a593Smuzhiyun     if ((delete != xTrue) && (delete != xFalse)) {
253*4882a593Smuzhiyun         client->errorValue = delete;
254*4882a593Smuzhiyun         return BadValue;
255*4882a593Smuzhiyun     }
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun     if ((type != AnyPropertyType) && !ValidAtom(type)) {
258*4882a593Smuzhiyun         client->errorValue = type;
259*4882a593Smuzhiyun         return BadAtom;
260*4882a593Smuzhiyun     }
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun     for (prop = dev->properties.properties; prop; prop = prop->next)
263*4882a593Smuzhiyun         if (prop->propertyName == property)
264*4882a593Smuzhiyun             break;
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun     if (!prop) {
267*4882a593Smuzhiyun         *bytes_after = 0;
268*4882a593Smuzhiyun         *type_return = None;
269*4882a593Smuzhiyun         *format = 0;
270*4882a593Smuzhiyun         *nitems = 0;
271*4882a593Smuzhiyun         *length_return = 0;
272*4882a593Smuzhiyun         return Success;
273*4882a593Smuzhiyun     }
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun     rc = XIGetDeviceProperty(dev, property, &prop_value);
276*4882a593Smuzhiyun     if (rc != Success) {
277*4882a593Smuzhiyun         client->errorValue = property;
278*4882a593Smuzhiyun         return rc;
279*4882a593Smuzhiyun     }
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun     /* If the request type and actual type don't match. Return the
282*4882a593Smuzhiyun        property information, but not the data. */
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun     if (((type != prop_value->type) && (type != AnyPropertyType))) {
285*4882a593Smuzhiyun         *bytes_after = prop_value->size;
286*4882a593Smuzhiyun         *format = prop_value->format;
287*4882a593Smuzhiyun         *length_return = 0;
288*4882a593Smuzhiyun         *nitems = 0;
289*4882a593Smuzhiyun         *type_return = prop_value->type;
290*4882a593Smuzhiyun         return Success;
291*4882a593Smuzhiyun     }
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun     /* Return type, format, value to client */
294*4882a593Smuzhiyun     n = (prop_value->format / 8) * prop_value->size;    /* size (bytes) of prop */
295*4882a593Smuzhiyun     ind = offset << 2;
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun     /* If offset is invalid such that it causes "len" to
298*4882a593Smuzhiyun        be negative, it's a value error. */
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun     if (n < ind) {
301*4882a593Smuzhiyun         client->errorValue = offset;
302*4882a593Smuzhiyun         return BadValue;
303*4882a593Smuzhiyun     }
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun     len = min(n - ind, 4 * length);
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun     *bytes_after = n - (ind + len);
308*4882a593Smuzhiyun     *format = prop_value->format;
309*4882a593Smuzhiyun     *length_return = len;
310*4882a593Smuzhiyun     if (prop_value->format)
311*4882a593Smuzhiyun         *nitems = len / (prop_value->format / 8);
312*4882a593Smuzhiyun     else
313*4882a593Smuzhiyun         *nitems = 0;
314*4882a593Smuzhiyun     *type_return = prop_value->type;
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun     *data = (char *) prop_value->data + ind;
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun     return Success;
319*4882a593Smuzhiyun }
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun static int
check_change_property(ClientPtr client,Atom property,Atom type,int format,int mode,int nitems)322*4882a593Smuzhiyun check_change_property(ClientPtr client, Atom property, Atom type, int format,
323*4882a593Smuzhiyun                       int mode, int nitems)
324*4882a593Smuzhiyun {
325*4882a593Smuzhiyun     if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
326*4882a593Smuzhiyun         (mode != PropModePrepend)) {
327*4882a593Smuzhiyun         client->errorValue = mode;
328*4882a593Smuzhiyun         return BadValue;
329*4882a593Smuzhiyun     }
330*4882a593Smuzhiyun     if ((format != 8) && (format != 16) && (format != 32)) {
331*4882a593Smuzhiyun         client->errorValue = format;
332*4882a593Smuzhiyun         return BadValue;
333*4882a593Smuzhiyun     }
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun     if (!ValidAtom(property)) {
336*4882a593Smuzhiyun         client->errorValue = property;
337*4882a593Smuzhiyun         return BadAtom;
338*4882a593Smuzhiyun     }
339*4882a593Smuzhiyun     if (!ValidAtom(type)) {
340*4882a593Smuzhiyun         client->errorValue = type;
341*4882a593Smuzhiyun         return BadAtom;
342*4882a593Smuzhiyun     }
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun     return Success;
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun static int
change_property(ClientPtr client,DeviceIntPtr dev,Atom property,Atom type,int format,int mode,int len,void * data)348*4882a593Smuzhiyun change_property(ClientPtr client, DeviceIntPtr dev, Atom property, Atom type,
349*4882a593Smuzhiyun                 int format, int mode, int len, void *data)
350*4882a593Smuzhiyun {
351*4882a593Smuzhiyun     int rc = Success;
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun     rc = XIChangeDeviceProperty(dev, property, type, format, mode, len, data,
354*4882a593Smuzhiyun                                 TRUE);
355*4882a593Smuzhiyun     if (rc != Success)
356*4882a593Smuzhiyun         client->errorValue = property;
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun     return rc;
359*4882a593Smuzhiyun }
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun /**
362*4882a593Smuzhiyun  * Return the atom assigned to the specified string or 0 if the atom isn't known
363*4882a593Smuzhiyun  * to the DIX.
364*4882a593Smuzhiyun  *
365*4882a593Smuzhiyun  * If name is NULL, None is returned.
366*4882a593Smuzhiyun  */
367*4882a593Smuzhiyun Atom
XIGetKnownProperty(const char * name)368*4882a593Smuzhiyun XIGetKnownProperty(const char *name)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun     int i;
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun     if (!name)
373*4882a593Smuzhiyun         return None;
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun     for (i = 0; i < ARRAY_SIZE(dev_properties); i++) {
376*4882a593Smuzhiyun         if (strcmp(name, dev_properties[i].name) == 0) {
377*4882a593Smuzhiyun             if (dev_properties[i].type == None) {
378*4882a593Smuzhiyun                 dev_properties[i].type =
379*4882a593Smuzhiyun                     MakeAtom(dev_properties[i].name,
380*4882a593Smuzhiyun                              strlen(dev_properties[i].name), TRUE);
381*4882a593Smuzhiyun             }
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun             return dev_properties[i].type;
384*4882a593Smuzhiyun         }
385*4882a593Smuzhiyun     }
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun     return 0;
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun void
XIResetProperties(void)391*4882a593Smuzhiyun XIResetProperties(void)
392*4882a593Smuzhiyun {
393*4882a593Smuzhiyun     int i;
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun     for (i = 0; i < ARRAY_SIZE(dev_properties); i++)
396*4882a593Smuzhiyun         dev_properties[i].type = None;
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun /**
400*4882a593Smuzhiyun  * Convert the given property's value(s) into @nelem_return integer values and
401*4882a593Smuzhiyun  * store them in @buf_return. If @nelem_return is larger than the number of
402*4882a593Smuzhiyun  * values in the property, @nelem_return is set to the number of values in the
403*4882a593Smuzhiyun  * property.
404*4882a593Smuzhiyun  *
405*4882a593Smuzhiyun  * If *@buf_return is NULL and @nelem_return is 0, memory is allocated
406*4882a593Smuzhiyun  * automatically and must be freed by the caller.
407*4882a593Smuzhiyun  *
408*4882a593Smuzhiyun  * Possible return codes.
409*4882a593Smuzhiyun  * Success ... No error.
410*4882a593Smuzhiyun  * BadMatch ... Wrong atom type, atom is not XA_INTEGER
411*4882a593Smuzhiyun  * BadAlloc ... NULL passed as buffer and allocation failed.
412*4882a593Smuzhiyun  * BadLength ... @buff is NULL but @nelem_return is non-zero.
413*4882a593Smuzhiyun  *
414*4882a593Smuzhiyun  * @param val The property value
415*4882a593Smuzhiyun  * @param nelem_return The maximum number of elements to return.
416*4882a593Smuzhiyun  * @param buf_return Pointer to an array of at least @nelem_return values.
417*4882a593Smuzhiyun  * @return Success or the error code if an error occured.
418*4882a593Smuzhiyun  */
419*4882a593Smuzhiyun _X_EXPORT int
XIPropToInt(XIPropertyValuePtr val,int * nelem_return,int ** buf_return)420*4882a593Smuzhiyun XIPropToInt(XIPropertyValuePtr val, int *nelem_return, int **buf_return)
421*4882a593Smuzhiyun {
422*4882a593Smuzhiyun     int i;
423*4882a593Smuzhiyun     int *buf;
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun     if (val->type != XA_INTEGER)
426*4882a593Smuzhiyun         return BadMatch;
427*4882a593Smuzhiyun     if (!*buf_return && *nelem_return)
428*4882a593Smuzhiyun         return BadLength;
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun     switch (val->format) {
431*4882a593Smuzhiyun     case 8:
432*4882a593Smuzhiyun     case 16:
433*4882a593Smuzhiyun     case 32:
434*4882a593Smuzhiyun         break;
435*4882a593Smuzhiyun     default:
436*4882a593Smuzhiyun         return BadValue;
437*4882a593Smuzhiyun     }
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun     buf = *buf_return;
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun     if (!buf && !(*nelem_return)) {
442*4882a593Smuzhiyun         buf = calloc(val->size, sizeof(int));
443*4882a593Smuzhiyun         if (!buf)
444*4882a593Smuzhiyun             return BadAlloc;
445*4882a593Smuzhiyun         *buf_return = buf;
446*4882a593Smuzhiyun         *nelem_return = val->size;
447*4882a593Smuzhiyun     }
448*4882a593Smuzhiyun     else if (val->size < *nelem_return)
449*4882a593Smuzhiyun         *nelem_return = val->size;
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun     for (i = 0; i < val->size && i < *nelem_return; i++) {
452*4882a593Smuzhiyun         switch (val->format) {
453*4882a593Smuzhiyun         case 8:
454*4882a593Smuzhiyun             buf[i] = ((CARD8 *) val->data)[i];
455*4882a593Smuzhiyun             break;
456*4882a593Smuzhiyun         case 16:
457*4882a593Smuzhiyun             buf[i] = ((CARD16 *) val->data)[i];
458*4882a593Smuzhiyun             break;
459*4882a593Smuzhiyun         case 32:
460*4882a593Smuzhiyun             buf[i] = ((CARD32 *) val->data)[i];
461*4882a593Smuzhiyun             break;
462*4882a593Smuzhiyun         }
463*4882a593Smuzhiyun     }
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun     return Success;
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun /**
469*4882a593Smuzhiyun  * Convert the given property's value(s) into @nelem_return float values and
470*4882a593Smuzhiyun  * store them in @buf_return. If @nelem_return is larger than the number of
471*4882a593Smuzhiyun  * values in the property, @nelem_return is set to the number of values in the
472*4882a593Smuzhiyun  * property.
473*4882a593Smuzhiyun  *
474*4882a593Smuzhiyun  * If *@buf_return is NULL and @nelem_return is 0, memory is allocated
475*4882a593Smuzhiyun  * automatically and must be freed by the caller.
476*4882a593Smuzhiyun  *
477*4882a593Smuzhiyun  * Possible errors returned:
478*4882a593Smuzhiyun  * Success
479*4882a593Smuzhiyun  * BadMatch ... Wrong atom type, atom is not XA_FLOAT
480*4882a593Smuzhiyun  * BadValue ... Wrong format, format is not 32
481*4882a593Smuzhiyun  * BadAlloc ... NULL passed as buffer and allocation failed.
482*4882a593Smuzhiyun  * BadLength ... @buff is NULL but @nelem_return is non-zero.
483*4882a593Smuzhiyun  *
484*4882a593Smuzhiyun  * @param val The property value
485*4882a593Smuzhiyun  * @param nelem_return The maximum number of elements to return.
486*4882a593Smuzhiyun  * @param buf_return Pointer to an array of at least @nelem_return values.
487*4882a593Smuzhiyun  * @return Success or the error code if an error occured.
488*4882a593Smuzhiyun  */
489*4882a593Smuzhiyun _X_EXPORT int
XIPropToFloat(XIPropertyValuePtr val,int * nelem_return,float ** buf_return)490*4882a593Smuzhiyun XIPropToFloat(XIPropertyValuePtr val, int *nelem_return, float **buf_return)
491*4882a593Smuzhiyun {
492*4882a593Smuzhiyun     int i;
493*4882a593Smuzhiyun     float *buf;
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun     if (!val->type || val->type != XIGetKnownProperty(XATOM_FLOAT))
496*4882a593Smuzhiyun         return BadMatch;
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun     if (val->format != 32)
499*4882a593Smuzhiyun         return BadValue;
500*4882a593Smuzhiyun     if (!*buf_return && *nelem_return)
501*4882a593Smuzhiyun         return BadLength;
502*4882a593Smuzhiyun 
503*4882a593Smuzhiyun     buf = *buf_return;
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun     if (!buf && !(*nelem_return)) {
506*4882a593Smuzhiyun         buf = calloc(val->size, sizeof(float));
507*4882a593Smuzhiyun         if (!buf)
508*4882a593Smuzhiyun             return BadAlloc;
509*4882a593Smuzhiyun         *buf_return = buf;
510*4882a593Smuzhiyun         *nelem_return = val->size;
511*4882a593Smuzhiyun     }
512*4882a593Smuzhiyun     else if (val->size < *nelem_return)
513*4882a593Smuzhiyun         *nelem_return = val->size;
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun     for (i = 0; i < val->size && i < *nelem_return; i++)
516*4882a593Smuzhiyun         buf[i] = ((float *) val->data)[i];
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun     return Success;
519*4882a593Smuzhiyun }
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun /* Registers a new property handler on the given device and returns a unique
522*4882a593Smuzhiyun  * identifier for this handler. This identifier is required to unregister the
523*4882a593Smuzhiyun  * property handler again.
524*4882a593Smuzhiyun  * @return The handler's identifier or 0 if an error occured.
525*4882a593Smuzhiyun  */
526*4882a593Smuzhiyun long
XIRegisterPropertyHandler(DeviceIntPtr dev,int (* SetProperty)(DeviceIntPtr dev,Atom property,XIPropertyValuePtr prop,BOOL checkonly),int (* GetProperty)(DeviceIntPtr dev,Atom property),int (* DeleteProperty)(DeviceIntPtr dev,Atom property))527*4882a593Smuzhiyun XIRegisterPropertyHandler(DeviceIntPtr dev,
528*4882a593Smuzhiyun                           int (*SetProperty) (DeviceIntPtr dev,
529*4882a593Smuzhiyun                                               Atom property,
530*4882a593Smuzhiyun                                               XIPropertyValuePtr prop,
531*4882a593Smuzhiyun                                               BOOL checkonly),
532*4882a593Smuzhiyun                           int (*GetProperty) (DeviceIntPtr dev,
533*4882a593Smuzhiyun                                               Atom property),
534*4882a593Smuzhiyun                           int (*DeleteProperty) (DeviceIntPtr dev,
535*4882a593Smuzhiyun                                                  Atom property))
536*4882a593Smuzhiyun {
537*4882a593Smuzhiyun     XIPropertyHandlerPtr new_handler;
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun     new_handler = calloc(1, sizeof(XIPropertyHandler));
540*4882a593Smuzhiyun     if (!new_handler)
541*4882a593Smuzhiyun         return 0;
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun     new_handler->id = XIPropHandlerID++;
544*4882a593Smuzhiyun     new_handler->SetProperty = SetProperty;
545*4882a593Smuzhiyun     new_handler->GetProperty = GetProperty;
546*4882a593Smuzhiyun     new_handler->DeleteProperty = DeleteProperty;
547*4882a593Smuzhiyun     new_handler->next = dev->properties.handlers;
548*4882a593Smuzhiyun     dev->properties.handlers = new_handler;
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun     return new_handler->id;
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun void
XIUnregisterPropertyHandler(DeviceIntPtr dev,long id)554*4882a593Smuzhiyun XIUnregisterPropertyHandler(DeviceIntPtr dev, long id)
555*4882a593Smuzhiyun {
556*4882a593Smuzhiyun     XIPropertyHandlerPtr curr, prev = NULL;
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun     curr = dev->properties.handlers;
559*4882a593Smuzhiyun     while (curr && curr->id != id) {
560*4882a593Smuzhiyun         prev = curr;
561*4882a593Smuzhiyun         curr = curr->next;
562*4882a593Smuzhiyun     }
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun     if (!curr)
565*4882a593Smuzhiyun         return;
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun     if (!prev)                  /* first one */
568*4882a593Smuzhiyun         dev->properties.handlers = curr->next;
569*4882a593Smuzhiyun     else
570*4882a593Smuzhiyun         prev->next = curr->next;
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun     free(curr);
573*4882a593Smuzhiyun }
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun static XIPropertyPtr
XICreateDeviceProperty(Atom property)576*4882a593Smuzhiyun XICreateDeviceProperty(Atom property)
577*4882a593Smuzhiyun {
578*4882a593Smuzhiyun     XIPropertyPtr prop;
579*4882a593Smuzhiyun 
580*4882a593Smuzhiyun     prop = (XIPropertyPtr) malloc(sizeof(XIPropertyRec));
581*4882a593Smuzhiyun     if (!prop)
582*4882a593Smuzhiyun         return NULL;
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun     prop->next = NULL;
585*4882a593Smuzhiyun     prop->propertyName = property;
586*4882a593Smuzhiyun     prop->value.type = None;
587*4882a593Smuzhiyun     prop->value.format = 0;
588*4882a593Smuzhiyun     prop->value.size = 0;
589*4882a593Smuzhiyun     prop->value.data = NULL;
590*4882a593Smuzhiyun     prop->deletable = TRUE;
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun     return prop;
593*4882a593Smuzhiyun }
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun static XIPropertyPtr
XIFetchDeviceProperty(DeviceIntPtr dev,Atom property)596*4882a593Smuzhiyun XIFetchDeviceProperty(DeviceIntPtr dev, Atom property)
597*4882a593Smuzhiyun {
598*4882a593Smuzhiyun     XIPropertyPtr prop;
599*4882a593Smuzhiyun 
600*4882a593Smuzhiyun     for (prop = dev->properties.properties; prop; prop = prop->next)
601*4882a593Smuzhiyun         if (prop->propertyName == property)
602*4882a593Smuzhiyun             return prop;
603*4882a593Smuzhiyun     return NULL;
604*4882a593Smuzhiyun }
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun static void
XIDestroyDeviceProperty(XIPropertyPtr prop)607*4882a593Smuzhiyun XIDestroyDeviceProperty(XIPropertyPtr prop)
608*4882a593Smuzhiyun {
609*4882a593Smuzhiyun     free(prop->value.data);
610*4882a593Smuzhiyun     free(prop);
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun /* This function destroys all of the device's property-related stuff,
614*4882a593Smuzhiyun  * including removing all device handlers.
615*4882a593Smuzhiyun  * DO NOT CALL FROM THE DRIVER.
616*4882a593Smuzhiyun  */
617*4882a593Smuzhiyun void
XIDeleteAllDeviceProperties(DeviceIntPtr device)618*4882a593Smuzhiyun XIDeleteAllDeviceProperties(DeviceIntPtr device)
619*4882a593Smuzhiyun {
620*4882a593Smuzhiyun     XIPropertyPtr prop, next;
621*4882a593Smuzhiyun     XIPropertyHandlerPtr curr_handler, next_handler;
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun     UpdateCurrentTimeIf();
624*4882a593Smuzhiyun     for (prop = device->properties.properties; prop; prop = next) {
625*4882a593Smuzhiyun         next = prop->next;
626*4882a593Smuzhiyun         send_property_event(device, prop->propertyName, XIPropertyDeleted);
627*4882a593Smuzhiyun         XIDestroyDeviceProperty(prop);
628*4882a593Smuzhiyun     }
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun     device->properties.properties = NULL;
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun     /* Now free all handlers */
633*4882a593Smuzhiyun     curr_handler = device->properties.handlers;
634*4882a593Smuzhiyun     while (curr_handler) {
635*4882a593Smuzhiyun         next_handler = curr_handler->next;
636*4882a593Smuzhiyun         free(curr_handler);
637*4882a593Smuzhiyun         curr_handler = next_handler;
638*4882a593Smuzhiyun     }
639*4882a593Smuzhiyun 
640*4882a593Smuzhiyun     device->properties.handlers = NULL;
641*4882a593Smuzhiyun }
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun int
XIDeleteDeviceProperty(DeviceIntPtr device,Atom property,Bool fromClient)644*4882a593Smuzhiyun XIDeleteDeviceProperty(DeviceIntPtr device, Atom property, Bool fromClient)
645*4882a593Smuzhiyun {
646*4882a593Smuzhiyun     XIPropertyPtr prop, *prev;
647*4882a593Smuzhiyun     int rc = Success;
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun     for (prev = &device->properties.properties; (prop = *prev);
650*4882a593Smuzhiyun          prev = &(prop->next))
651*4882a593Smuzhiyun         if (prop->propertyName == property)
652*4882a593Smuzhiyun             break;
653*4882a593Smuzhiyun 
654*4882a593Smuzhiyun     if (!prop)
655*4882a593Smuzhiyun         return Success;
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun     if (fromClient && !prop->deletable)
658*4882a593Smuzhiyun         return BadAccess;
659*4882a593Smuzhiyun 
660*4882a593Smuzhiyun     /* Ask handlers if we may delete the property */
661*4882a593Smuzhiyun     if (device->properties.handlers) {
662*4882a593Smuzhiyun         XIPropertyHandlerPtr handler = device->properties.handlers;
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun         while (handler) {
665*4882a593Smuzhiyun             if (handler->DeleteProperty)
666*4882a593Smuzhiyun                 rc = handler->DeleteProperty(device, prop->propertyName);
667*4882a593Smuzhiyun             if (rc != Success)
668*4882a593Smuzhiyun                 return rc;
669*4882a593Smuzhiyun             handler = handler->next;
670*4882a593Smuzhiyun         }
671*4882a593Smuzhiyun     }
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun     if (prop) {
674*4882a593Smuzhiyun         UpdateCurrentTimeIf();
675*4882a593Smuzhiyun         *prev = prop->next;
676*4882a593Smuzhiyun         send_property_event(device, prop->propertyName, XIPropertyDeleted);
677*4882a593Smuzhiyun         XIDestroyDeviceProperty(prop);
678*4882a593Smuzhiyun     }
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun     return Success;
681*4882a593Smuzhiyun }
682*4882a593Smuzhiyun 
683*4882a593Smuzhiyun int
XIChangeDeviceProperty(DeviceIntPtr dev,Atom property,Atom type,int format,int mode,unsigned long len,const void * value,Bool sendevent)684*4882a593Smuzhiyun XIChangeDeviceProperty(DeviceIntPtr dev, Atom property, Atom type,
685*4882a593Smuzhiyun                        int format, int mode, unsigned long len,
686*4882a593Smuzhiyun                        const void *value, Bool sendevent)
687*4882a593Smuzhiyun {
688*4882a593Smuzhiyun     XIPropertyPtr prop;
689*4882a593Smuzhiyun     int size_in_bytes;
690*4882a593Smuzhiyun     unsigned long total_len;
691*4882a593Smuzhiyun     XIPropertyValuePtr prop_value;
692*4882a593Smuzhiyun     XIPropertyValueRec new_value;
693*4882a593Smuzhiyun     Bool add = FALSE;
694*4882a593Smuzhiyun     int rc;
695*4882a593Smuzhiyun 
696*4882a593Smuzhiyun     size_in_bytes = format >> 3;
697*4882a593Smuzhiyun 
698*4882a593Smuzhiyun     /* first see if property already exists */
699*4882a593Smuzhiyun     prop = XIFetchDeviceProperty(dev, property);
700*4882a593Smuzhiyun     if (!prop) {                /* just add to list */
701*4882a593Smuzhiyun         prop = XICreateDeviceProperty(property);
702*4882a593Smuzhiyun         if (!prop)
703*4882a593Smuzhiyun             return BadAlloc;
704*4882a593Smuzhiyun         add = TRUE;
705*4882a593Smuzhiyun         mode = PropModeReplace;
706*4882a593Smuzhiyun     }
707*4882a593Smuzhiyun     prop_value = &prop->value;
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun     /* To append or prepend to a property the request format and type
710*4882a593Smuzhiyun        must match those of the already defined property.  The
711*4882a593Smuzhiyun        existing format and type are irrelevant when using the mode
712*4882a593Smuzhiyun        "PropModeReplace" since they will be written over. */
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun     if ((format != prop_value->format) && (mode != PropModeReplace))
715*4882a593Smuzhiyun         return BadMatch;
716*4882a593Smuzhiyun     if ((prop_value->type != type) && (mode != PropModeReplace))
717*4882a593Smuzhiyun         return BadMatch;
718*4882a593Smuzhiyun     new_value = *prop_value;
719*4882a593Smuzhiyun     if (mode == PropModeReplace)
720*4882a593Smuzhiyun         total_len = len;
721*4882a593Smuzhiyun     else
722*4882a593Smuzhiyun         total_len = prop_value->size + len;
723*4882a593Smuzhiyun 
724*4882a593Smuzhiyun     if (mode == PropModeReplace || len > 0) {
725*4882a593Smuzhiyun         void *new_data = NULL, *old_data = NULL;
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun         new_value.data = xallocarray(total_len, size_in_bytes);
728*4882a593Smuzhiyun         if (!new_value.data && total_len && size_in_bytes) {
729*4882a593Smuzhiyun             if (add)
730*4882a593Smuzhiyun                 XIDestroyDeviceProperty(prop);
731*4882a593Smuzhiyun             return BadAlloc;
732*4882a593Smuzhiyun         }
733*4882a593Smuzhiyun         new_value.size = len;
734*4882a593Smuzhiyun         new_value.type = type;
735*4882a593Smuzhiyun         new_value.format = format;
736*4882a593Smuzhiyun 
737*4882a593Smuzhiyun         switch (mode) {
738*4882a593Smuzhiyun         case PropModeReplace:
739*4882a593Smuzhiyun             new_data = new_value.data;
740*4882a593Smuzhiyun             old_data = NULL;
741*4882a593Smuzhiyun             break;
742*4882a593Smuzhiyun         case PropModeAppend:
743*4882a593Smuzhiyun             new_data = (void *) (((char *) new_value.data) +
744*4882a593Smuzhiyun                                   (prop_value->size * size_in_bytes));
745*4882a593Smuzhiyun             old_data = new_value.data;
746*4882a593Smuzhiyun             break;
747*4882a593Smuzhiyun         case PropModePrepend:
748*4882a593Smuzhiyun             new_data = new_value.data;
749*4882a593Smuzhiyun             old_data = (void *) (((char *) new_value.data) +
750*4882a593Smuzhiyun                                   (prop_value->size * size_in_bytes));
751*4882a593Smuzhiyun             break;
752*4882a593Smuzhiyun         }
753*4882a593Smuzhiyun         if (new_data)
754*4882a593Smuzhiyun             memcpy((char *) new_data, value, len * size_in_bytes);
755*4882a593Smuzhiyun         if (old_data)
756*4882a593Smuzhiyun             memcpy((char *) old_data, (char *) prop_value->data,
757*4882a593Smuzhiyun                    prop_value->size * size_in_bytes);
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun         if (dev->properties.handlers) {
760*4882a593Smuzhiyun             XIPropertyHandlerPtr handler;
761*4882a593Smuzhiyun             BOOL checkonly = TRUE;
762*4882a593Smuzhiyun 
763*4882a593Smuzhiyun             /* run through all handlers with checkonly TRUE, then again with
764*4882a593Smuzhiyun              * checkonly FALSE. Handlers MUST return error codes on the
765*4882a593Smuzhiyun              * checkonly run, errors on the second run are ignored */
766*4882a593Smuzhiyun             do {
767*4882a593Smuzhiyun                 handler = dev->properties.handlers;
768*4882a593Smuzhiyun                 while (handler) {
769*4882a593Smuzhiyun                     if (handler->SetProperty) {
770*4882a593Smuzhiyun                         input_lock();
771*4882a593Smuzhiyun                         rc = handler->SetProperty(dev, prop->propertyName,
772*4882a593Smuzhiyun                                                   &new_value, checkonly);
773*4882a593Smuzhiyun                         input_unlock();
774*4882a593Smuzhiyun                         if (checkonly && rc != Success) {
775*4882a593Smuzhiyun                             free(new_value.data);
776*4882a593Smuzhiyun                             if (add)
777*4882a593Smuzhiyun                                 XIDestroyDeviceProperty(prop);
778*4882a593Smuzhiyun                             return rc;
779*4882a593Smuzhiyun                         }
780*4882a593Smuzhiyun                     }
781*4882a593Smuzhiyun                     handler = handler->next;
782*4882a593Smuzhiyun                 }
783*4882a593Smuzhiyun                 checkonly = !checkonly;
784*4882a593Smuzhiyun             } while (!checkonly);
785*4882a593Smuzhiyun         }
786*4882a593Smuzhiyun         free(prop_value->data);
787*4882a593Smuzhiyun         *prop_value = new_value;
788*4882a593Smuzhiyun     }
789*4882a593Smuzhiyun     else if (len == 0) {
790*4882a593Smuzhiyun         /* do nothing */
791*4882a593Smuzhiyun     }
792*4882a593Smuzhiyun 
793*4882a593Smuzhiyun     if (add) {
794*4882a593Smuzhiyun         prop->next = dev->properties.properties;
795*4882a593Smuzhiyun         dev->properties.properties = prop;
796*4882a593Smuzhiyun     }
797*4882a593Smuzhiyun 
798*4882a593Smuzhiyun     if (sendevent) {
799*4882a593Smuzhiyun         UpdateCurrentTimeIf();
800*4882a593Smuzhiyun         send_property_event(dev, prop->propertyName,
801*4882a593Smuzhiyun                             (add) ? XIPropertyCreated : XIPropertyModified);
802*4882a593Smuzhiyun     }
803*4882a593Smuzhiyun 
804*4882a593Smuzhiyun     return Success;
805*4882a593Smuzhiyun }
806*4882a593Smuzhiyun 
807*4882a593Smuzhiyun int
XIGetDeviceProperty(DeviceIntPtr dev,Atom property,XIPropertyValuePtr * value)808*4882a593Smuzhiyun XIGetDeviceProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr *value)
809*4882a593Smuzhiyun {
810*4882a593Smuzhiyun     XIPropertyPtr prop = XIFetchDeviceProperty(dev, property);
811*4882a593Smuzhiyun     int rc;
812*4882a593Smuzhiyun 
813*4882a593Smuzhiyun     if (!prop) {
814*4882a593Smuzhiyun         *value = NULL;
815*4882a593Smuzhiyun         return BadAtom;
816*4882a593Smuzhiyun     }
817*4882a593Smuzhiyun 
818*4882a593Smuzhiyun     /* If we can, try to update the property value first */
819*4882a593Smuzhiyun     if (dev->properties.handlers) {
820*4882a593Smuzhiyun         XIPropertyHandlerPtr handler = dev->properties.handlers;
821*4882a593Smuzhiyun 
822*4882a593Smuzhiyun         while (handler) {
823*4882a593Smuzhiyun             if (handler->GetProperty) {
824*4882a593Smuzhiyun                 rc = handler->GetProperty(dev, prop->propertyName);
825*4882a593Smuzhiyun                 if (rc != Success) {
826*4882a593Smuzhiyun                     *value = NULL;
827*4882a593Smuzhiyun                     return rc;
828*4882a593Smuzhiyun                 }
829*4882a593Smuzhiyun             }
830*4882a593Smuzhiyun             handler = handler->next;
831*4882a593Smuzhiyun         }
832*4882a593Smuzhiyun     }
833*4882a593Smuzhiyun 
834*4882a593Smuzhiyun     *value = &prop->value;
835*4882a593Smuzhiyun     return Success;
836*4882a593Smuzhiyun }
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun int
XISetDevicePropertyDeletable(DeviceIntPtr dev,Atom property,Bool deletable)839*4882a593Smuzhiyun XISetDevicePropertyDeletable(DeviceIntPtr dev, Atom property, Bool deletable)
840*4882a593Smuzhiyun {
841*4882a593Smuzhiyun     XIPropertyPtr prop = XIFetchDeviceProperty(dev, property);
842*4882a593Smuzhiyun 
843*4882a593Smuzhiyun     if (!prop)
844*4882a593Smuzhiyun         return BadAtom;
845*4882a593Smuzhiyun 
846*4882a593Smuzhiyun     prop->deletable = deletable;
847*4882a593Smuzhiyun     return Success;
848*4882a593Smuzhiyun }
849*4882a593Smuzhiyun 
850*4882a593Smuzhiyun int
ProcXListDeviceProperties(ClientPtr client)851*4882a593Smuzhiyun ProcXListDeviceProperties(ClientPtr client)
852*4882a593Smuzhiyun {
853*4882a593Smuzhiyun     Atom *atoms;
854*4882a593Smuzhiyun     xListDevicePropertiesReply rep;
855*4882a593Smuzhiyun     int natoms;
856*4882a593Smuzhiyun     DeviceIntPtr dev;
857*4882a593Smuzhiyun     int rc = Success;
858*4882a593Smuzhiyun 
859*4882a593Smuzhiyun     REQUEST(xListDevicePropertiesReq);
860*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
861*4882a593Smuzhiyun 
862*4882a593Smuzhiyun     rc = dixLookupDevice(&dev, stuff->deviceid, client, DixListPropAccess);
863*4882a593Smuzhiyun     if (rc != Success)
864*4882a593Smuzhiyun         return rc;
865*4882a593Smuzhiyun 
866*4882a593Smuzhiyun     rc = list_atoms(dev, &natoms, &atoms);
867*4882a593Smuzhiyun     if (rc != Success)
868*4882a593Smuzhiyun         return rc;
869*4882a593Smuzhiyun 
870*4882a593Smuzhiyun     rep = (xListDevicePropertiesReply) {
871*4882a593Smuzhiyun         .repType = X_Reply,
872*4882a593Smuzhiyun         .RepType = X_ListDeviceProperties,
873*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
874*4882a593Smuzhiyun         .length = natoms,
875*4882a593Smuzhiyun         .nAtoms = natoms
876*4882a593Smuzhiyun     };
877*4882a593Smuzhiyun 
878*4882a593Smuzhiyun     WriteReplyToClient(client, sizeof(xListDevicePropertiesReply), &rep);
879*4882a593Smuzhiyun     if (natoms) {
880*4882a593Smuzhiyun         client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
881*4882a593Smuzhiyun         WriteSwappedDataToClient(client, natoms * sizeof(Atom), atoms);
882*4882a593Smuzhiyun         free(atoms);
883*4882a593Smuzhiyun     }
884*4882a593Smuzhiyun     return rc;
885*4882a593Smuzhiyun }
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun int
ProcXChangeDeviceProperty(ClientPtr client)888*4882a593Smuzhiyun ProcXChangeDeviceProperty(ClientPtr client)
889*4882a593Smuzhiyun {
890*4882a593Smuzhiyun     REQUEST(xChangeDevicePropertyReq);
891*4882a593Smuzhiyun     DeviceIntPtr dev;
892*4882a593Smuzhiyun     unsigned long len;
893*4882a593Smuzhiyun     int totalSize;
894*4882a593Smuzhiyun     int rc;
895*4882a593Smuzhiyun 
896*4882a593Smuzhiyun     REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq);
897*4882a593Smuzhiyun     UpdateCurrentTime();
898*4882a593Smuzhiyun 
899*4882a593Smuzhiyun     rc = dixLookupDevice(&dev, stuff->deviceid, client, DixSetPropAccess);
900*4882a593Smuzhiyun     if (rc != Success)
901*4882a593Smuzhiyun         return rc;
902*4882a593Smuzhiyun 
903*4882a593Smuzhiyun     rc = check_change_property(client, stuff->property, stuff->type,
904*4882a593Smuzhiyun                                stuff->format, stuff->mode, stuff->nUnits);
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun     len = stuff->nUnits;
907*4882a593Smuzhiyun     if (len > (bytes_to_int32(0xffffffff - sizeof(xChangeDevicePropertyReq))))
908*4882a593Smuzhiyun         return BadLength;
909*4882a593Smuzhiyun 
910*4882a593Smuzhiyun     totalSize = len * (stuff->format / 8);
911*4882a593Smuzhiyun     REQUEST_FIXED_SIZE(xChangeDevicePropertyReq, totalSize);
912*4882a593Smuzhiyun 
913*4882a593Smuzhiyun     rc = change_property(client, dev, stuff->property, stuff->type,
914*4882a593Smuzhiyun                          stuff->format, stuff->mode, len, (void *) &stuff[1]);
915*4882a593Smuzhiyun     return rc;
916*4882a593Smuzhiyun }
917*4882a593Smuzhiyun 
918*4882a593Smuzhiyun int
ProcXDeleteDeviceProperty(ClientPtr client)919*4882a593Smuzhiyun ProcXDeleteDeviceProperty(ClientPtr client)
920*4882a593Smuzhiyun {
921*4882a593Smuzhiyun     REQUEST(xDeleteDevicePropertyReq);
922*4882a593Smuzhiyun     DeviceIntPtr dev;
923*4882a593Smuzhiyun     int rc;
924*4882a593Smuzhiyun 
925*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
926*4882a593Smuzhiyun     UpdateCurrentTime();
927*4882a593Smuzhiyun     rc = dixLookupDevice(&dev, stuff->deviceid, client, DixSetPropAccess);
928*4882a593Smuzhiyun     if (rc != Success)
929*4882a593Smuzhiyun         return rc;
930*4882a593Smuzhiyun 
931*4882a593Smuzhiyun     if (!ValidAtom(stuff->property)) {
932*4882a593Smuzhiyun         client->errorValue = stuff->property;
933*4882a593Smuzhiyun         return BadAtom;
934*4882a593Smuzhiyun     }
935*4882a593Smuzhiyun 
936*4882a593Smuzhiyun     rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE);
937*4882a593Smuzhiyun     return rc;
938*4882a593Smuzhiyun }
939*4882a593Smuzhiyun 
940*4882a593Smuzhiyun int
ProcXGetDeviceProperty(ClientPtr client)941*4882a593Smuzhiyun ProcXGetDeviceProperty(ClientPtr client)
942*4882a593Smuzhiyun {
943*4882a593Smuzhiyun     REQUEST(xGetDevicePropertyReq);
944*4882a593Smuzhiyun     DeviceIntPtr dev;
945*4882a593Smuzhiyun     int length;
946*4882a593Smuzhiyun     int rc, format, nitems, bytes_after;
947*4882a593Smuzhiyun     char *data;
948*4882a593Smuzhiyun     Atom type;
949*4882a593Smuzhiyun     xGetDevicePropertyReply reply;
950*4882a593Smuzhiyun 
951*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
952*4882a593Smuzhiyun     if (stuff->delete)
953*4882a593Smuzhiyun         UpdateCurrentTime();
954*4882a593Smuzhiyun     rc = dixLookupDevice(&dev, stuff->deviceid, client,
955*4882a593Smuzhiyun                          stuff->delete ? DixSetPropAccess : DixGetPropAccess);
956*4882a593Smuzhiyun     if (rc != Success)
957*4882a593Smuzhiyun         return rc;
958*4882a593Smuzhiyun 
959*4882a593Smuzhiyun     rc = get_property(client, dev, stuff->property, stuff->type,
960*4882a593Smuzhiyun                       stuff->delete, stuff->longOffset, stuff->longLength,
961*4882a593Smuzhiyun                       &bytes_after, &type, &format, &nitems, &length, &data);
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun     if (rc != Success)
964*4882a593Smuzhiyun         return rc;
965*4882a593Smuzhiyun 
966*4882a593Smuzhiyun     reply = (xGetDevicePropertyReply) {
967*4882a593Smuzhiyun         .repType = X_Reply,
968*4882a593Smuzhiyun         .RepType = X_GetDeviceProperty,
969*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
970*4882a593Smuzhiyun         .length = bytes_to_int32(length),
971*4882a593Smuzhiyun         .propertyType = type,
972*4882a593Smuzhiyun         .bytesAfter = bytes_after,
973*4882a593Smuzhiyun         .nItems = nitems,
974*4882a593Smuzhiyun         .format = format,
975*4882a593Smuzhiyun         .deviceid = dev->id
976*4882a593Smuzhiyun     };
977*4882a593Smuzhiyun 
978*4882a593Smuzhiyun     if (stuff->delete && (reply.bytesAfter == 0))
979*4882a593Smuzhiyun         send_property_event(dev, stuff->property, XIPropertyDeleted);
980*4882a593Smuzhiyun 
981*4882a593Smuzhiyun     WriteReplyToClient(client, sizeof(xGenericReply), &reply);
982*4882a593Smuzhiyun 
983*4882a593Smuzhiyun     if (length) {
984*4882a593Smuzhiyun         switch (reply.format) {
985*4882a593Smuzhiyun         case 32:
986*4882a593Smuzhiyun             client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
987*4882a593Smuzhiyun             break;
988*4882a593Smuzhiyun         case 16:
989*4882a593Smuzhiyun             client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write;
990*4882a593Smuzhiyun             break;
991*4882a593Smuzhiyun         default:
992*4882a593Smuzhiyun             client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient;
993*4882a593Smuzhiyun             break;
994*4882a593Smuzhiyun         }
995*4882a593Smuzhiyun         WriteSwappedDataToClient(client, length, data);
996*4882a593Smuzhiyun     }
997*4882a593Smuzhiyun 
998*4882a593Smuzhiyun     /* delete the Property */
999*4882a593Smuzhiyun     if (stuff->delete && (reply.bytesAfter == 0)) {
1000*4882a593Smuzhiyun         XIPropertyPtr prop, *prev;
1001*4882a593Smuzhiyun 
1002*4882a593Smuzhiyun         for (prev = &dev->properties.properties; (prop = *prev);
1003*4882a593Smuzhiyun              prev = &prop->next) {
1004*4882a593Smuzhiyun             if (prop->propertyName == stuff->property) {
1005*4882a593Smuzhiyun                 *prev = prop->next;
1006*4882a593Smuzhiyun                 XIDestroyDeviceProperty(prop);
1007*4882a593Smuzhiyun                 break;
1008*4882a593Smuzhiyun             }
1009*4882a593Smuzhiyun         }
1010*4882a593Smuzhiyun     }
1011*4882a593Smuzhiyun     return Success;
1012*4882a593Smuzhiyun }
1013*4882a593Smuzhiyun 
1014*4882a593Smuzhiyun int _X_COLD
SProcXListDeviceProperties(ClientPtr client)1015*4882a593Smuzhiyun SProcXListDeviceProperties(ClientPtr client)
1016*4882a593Smuzhiyun {
1017*4882a593Smuzhiyun     REQUEST(xListDevicePropertiesReq);
1018*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
1019*4882a593Smuzhiyun 
1020*4882a593Smuzhiyun     swaps(&stuff->length);
1021*4882a593Smuzhiyun     return (ProcXListDeviceProperties(client));
1022*4882a593Smuzhiyun }
1023*4882a593Smuzhiyun 
1024*4882a593Smuzhiyun int _X_COLD
SProcXChangeDeviceProperty(ClientPtr client)1025*4882a593Smuzhiyun SProcXChangeDeviceProperty(ClientPtr client)
1026*4882a593Smuzhiyun {
1027*4882a593Smuzhiyun     REQUEST(xChangeDevicePropertyReq);
1028*4882a593Smuzhiyun 
1029*4882a593Smuzhiyun     REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq);
1030*4882a593Smuzhiyun     swaps(&stuff->length);
1031*4882a593Smuzhiyun     swapl(&stuff->property);
1032*4882a593Smuzhiyun     swapl(&stuff->type);
1033*4882a593Smuzhiyun     swapl(&stuff->nUnits);
1034*4882a593Smuzhiyun     return (ProcXChangeDeviceProperty(client));
1035*4882a593Smuzhiyun }
1036*4882a593Smuzhiyun 
1037*4882a593Smuzhiyun int _X_COLD
SProcXDeleteDeviceProperty(ClientPtr client)1038*4882a593Smuzhiyun SProcXDeleteDeviceProperty(ClientPtr client)
1039*4882a593Smuzhiyun {
1040*4882a593Smuzhiyun     REQUEST(xDeleteDevicePropertyReq);
1041*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
1042*4882a593Smuzhiyun 
1043*4882a593Smuzhiyun     swaps(&stuff->length);
1044*4882a593Smuzhiyun     swapl(&stuff->property);
1045*4882a593Smuzhiyun     return (ProcXDeleteDeviceProperty(client));
1046*4882a593Smuzhiyun }
1047*4882a593Smuzhiyun 
1048*4882a593Smuzhiyun int _X_COLD
SProcXGetDeviceProperty(ClientPtr client)1049*4882a593Smuzhiyun SProcXGetDeviceProperty(ClientPtr client)
1050*4882a593Smuzhiyun {
1051*4882a593Smuzhiyun     REQUEST(xGetDevicePropertyReq);
1052*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
1053*4882a593Smuzhiyun 
1054*4882a593Smuzhiyun     swaps(&stuff->length);
1055*4882a593Smuzhiyun     swapl(&stuff->property);
1056*4882a593Smuzhiyun     swapl(&stuff->type);
1057*4882a593Smuzhiyun     swapl(&stuff->longOffset);
1058*4882a593Smuzhiyun     swapl(&stuff->longLength);
1059*4882a593Smuzhiyun     return (ProcXGetDeviceProperty(client));
1060*4882a593Smuzhiyun }
1061*4882a593Smuzhiyun 
1062*4882a593Smuzhiyun /* Reply swapping */
1063*4882a593Smuzhiyun 
1064*4882a593Smuzhiyun void _X_COLD
SRepXListDeviceProperties(ClientPtr client,int size,xListDevicePropertiesReply * rep)1065*4882a593Smuzhiyun SRepXListDeviceProperties(ClientPtr client, int size,
1066*4882a593Smuzhiyun                           xListDevicePropertiesReply * rep)
1067*4882a593Smuzhiyun {
1068*4882a593Smuzhiyun     swaps(&rep->sequenceNumber);
1069*4882a593Smuzhiyun     swapl(&rep->length);
1070*4882a593Smuzhiyun     swaps(&rep->nAtoms);
1071*4882a593Smuzhiyun     /* properties will be swapped later, see ProcXListDeviceProperties */
1072*4882a593Smuzhiyun     WriteToClient(client, size, rep);
1073*4882a593Smuzhiyun }
1074*4882a593Smuzhiyun 
1075*4882a593Smuzhiyun void _X_COLD
SRepXGetDeviceProperty(ClientPtr client,int size,xGetDevicePropertyReply * rep)1076*4882a593Smuzhiyun SRepXGetDeviceProperty(ClientPtr client, int size,
1077*4882a593Smuzhiyun                        xGetDevicePropertyReply * rep)
1078*4882a593Smuzhiyun {
1079*4882a593Smuzhiyun     swaps(&rep->sequenceNumber);
1080*4882a593Smuzhiyun     swapl(&rep->length);
1081*4882a593Smuzhiyun     swapl(&rep->propertyType);
1082*4882a593Smuzhiyun     swapl(&rep->bytesAfter);
1083*4882a593Smuzhiyun     swapl(&rep->nItems);
1084*4882a593Smuzhiyun     /* data will be swapped, see ProcXGetDeviceProperty */
1085*4882a593Smuzhiyun     WriteToClient(client, size, rep);
1086*4882a593Smuzhiyun }
1087*4882a593Smuzhiyun 
1088*4882a593Smuzhiyun /* XI2 Request/reply handling */
1089*4882a593Smuzhiyun int
ProcXIListProperties(ClientPtr client)1090*4882a593Smuzhiyun ProcXIListProperties(ClientPtr client)
1091*4882a593Smuzhiyun {
1092*4882a593Smuzhiyun     Atom *atoms;
1093*4882a593Smuzhiyun     xXIListPropertiesReply rep;
1094*4882a593Smuzhiyun     int natoms;
1095*4882a593Smuzhiyun     DeviceIntPtr dev;
1096*4882a593Smuzhiyun     int rc = Success;
1097*4882a593Smuzhiyun 
1098*4882a593Smuzhiyun     REQUEST(xXIListPropertiesReq);
1099*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xXIListPropertiesReq);
1100*4882a593Smuzhiyun 
1101*4882a593Smuzhiyun     rc = dixLookupDevice(&dev, stuff->deviceid, client, DixListPropAccess);
1102*4882a593Smuzhiyun     if (rc != Success)
1103*4882a593Smuzhiyun         return rc;
1104*4882a593Smuzhiyun 
1105*4882a593Smuzhiyun     rc = list_atoms(dev, &natoms, &atoms);
1106*4882a593Smuzhiyun     if (rc != Success)
1107*4882a593Smuzhiyun         return rc;
1108*4882a593Smuzhiyun 
1109*4882a593Smuzhiyun     rep = (xXIListPropertiesReply) {
1110*4882a593Smuzhiyun         .repType = X_Reply,
1111*4882a593Smuzhiyun         .RepType = X_XIListProperties,
1112*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
1113*4882a593Smuzhiyun         .length = natoms,
1114*4882a593Smuzhiyun         .num_properties = natoms
1115*4882a593Smuzhiyun     };
1116*4882a593Smuzhiyun 
1117*4882a593Smuzhiyun     WriteReplyToClient(client, sizeof(xXIListPropertiesReply), &rep);
1118*4882a593Smuzhiyun     if (natoms) {
1119*4882a593Smuzhiyun         client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
1120*4882a593Smuzhiyun         WriteSwappedDataToClient(client, natoms * sizeof(Atom), atoms);
1121*4882a593Smuzhiyun         free(atoms);
1122*4882a593Smuzhiyun     }
1123*4882a593Smuzhiyun     return rc;
1124*4882a593Smuzhiyun }
1125*4882a593Smuzhiyun 
1126*4882a593Smuzhiyun int
ProcXIChangeProperty(ClientPtr client)1127*4882a593Smuzhiyun ProcXIChangeProperty(ClientPtr client)
1128*4882a593Smuzhiyun {
1129*4882a593Smuzhiyun     int rc;
1130*4882a593Smuzhiyun     DeviceIntPtr dev;
1131*4882a593Smuzhiyun     int totalSize;
1132*4882a593Smuzhiyun     unsigned long len;
1133*4882a593Smuzhiyun 
1134*4882a593Smuzhiyun     REQUEST(xXIChangePropertyReq);
1135*4882a593Smuzhiyun     REQUEST_AT_LEAST_SIZE(xXIChangePropertyReq);
1136*4882a593Smuzhiyun     UpdateCurrentTime();
1137*4882a593Smuzhiyun 
1138*4882a593Smuzhiyun     rc = dixLookupDevice(&dev, stuff->deviceid, client, DixSetPropAccess);
1139*4882a593Smuzhiyun     if (rc != Success)
1140*4882a593Smuzhiyun         return rc;
1141*4882a593Smuzhiyun 
1142*4882a593Smuzhiyun     rc = check_change_property(client, stuff->property, stuff->type,
1143*4882a593Smuzhiyun                                stuff->format, stuff->mode, stuff->num_items);
1144*4882a593Smuzhiyun     len = stuff->num_items;
1145*4882a593Smuzhiyun     if (len > bytes_to_int32(0xffffffff - sizeof(xXIChangePropertyReq)))
1146*4882a593Smuzhiyun         return BadLength;
1147*4882a593Smuzhiyun 
1148*4882a593Smuzhiyun     totalSize = len * (stuff->format / 8);
1149*4882a593Smuzhiyun     REQUEST_FIXED_SIZE(xXIChangePropertyReq, totalSize);
1150*4882a593Smuzhiyun 
1151*4882a593Smuzhiyun     rc = change_property(client, dev, stuff->property, stuff->type,
1152*4882a593Smuzhiyun                          stuff->format, stuff->mode, len, (void *) &stuff[1]);
1153*4882a593Smuzhiyun     return rc;
1154*4882a593Smuzhiyun }
1155*4882a593Smuzhiyun 
1156*4882a593Smuzhiyun int
ProcXIDeleteProperty(ClientPtr client)1157*4882a593Smuzhiyun ProcXIDeleteProperty(ClientPtr client)
1158*4882a593Smuzhiyun {
1159*4882a593Smuzhiyun     DeviceIntPtr dev;
1160*4882a593Smuzhiyun     int rc;
1161*4882a593Smuzhiyun 
1162*4882a593Smuzhiyun     REQUEST(xXIDeletePropertyReq);
1163*4882a593Smuzhiyun 
1164*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xXIDeletePropertyReq);
1165*4882a593Smuzhiyun     UpdateCurrentTime();
1166*4882a593Smuzhiyun     rc = dixLookupDevice(&dev, stuff->deviceid, client, DixSetPropAccess);
1167*4882a593Smuzhiyun     if (rc != Success)
1168*4882a593Smuzhiyun         return rc;
1169*4882a593Smuzhiyun 
1170*4882a593Smuzhiyun     if (!ValidAtom(stuff->property)) {
1171*4882a593Smuzhiyun         client->errorValue = stuff->property;
1172*4882a593Smuzhiyun         return BadAtom;
1173*4882a593Smuzhiyun     }
1174*4882a593Smuzhiyun 
1175*4882a593Smuzhiyun     rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE);
1176*4882a593Smuzhiyun     return rc;
1177*4882a593Smuzhiyun }
1178*4882a593Smuzhiyun 
1179*4882a593Smuzhiyun int
ProcXIGetProperty(ClientPtr client)1180*4882a593Smuzhiyun ProcXIGetProperty(ClientPtr client)
1181*4882a593Smuzhiyun {
1182*4882a593Smuzhiyun     REQUEST(xXIGetPropertyReq);
1183*4882a593Smuzhiyun     DeviceIntPtr dev;
1184*4882a593Smuzhiyun     xXIGetPropertyReply reply;
1185*4882a593Smuzhiyun     int length;
1186*4882a593Smuzhiyun     int rc, format, nitems, bytes_after;
1187*4882a593Smuzhiyun     char *data;
1188*4882a593Smuzhiyun     Atom type;
1189*4882a593Smuzhiyun 
1190*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xXIGetPropertyReq);
1191*4882a593Smuzhiyun     if (stuff->delete)
1192*4882a593Smuzhiyun         UpdateCurrentTime();
1193*4882a593Smuzhiyun     rc = dixLookupDevice(&dev, stuff->deviceid, client,
1194*4882a593Smuzhiyun                          stuff->delete ? DixSetPropAccess : DixGetPropAccess);
1195*4882a593Smuzhiyun     if (rc != Success)
1196*4882a593Smuzhiyun         return rc;
1197*4882a593Smuzhiyun 
1198*4882a593Smuzhiyun     rc = get_property(client, dev, stuff->property, stuff->type,
1199*4882a593Smuzhiyun                       stuff->delete, stuff->offset, stuff->len,
1200*4882a593Smuzhiyun                       &bytes_after, &type, &format, &nitems, &length, &data);
1201*4882a593Smuzhiyun 
1202*4882a593Smuzhiyun     if (rc != Success)
1203*4882a593Smuzhiyun         return rc;
1204*4882a593Smuzhiyun 
1205*4882a593Smuzhiyun     reply = (xXIGetPropertyReply) {
1206*4882a593Smuzhiyun         .repType = X_Reply,
1207*4882a593Smuzhiyun         .RepType = X_XIGetProperty,
1208*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
1209*4882a593Smuzhiyun         .length = bytes_to_int32(length),
1210*4882a593Smuzhiyun         .type = type,
1211*4882a593Smuzhiyun         .bytes_after = bytes_after,
1212*4882a593Smuzhiyun         .num_items = nitems,
1213*4882a593Smuzhiyun         .format = format
1214*4882a593Smuzhiyun     };
1215*4882a593Smuzhiyun 
1216*4882a593Smuzhiyun     if (length && stuff->delete && (reply.bytes_after == 0))
1217*4882a593Smuzhiyun         send_property_event(dev, stuff->property, XIPropertyDeleted);
1218*4882a593Smuzhiyun 
1219*4882a593Smuzhiyun     WriteReplyToClient(client, sizeof(xXIGetPropertyReply), &reply);
1220*4882a593Smuzhiyun 
1221*4882a593Smuzhiyun     if (length) {
1222*4882a593Smuzhiyun         switch (reply.format) {
1223*4882a593Smuzhiyun         case 32:
1224*4882a593Smuzhiyun             client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
1225*4882a593Smuzhiyun             break;
1226*4882a593Smuzhiyun         case 16:
1227*4882a593Smuzhiyun             client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write;
1228*4882a593Smuzhiyun             break;
1229*4882a593Smuzhiyun         default:
1230*4882a593Smuzhiyun             client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient;
1231*4882a593Smuzhiyun             break;
1232*4882a593Smuzhiyun         }
1233*4882a593Smuzhiyun         WriteSwappedDataToClient(client, length, data);
1234*4882a593Smuzhiyun     }
1235*4882a593Smuzhiyun 
1236*4882a593Smuzhiyun     /* delete the Property */
1237*4882a593Smuzhiyun     if (stuff->delete && (reply.bytes_after == 0)) {
1238*4882a593Smuzhiyun         XIPropertyPtr prop, *prev;
1239*4882a593Smuzhiyun 
1240*4882a593Smuzhiyun         for (prev = &dev->properties.properties; (prop = *prev);
1241*4882a593Smuzhiyun              prev = &prop->next) {
1242*4882a593Smuzhiyun             if (prop->propertyName == stuff->property) {
1243*4882a593Smuzhiyun                 *prev = prop->next;
1244*4882a593Smuzhiyun                 XIDestroyDeviceProperty(prop);
1245*4882a593Smuzhiyun                 break;
1246*4882a593Smuzhiyun             }
1247*4882a593Smuzhiyun         }
1248*4882a593Smuzhiyun     }
1249*4882a593Smuzhiyun 
1250*4882a593Smuzhiyun     return Success;
1251*4882a593Smuzhiyun }
1252*4882a593Smuzhiyun 
1253*4882a593Smuzhiyun int _X_COLD
SProcXIListProperties(ClientPtr client)1254*4882a593Smuzhiyun SProcXIListProperties(ClientPtr client)
1255*4882a593Smuzhiyun {
1256*4882a593Smuzhiyun     REQUEST(xXIListPropertiesReq);
1257*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xXIListPropertiesReq);
1258*4882a593Smuzhiyun 
1259*4882a593Smuzhiyun     swaps(&stuff->length);
1260*4882a593Smuzhiyun     swaps(&stuff->deviceid);
1261*4882a593Smuzhiyun     return (ProcXIListProperties(client));
1262*4882a593Smuzhiyun }
1263*4882a593Smuzhiyun 
1264*4882a593Smuzhiyun int _X_COLD
SProcXIChangeProperty(ClientPtr client)1265*4882a593Smuzhiyun SProcXIChangeProperty(ClientPtr client)
1266*4882a593Smuzhiyun {
1267*4882a593Smuzhiyun     REQUEST(xXIChangePropertyReq);
1268*4882a593Smuzhiyun 
1269*4882a593Smuzhiyun     REQUEST_AT_LEAST_SIZE(xXIChangePropertyReq);
1270*4882a593Smuzhiyun     swaps(&stuff->length);
1271*4882a593Smuzhiyun     swaps(&stuff->deviceid);
1272*4882a593Smuzhiyun     swapl(&stuff->property);
1273*4882a593Smuzhiyun     swapl(&stuff->type);
1274*4882a593Smuzhiyun     swapl(&stuff->num_items);
1275*4882a593Smuzhiyun     return (ProcXIChangeProperty(client));
1276*4882a593Smuzhiyun }
1277*4882a593Smuzhiyun 
1278*4882a593Smuzhiyun int _X_COLD
SProcXIDeleteProperty(ClientPtr client)1279*4882a593Smuzhiyun SProcXIDeleteProperty(ClientPtr client)
1280*4882a593Smuzhiyun {
1281*4882a593Smuzhiyun     REQUEST(xXIDeletePropertyReq);
1282*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xXIDeletePropertyReq);
1283*4882a593Smuzhiyun 
1284*4882a593Smuzhiyun     swaps(&stuff->length);
1285*4882a593Smuzhiyun     swaps(&stuff->deviceid);
1286*4882a593Smuzhiyun     swapl(&stuff->property);
1287*4882a593Smuzhiyun     return (ProcXIDeleteProperty(client));
1288*4882a593Smuzhiyun }
1289*4882a593Smuzhiyun 
1290*4882a593Smuzhiyun int _X_COLD
SProcXIGetProperty(ClientPtr client)1291*4882a593Smuzhiyun SProcXIGetProperty(ClientPtr client)
1292*4882a593Smuzhiyun {
1293*4882a593Smuzhiyun     REQUEST(xXIGetPropertyReq);
1294*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xXIGetPropertyReq);
1295*4882a593Smuzhiyun 
1296*4882a593Smuzhiyun     swaps(&stuff->length);
1297*4882a593Smuzhiyun     swaps(&stuff->deviceid);
1298*4882a593Smuzhiyun     swapl(&stuff->property);
1299*4882a593Smuzhiyun     swapl(&stuff->type);
1300*4882a593Smuzhiyun     swapl(&stuff->offset);
1301*4882a593Smuzhiyun     swapl(&stuff->len);
1302*4882a593Smuzhiyun     return (ProcXIGetProperty(client));
1303*4882a593Smuzhiyun }
1304*4882a593Smuzhiyun 
1305*4882a593Smuzhiyun void _X_COLD
SRepXIListProperties(ClientPtr client,int size,xXIListPropertiesReply * rep)1306*4882a593Smuzhiyun SRepXIListProperties(ClientPtr client, int size, xXIListPropertiesReply * rep)
1307*4882a593Smuzhiyun {
1308*4882a593Smuzhiyun     swaps(&rep->sequenceNumber);
1309*4882a593Smuzhiyun     swapl(&rep->length);
1310*4882a593Smuzhiyun     swaps(&rep->num_properties);
1311*4882a593Smuzhiyun     /* properties will be swapped later, see ProcXIListProperties */
1312*4882a593Smuzhiyun     WriteToClient(client, size, rep);
1313*4882a593Smuzhiyun }
1314*4882a593Smuzhiyun 
1315*4882a593Smuzhiyun void _X_COLD
SRepXIGetProperty(ClientPtr client,int size,xXIGetPropertyReply * rep)1316*4882a593Smuzhiyun SRepXIGetProperty(ClientPtr client, int size, xXIGetPropertyReply * rep)
1317*4882a593Smuzhiyun {
1318*4882a593Smuzhiyun     swaps(&rep->sequenceNumber);
1319*4882a593Smuzhiyun     swapl(&rep->length);
1320*4882a593Smuzhiyun     swapl(&rep->type);
1321*4882a593Smuzhiyun     swapl(&rep->bytes_after);
1322*4882a593Smuzhiyun     swapl(&rep->num_items);
1323*4882a593Smuzhiyun     /* data will be swapped, see ProcXIGetProperty */
1324*4882a593Smuzhiyun     WriteToClient(client, size, rep);
1325*4882a593Smuzhiyun }
1326