xiproperty.c revision e383896c
14642e01fSmrg/*
24642e01fSmrg * Copyright © 2006 Keith Packard
34642e01fSmrg * Copyright © 2008 Peter Hutterer
44642e01fSmrg *
54642e01fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
64642e01fSmrg * copy of this software and associated documentation files (the "Software"),
74642e01fSmrg * to deal in the Software without restriction, including without limitation
84642e01fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
94642e01fSmrg * and/or sell copies of the Software, and to permit persons to whom the
104642e01fSmrg * Software is furnished to do so, subject to the following conditions:
114642e01fSmrg *
124642e01fSmrg * The above copyright notice and this permission notice (including the next
134642e01fSmrg * paragraph) shall be included in all copies or substantial portions of the
144642e01fSmrg * Software.
154642e01fSmrg *
164642e01fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WAXIANTY OF ANY KIND, EXPRESS OR
174642e01fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WAXIANTIES OF MERCHANTABILITY,
184642e01fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
194642e01fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
204642e01fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
214642e01fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
224642e01fSmrg * DEALINGS IN THE SOFTWARE.
234642e01fSmrg *
244642e01fSmrg */
254642e01fSmrg
264642e01fSmrg/* This code is a modified version of randr/rrproperty.c */
274642e01fSmrg
284642e01fSmrg#ifdef HAVE_DIX_CONFIG_H
294642e01fSmrg#include <dix-config.h>
304642e01fSmrg#endif
314642e01fSmrg
324642e01fSmrg#include "dix.h"
334642e01fSmrg#include "inputstr.h"
344642e01fSmrg#include <X11/extensions/XI.h>
354642e01fSmrg#include <X11/Xatom.h>
364642e01fSmrg#include <X11/extensions/XIproto.h>
376747b715Smrg#include <X11/extensions/XI2proto.h>
384642e01fSmrg#include "exglobals.h"
394642e01fSmrg#include "exevents.h"
404642e01fSmrg#include "swaprep.h"
414642e01fSmrg
424642e01fSmrg#include "xiproperty.h"
434642e01fSmrg#include "xserver-properties.h"
444642e01fSmrg
454642e01fSmrg/**
464642e01fSmrg * Properties used or alloced from inside the server.
474642e01fSmrg */
48f7df2e56Smrgstatic struct dev_properties {
494642e01fSmrg    Atom type;
50f7df2e56Smrg    const char *name;
514642e01fSmrg} dev_properties[] = {
524642e01fSmrg    {0, XI_PROP_ENABLED},
536747b715Smrg    {0, XI_PROP_XTEST_DEVICE},
546747b715Smrg    {0, XATOM_FLOAT},
556747b715Smrg    {0, ACCEL_PROP_PROFILE_NUMBER},
566747b715Smrg    {0, ACCEL_PROP_CONSTANT_DECELERATION},
576747b715Smrg    {0, ACCEL_PROP_ADAPTIVE_DECELERATION},
586747b715Smrg    {0, ACCEL_PROP_VELOCITY_SCALING},
596747b715Smrg    {0, AXIS_LABEL_PROP},
606747b715Smrg    {0, AXIS_LABEL_PROP_REL_X},
616747b715Smrg    {0, AXIS_LABEL_PROP_REL_Y},
626747b715Smrg    {0, AXIS_LABEL_PROP_REL_Z},
636747b715Smrg    {0, AXIS_LABEL_PROP_REL_RX},
646747b715Smrg    {0, AXIS_LABEL_PROP_REL_RY},
656747b715Smrg    {0, AXIS_LABEL_PROP_REL_RZ},
666747b715Smrg    {0, AXIS_LABEL_PROP_REL_HWHEEL},
676747b715Smrg    {0, AXIS_LABEL_PROP_REL_DIAL},
686747b715Smrg    {0, AXIS_LABEL_PROP_REL_WHEEL},
696747b715Smrg    {0, AXIS_LABEL_PROP_REL_MISC},
70f7df2e56Smrg    {0, AXIS_LABEL_PROP_REL_VSCROLL},
71f7df2e56Smrg    {0, AXIS_LABEL_PROP_REL_HSCROLL},
726747b715Smrg    {0, AXIS_LABEL_PROP_ABS_X},
736747b715Smrg    {0, AXIS_LABEL_PROP_ABS_Y},
746747b715Smrg    {0, AXIS_LABEL_PROP_ABS_Z},
756747b715Smrg    {0, AXIS_LABEL_PROP_ABS_RX},
766747b715Smrg    {0, AXIS_LABEL_PROP_ABS_RY},
776747b715Smrg    {0, AXIS_LABEL_PROP_ABS_RZ},
786747b715Smrg    {0, AXIS_LABEL_PROP_ABS_THROTTLE},
796747b715Smrg    {0, AXIS_LABEL_PROP_ABS_RUDDER},
806747b715Smrg    {0, AXIS_LABEL_PROP_ABS_WHEEL},
816747b715Smrg    {0, AXIS_LABEL_PROP_ABS_GAS},
826747b715Smrg    {0, AXIS_LABEL_PROP_ABS_BRAKE},
836747b715Smrg    {0, AXIS_LABEL_PROP_ABS_HAT0X},
846747b715Smrg    {0, AXIS_LABEL_PROP_ABS_HAT0Y},
856747b715Smrg    {0, AXIS_LABEL_PROP_ABS_HAT1X},
866747b715Smrg    {0, AXIS_LABEL_PROP_ABS_HAT1Y},
876747b715Smrg    {0, AXIS_LABEL_PROP_ABS_HAT2X},
886747b715Smrg    {0, AXIS_LABEL_PROP_ABS_HAT2Y},
896747b715Smrg    {0, AXIS_LABEL_PROP_ABS_HAT3X},
906747b715Smrg    {0, AXIS_LABEL_PROP_ABS_HAT3Y},
916747b715Smrg    {0, AXIS_LABEL_PROP_ABS_PRESSURE},
926747b715Smrg    {0, AXIS_LABEL_PROP_ABS_DISTANCE},
936747b715Smrg    {0, AXIS_LABEL_PROP_ABS_TILT_X},
946747b715Smrg    {0, AXIS_LABEL_PROP_ABS_TILT_Y},
956747b715Smrg    {0, AXIS_LABEL_PROP_ABS_TOOL_WIDTH},
966747b715Smrg    {0, AXIS_LABEL_PROP_ABS_VOLUME},
976747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR},
986747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR},
996747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_WIDTH_MAJOR},
1006747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_WIDTH_MINOR},
1016747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_ORIENTATION},
1026747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_POSITION_X},
1036747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_POSITION_Y},
1046747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_TOOL_TYPE},
1056747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_BLOB_ID},
1066747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_TRACKING_ID},
1076747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_PRESSURE},
108f7df2e56Smrg    {0, AXIS_LABEL_PROP_ABS_MT_DISTANCE},
109f7df2e56Smrg    {0, AXIS_LABEL_PROP_ABS_MT_TOOL_X},
110f7df2e56Smrg    {0, AXIS_LABEL_PROP_ABS_MT_TOOL_Y},
1116747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MISC},
1126747b715Smrg    {0, BTN_LABEL_PROP},
1136747b715Smrg    {0, BTN_LABEL_PROP_BTN_UNKNOWN},
1146747b715Smrg    {0, BTN_LABEL_PROP_BTN_WHEEL_UP},
1156747b715Smrg    {0, BTN_LABEL_PROP_BTN_WHEEL_DOWN},
1166747b715Smrg    {0, BTN_LABEL_PROP_BTN_HWHEEL_LEFT},
1176747b715Smrg    {0, BTN_LABEL_PROP_BTN_HWHEEL_RIGHT},
1186747b715Smrg    {0, BTN_LABEL_PROP_BTN_0},
1196747b715Smrg    {0, BTN_LABEL_PROP_BTN_1},
1206747b715Smrg    {0, BTN_LABEL_PROP_BTN_2},
1216747b715Smrg    {0, BTN_LABEL_PROP_BTN_3},
1226747b715Smrg    {0, BTN_LABEL_PROP_BTN_4},
1236747b715Smrg    {0, BTN_LABEL_PROP_BTN_5},
1246747b715Smrg    {0, BTN_LABEL_PROP_BTN_6},
1256747b715Smrg    {0, BTN_LABEL_PROP_BTN_7},
1266747b715Smrg    {0, BTN_LABEL_PROP_BTN_8},
1276747b715Smrg    {0, BTN_LABEL_PROP_BTN_9},
1286747b715Smrg    {0, BTN_LABEL_PROP_BTN_LEFT},
1296747b715Smrg    {0, BTN_LABEL_PROP_BTN_RIGHT},
1306747b715Smrg    {0, BTN_LABEL_PROP_BTN_MIDDLE},
1316747b715Smrg    {0, BTN_LABEL_PROP_BTN_SIDE},
1326747b715Smrg    {0, BTN_LABEL_PROP_BTN_EXTRA},
1336747b715Smrg    {0, BTN_LABEL_PROP_BTN_FORWARD},
1346747b715Smrg    {0, BTN_LABEL_PROP_BTN_BACK},
1356747b715Smrg    {0, BTN_LABEL_PROP_BTN_TASK},
1366747b715Smrg    {0, BTN_LABEL_PROP_BTN_TRIGGER},
1376747b715Smrg    {0, BTN_LABEL_PROP_BTN_THUMB},
1386747b715Smrg    {0, BTN_LABEL_PROP_BTN_THUMB2},
1396747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOP},
1406747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOP2},
1416747b715Smrg    {0, BTN_LABEL_PROP_BTN_PINKIE},
1426747b715Smrg    {0, BTN_LABEL_PROP_BTN_BASE},
1436747b715Smrg    {0, BTN_LABEL_PROP_BTN_BASE2},
1446747b715Smrg    {0, BTN_LABEL_PROP_BTN_BASE3},
1456747b715Smrg    {0, BTN_LABEL_PROP_BTN_BASE4},
1466747b715Smrg    {0, BTN_LABEL_PROP_BTN_BASE5},
1476747b715Smrg    {0, BTN_LABEL_PROP_BTN_BASE6},
1486747b715Smrg    {0, BTN_LABEL_PROP_BTN_DEAD},
1496747b715Smrg    {0, BTN_LABEL_PROP_BTN_A},
1506747b715Smrg    {0, BTN_LABEL_PROP_BTN_B},
1516747b715Smrg    {0, BTN_LABEL_PROP_BTN_C},
1526747b715Smrg    {0, BTN_LABEL_PROP_BTN_X},
1536747b715Smrg    {0, BTN_LABEL_PROP_BTN_Y},
1546747b715Smrg    {0, BTN_LABEL_PROP_BTN_Z},
1556747b715Smrg    {0, BTN_LABEL_PROP_BTN_TL},
1566747b715Smrg    {0, BTN_LABEL_PROP_BTN_TR},
1576747b715Smrg    {0, BTN_LABEL_PROP_BTN_TL2},
1586747b715Smrg    {0, BTN_LABEL_PROP_BTN_TR2},
1596747b715Smrg    {0, BTN_LABEL_PROP_BTN_SELECT},
1606747b715Smrg    {0, BTN_LABEL_PROP_BTN_START},
1616747b715Smrg    {0, BTN_LABEL_PROP_BTN_MODE},
1626747b715Smrg    {0, BTN_LABEL_PROP_BTN_THUMBL},
1636747b715Smrg    {0, BTN_LABEL_PROP_BTN_THUMBR},
1646747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOOL_PEN},
1656747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOOL_RUBBER},
1666747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOOL_BRUSH},
1676747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOOL_PENCIL},
1686747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOOL_AIRBRUSH},
1696747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOOL_FINGER},
1706747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOOL_MOUSE},
1716747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOOL_LENS},
1726747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOUCH},
1736747b715Smrg    {0, BTN_LABEL_PROP_BTN_STYLUS},
1746747b715Smrg    {0, BTN_LABEL_PROP_BTN_STYLUS2},
1756747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOOL_DOUBLETAP},
1766747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOOL_TRIPLETAP},
1776747b715Smrg    {0, BTN_LABEL_PROP_BTN_GEAR_DOWN},
1786747b715Smrg    {0, BTN_LABEL_PROP_BTN_GEAR_UP},
1796747b715Smrg    {0, XI_PROP_TRANSFORM}
1804642e01fSmrg};
1814642e01fSmrg
1824642e01fSmrgstatic long XIPropHandlerID = 1;
1834642e01fSmrg
184f7df2e56Smrgstatic void
185f7df2e56Smrgsend_property_event(DeviceIntPtr dev, Atom property, int what)
1866747b715Smrg{
187f7df2e56Smrg    int state = (what == XIPropertyDeleted) ? PropertyDelete : PropertyNewValue;
188f7df2e56Smrg    devicePropertyNotify event = {
189f7df2e56Smrg        .type = DevicePropertyNotify,
190f7df2e56Smrg        .deviceid = dev->id,
191f7df2e56Smrg        .state = state,
192f7df2e56Smrg        .atom = property,
193f7df2e56Smrg        .time = currentTime.milliseconds
194f7df2e56Smrg    };
195f7df2e56Smrg    xXIPropertyEvent xi2 = {
196f7df2e56Smrg        .type = GenericEvent,
197f7df2e56Smrg        .extension = IReqCode,
198f7df2e56Smrg        .length = 0,
199f7df2e56Smrg        .evtype = XI_PropertyEvent,
200f7df2e56Smrg        .deviceid = dev->id,
201f7df2e56Smrg        .time = currentTime.milliseconds,
202f7df2e56Smrg        .property = property,
203f7df2e56Smrg        .what = what
204f7df2e56Smrg    };
205f7df2e56Smrg
206f7df2e56Smrg    SendEventToAllWindows(dev, DevicePropertyNotifyMask, (xEvent *) &event, 1);
207f7df2e56Smrg
208f7df2e56Smrg    SendEventToAllWindows(dev, GetEventFilter(dev, (xEvent *) &xi2),
209f7df2e56Smrg                          (xEvent *) &xi2, 1);
2106747b715Smrg}
2116747b715Smrg
212f7df2e56Smrgstatic int
213f7df2e56Smrglist_atoms(DeviceIntPtr dev, int *natoms, Atom **atoms_return)
2146747b715Smrg{
2156747b715Smrg    XIPropertyPtr prop;
216f7df2e56Smrg    Atom *atoms = NULL;
217f7df2e56Smrg    int nprops = 0;
2186747b715Smrg
2196747b715Smrg    for (prop = dev->properties.properties; prop; prop = prop->next)
2206747b715Smrg        nprops++;
221f7df2e56Smrg    if (nprops) {
2226747b715Smrg        Atom *a;
2236747b715Smrg
224f7df2e56Smrg        atoms = xallocarray(nprops, sizeof(Atom));
225f7df2e56Smrg        if (!atoms)
2266747b715Smrg            return BadAlloc;
2276747b715Smrg        a = atoms;
2286747b715Smrg        for (prop = dev->properties.properties; prop; prop = prop->next, a++)
2296747b715Smrg            *a = prop->propertyName;
2306747b715Smrg    }
2316747b715Smrg
2326747b715Smrg    *natoms = nprops;
2336747b715Smrg    *atoms_return = atoms;
2346747b715Smrg    return Success;
2356747b715Smrg}
2366747b715Smrg
2376747b715Smrgstatic int
2386747b715Smrgget_property(ClientPtr client, DeviceIntPtr dev, Atom property, Atom type,
2396747b715Smrg             BOOL delete, int offset, int length,
2406747b715Smrg             int *bytes_after, Atom *type_return, int *format, int *nitems,
2416747b715Smrg             int *length_return, char **data)
2426747b715Smrg{
2436747b715Smrg    unsigned long n, len, ind;
2446747b715Smrg    int rc;
2456747b715Smrg    XIPropertyPtr prop;
2466747b715Smrg    XIPropertyValuePtr prop_value;
2476747b715Smrg
248f7df2e56Smrg    if (!ValidAtom(property)) {
2496747b715Smrg        client->errorValue = property;
2506747b715Smrg        return BadAtom;
2516747b715Smrg    }
252f7df2e56Smrg    if ((delete != xTrue) && (delete != xFalse)) {
2536747b715Smrg        client->errorValue = delete;
2546747b715Smrg        return BadValue;
2556747b715Smrg    }
2566747b715Smrg
257f7df2e56Smrg    if ((type != AnyPropertyType) && !ValidAtom(type)) {
2586747b715Smrg        client->errorValue = type;
2596747b715Smrg        return BadAtom;
2606747b715Smrg    }
2616747b715Smrg
2626747b715Smrg    for (prop = dev->properties.properties; prop; prop = prop->next)
2636747b715Smrg        if (prop->propertyName == property)
2646747b715Smrg            break;
2656747b715Smrg
266f7df2e56Smrg    if (!prop) {
2676747b715Smrg        *bytes_after = 0;
2686747b715Smrg        *type_return = None;
2696747b715Smrg        *format = 0;
2706747b715Smrg        *nitems = 0;
2716747b715Smrg        *length_return = 0;
2726747b715Smrg        return Success;
2736747b715Smrg    }
2746747b715Smrg
2756747b715Smrg    rc = XIGetDeviceProperty(dev, property, &prop_value);
276f7df2e56Smrg    if (rc != Success) {
2776747b715Smrg        client->errorValue = property;
2786747b715Smrg        return rc;
2796747b715Smrg    }
2806747b715Smrg
2816747b715Smrg    /* If the request type and actual type don't match. Return the
282f7df2e56Smrg       property information, but not the data. */
2836747b715Smrg
284f7df2e56Smrg    if (((type != prop_value->type) && (type != AnyPropertyType))) {
2856747b715Smrg        *bytes_after = prop_value->size;
2866747b715Smrg        *format = prop_value->format;
2876747b715Smrg        *length_return = 0;
2886747b715Smrg        *nitems = 0;
2896747b715Smrg        *type_return = prop_value->type;
2906747b715Smrg        return Success;
2916747b715Smrg    }
2926747b715Smrg
2936747b715Smrg    /* Return type, format, value to client */
294f7df2e56Smrg    n = (prop_value->format / 8) * prop_value->size;    /* size (bytes) of prop */
2956747b715Smrg    ind = offset << 2;
2966747b715Smrg
297f7df2e56Smrg    /* If offset is invalid such that it causes "len" to
298f7df2e56Smrg       be negative, it's a value error. */
2996747b715Smrg
300f7df2e56Smrg    if (n < ind) {
3016747b715Smrg        client->errorValue = offset;
3026747b715Smrg        return BadValue;
3036747b715Smrg    }
3046747b715Smrg
3056747b715Smrg    len = min(n - ind, 4 * length);
3066747b715Smrg
3076747b715Smrg    *bytes_after = n - (ind + len);
3086747b715Smrg    *format = prop_value->format;
3096747b715Smrg    *length_return = len;
3106747b715Smrg    if (prop_value->format)
3116747b715Smrg        *nitems = len / (prop_value->format / 8);
3126747b715Smrg    else
3136747b715Smrg        *nitems = 0;
3146747b715Smrg    *type_return = prop_value->type;
3156747b715Smrg
316f7df2e56Smrg    *data = (char *) prop_value->data + ind;
3176747b715Smrg
3186747b715Smrg    return Success;
3196747b715Smrg}
3206747b715Smrg
3216747b715Smrgstatic int
3226747b715Smrgcheck_change_property(ClientPtr client, Atom property, Atom type, int format,
3236747b715Smrg                      int mode, int nitems)
3246747b715Smrg{
3256747b715Smrg    if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
326f7df2e56Smrg        (mode != PropModePrepend)) {
3276747b715Smrg        client->errorValue = mode;
3286747b715Smrg        return BadValue;
3296747b715Smrg    }
330f7df2e56Smrg    if ((format != 8) && (format != 16) && (format != 32)) {
3316747b715Smrg        client->errorValue = format;
3326747b715Smrg        return BadValue;
3336747b715Smrg    }
3346747b715Smrg
335f7df2e56Smrg    if (!ValidAtom(property)) {
3366747b715Smrg        client->errorValue = property;
3376747b715Smrg        return BadAtom;
3386747b715Smrg    }
339f7df2e56Smrg    if (!ValidAtom(type)) {
3406747b715Smrg        client->errorValue = type;
3416747b715Smrg        return BadAtom;
3426747b715Smrg    }
3436747b715Smrg
3446747b715Smrg    return Success;
3456747b715Smrg}
3466747b715Smrg
3476747b715Smrgstatic int
3486747b715Smrgchange_property(ClientPtr client, DeviceIntPtr dev, Atom property, Atom type,
3496747b715Smrg                int format, int mode, int len, void *data)
3506747b715Smrg{
3516747b715Smrg    int rc = Success;
3526747b715Smrg
353f7df2e56Smrg    rc = XIChangeDeviceProperty(dev, property, type, format, mode, len, data,
354f7df2e56Smrg                                TRUE);
3556747b715Smrg    if (rc != Success)
3566747b715Smrg        client->errorValue = property;
3576747b715Smrg
3586747b715Smrg    return rc;
3596747b715Smrg}
3606747b715Smrg
3614642e01fSmrg/**
3626747b715Smrg * Return the atom assigned to the specified string or 0 if the atom isn't known
3634642e01fSmrg * to the DIX.
3644642e01fSmrg *
3654642e01fSmrg * If name is NULL, None is returned.
3664642e01fSmrg */
3676747b715SmrgAtom
368f7df2e56SmrgXIGetKnownProperty(const char *name)
3694642e01fSmrg{
3704642e01fSmrg    int i;
3714642e01fSmrg
3724642e01fSmrg    if (!name)
3734642e01fSmrg        return None;
3744642e01fSmrg
3757e31ba66Smrg    for (i = 0; i < ARRAY_SIZE(dev_properties); i++) {
376f7df2e56Smrg        if (strcmp(name, dev_properties[i].name) == 0) {
377f7df2e56Smrg            if (dev_properties[i].type == None) {
378f7df2e56Smrg                dev_properties[i].type =
379f7df2e56Smrg                    MakeAtom(dev_properties[i].name,
380f7df2e56Smrg                             strlen(dev_properties[i].name), TRUE);
3816747b715Smrg            }
3826747b715Smrg
3834642e01fSmrg            return dev_properties[i].type;
3846747b715Smrg        }
3854642e01fSmrg    }
3864642e01fSmrg
3874642e01fSmrg    return 0;
3884642e01fSmrg}
3894642e01fSmrg
3906747b715Smrgvoid
3916747b715SmrgXIResetProperties(void)
3926747b715Smrg{
3936747b715Smrg    int i;
3946747b715Smrg
3957e31ba66Smrg    for (i = 0; i < ARRAY_SIZE(dev_properties); i++)
3966747b715Smrg        dev_properties[i].type = None;
3976747b715Smrg}
3986747b715Smrg
3994642e01fSmrg/**
4004642e01fSmrg * Convert the given property's value(s) into @nelem_return integer values and
4014642e01fSmrg * store them in @buf_return. If @nelem_return is larger than the number of
4024642e01fSmrg * values in the property, @nelem_return is set to the number of values in the
4034642e01fSmrg * property.
4044642e01fSmrg *
4054642e01fSmrg * If *@buf_return is NULL and @nelem_return is 0, memory is allocated
4064642e01fSmrg * automatically and must be freed by the caller.
4074642e01fSmrg *
4084642e01fSmrg * Possible return codes.
4094642e01fSmrg * Success ... No error.
4104642e01fSmrg * BadMatch ... Wrong atom type, atom is not XA_INTEGER
4114642e01fSmrg * BadAlloc ... NULL passed as buffer and allocation failed.
4124642e01fSmrg * BadLength ... @buff is NULL but @nelem_return is non-zero.
4134642e01fSmrg *
4144642e01fSmrg * @param val The property value
4154642e01fSmrg * @param nelem_return The maximum number of elements to return.
4164642e01fSmrg * @param buf_return Pointer to an array of at least @nelem_return values.
4175a112b11Smrg * @return Success or the error code if an error occurred.
4184642e01fSmrg */
4194642e01fSmrg_X_EXPORT int
4204642e01fSmrgXIPropToInt(XIPropertyValuePtr val, int *nelem_return, int **buf_return)
4214642e01fSmrg{
4224642e01fSmrg    int i;
4234642e01fSmrg    int *buf;
4244642e01fSmrg
4254642e01fSmrg    if (val->type != XA_INTEGER)
4264642e01fSmrg        return BadMatch;
4274642e01fSmrg    if (!*buf_return && *nelem_return)
4284642e01fSmrg        return BadLength;
4294642e01fSmrg
430f7df2e56Smrg    switch (val->format) {
431f7df2e56Smrg    case 8:
432f7df2e56Smrg    case 16:
433f7df2e56Smrg    case 32:
434f7df2e56Smrg        break;
435f7df2e56Smrg    default:
436f7df2e56Smrg        return BadValue;
4374642e01fSmrg    }
4384642e01fSmrg
4394642e01fSmrg    buf = *buf_return;
4404642e01fSmrg
441f7df2e56Smrg    if (!buf && !(*nelem_return)) {
4426747b715Smrg        buf = calloc(val->size, sizeof(int));
4434642e01fSmrg        if (!buf)
4444642e01fSmrg            return BadAlloc;
4454642e01fSmrg        *buf_return = buf;
4464642e01fSmrg        *nelem_return = val->size;
447f7df2e56Smrg    }
448f7df2e56Smrg    else if (val->size < *nelem_return)
4494642e01fSmrg        *nelem_return = val->size;
4504642e01fSmrg
451f7df2e56Smrg    for (i = 0; i < val->size && i < *nelem_return; i++) {
452f7df2e56Smrg        switch (val->format) {
453f7df2e56Smrg        case 8:
454f7df2e56Smrg            buf[i] = ((CARD8 *) val->data)[i];
455f7df2e56Smrg            break;
456f7df2e56Smrg        case 16:
457f7df2e56Smrg            buf[i] = ((CARD16 *) val->data)[i];
458f7df2e56Smrg            break;
459f7df2e56Smrg        case 32:
460f7df2e56Smrg            buf[i] = ((CARD32 *) val->data)[i];
461f7df2e56Smrg            break;
4624642e01fSmrg        }
4634642e01fSmrg    }
4644642e01fSmrg
4654642e01fSmrg    return Success;
4664642e01fSmrg}
4674642e01fSmrg
4684642e01fSmrg/**
4694642e01fSmrg * Convert the given property's value(s) into @nelem_return float values and
4704642e01fSmrg * store them in @buf_return. If @nelem_return is larger than the number of
4714642e01fSmrg * values in the property, @nelem_return is set to the number of values in the
4724642e01fSmrg * property.
4734642e01fSmrg *
4744642e01fSmrg * If *@buf_return is NULL and @nelem_return is 0, memory is allocated
4754642e01fSmrg * automatically and must be freed by the caller.
4764642e01fSmrg *
4774642e01fSmrg * Possible errors returned:
4784642e01fSmrg * Success
4794642e01fSmrg * BadMatch ... Wrong atom type, atom is not XA_FLOAT
4804642e01fSmrg * BadValue ... Wrong format, format is not 32
4814642e01fSmrg * BadAlloc ... NULL passed as buffer and allocation failed.
4824642e01fSmrg * BadLength ... @buff is NULL but @nelem_return is non-zero.
4834642e01fSmrg *
4844642e01fSmrg * @param val The property value
4854642e01fSmrg * @param nelem_return The maximum number of elements to return.
4864642e01fSmrg * @param buf_return Pointer to an array of at least @nelem_return values.
4875a112b11Smrg * @return Success or the error code if an error occurred.
4884642e01fSmrg */
4894642e01fSmrg_X_EXPORT int
4904642e01fSmrgXIPropToFloat(XIPropertyValuePtr val, int *nelem_return, float **buf_return)
4914642e01fSmrg{
4924642e01fSmrg    int i;
4934642e01fSmrg    float *buf;
4944642e01fSmrg
4954642e01fSmrg    if (!val->type || val->type != XIGetKnownProperty(XATOM_FLOAT))
4964642e01fSmrg        return BadMatch;
4974642e01fSmrg
4984642e01fSmrg    if (val->format != 32)
4994642e01fSmrg        return BadValue;
5004642e01fSmrg    if (!*buf_return && *nelem_return)
5014642e01fSmrg        return BadLength;
5024642e01fSmrg
5034642e01fSmrg    buf = *buf_return;
5044642e01fSmrg
505f7df2e56Smrg    if (!buf && !(*nelem_return)) {
5066747b715Smrg        buf = calloc(val->size, sizeof(float));
5074642e01fSmrg        if (!buf)
5084642e01fSmrg            return BadAlloc;
5094642e01fSmrg        *buf_return = buf;
5104642e01fSmrg        *nelem_return = val->size;
511f7df2e56Smrg    }
512f7df2e56Smrg    else if (val->size < *nelem_return)
5134642e01fSmrg        *nelem_return = val->size;
5144642e01fSmrg
5154642e01fSmrg    for (i = 0; i < val->size && i < *nelem_return; i++)
516f7df2e56Smrg        buf[i] = ((float *) val->data)[i];
5174642e01fSmrg
5184642e01fSmrg    return Success;
5194642e01fSmrg}
5204642e01fSmrg
5214642e01fSmrg/* Registers a new property handler on the given device and returns a unique
5224642e01fSmrg * identifier for this handler. This identifier is required to unregister the
5234642e01fSmrg * property handler again.
5245a112b11Smrg * @return The handler's identifier or 0 if an error occurred.
5254642e01fSmrg */
5264642e01fSmrglong
527f7df2e56SmrgXIRegisterPropertyHandler(DeviceIntPtr dev,
5284642e01fSmrg                          int (*SetProperty) (DeviceIntPtr dev,
5294642e01fSmrg                                              Atom property,
5304642e01fSmrg                                              XIPropertyValuePtr prop,
5314642e01fSmrg                                              BOOL checkonly),
5324642e01fSmrg                          int (*GetProperty) (DeviceIntPtr dev,
5334642e01fSmrg                                              Atom property),
5344642e01fSmrg                          int (*DeleteProperty) (DeviceIntPtr dev,
5354642e01fSmrg                                                 Atom property))
5364642e01fSmrg{
5374642e01fSmrg    XIPropertyHandlerPtr new_handler;
5384642e01fSmrg
5396747b715Smrg    new_handler = calloc(1, sizeof(XIPropertyHandler));
5404642e01fSmrg    if (!new_handler)
5414642e01fSmrg        return 0;
5424642e01fSmrg
5434642e01fSmrg    new_handler->id = XIPropHandlerID++;
5444642e01fSmrg    new_handler->SetProperty = SetProperty;
5454642e01fSmrg    new_handler->GetProperty = GetProperty;
5464642e01fSmrg    new_handler->DeleteProperty = DeleteProperty;
5474642e01fSmrg    new_handler->next = dev->properties.handlers;
5484642e01fSmrg    dev->properties.handlers = new_handler;
5494642e01fSmrg
5504642e01fSmrg    return new_handler->id;
5514642e01fSmrg}
5524642e01fSmrg
5534642e01fSmrgvoid
5544642e01fSmrgXIUnregisterPropertyHandler(DeviceIntPtr dev, long id)
5554642e01fSmrg{
5564642e01fSmrg    XIPropertyHandlerPtr curr, prev = NULL;
5574642e01fSmrg
5584642e01fSmrg    curr = dev->properties.handlers;
559f7df2e56Smrg    while (curr && curr->id != id) {
5604642e01fSmrg        prev = curr;
5614642e01fSmrg        curr = curr->next;
5624642e01fSmrg    }
5634642e01fSmrg
5644642e01fSmrg    if (!curr)
5654642e01fSmrg        return;
5664642e01fSmrg
567f7df2e56Smrg    if (!prev)                  /* first one */
5684642e01fSmrg        dev->properties.handlers = curr->next;
5694642e01fSmrg    else
5704642e01fSmrg        prev->next = curr->next;
5714642e01fSmrg
5726747b715Smrg    free(curr);
5734642e01fSmrg}
5744642e01fSmrg
5754642e01fSmrgstatic XIPropertyPtr
576f7df2e56SmrgXICreateDeviceProperty(Atom property)
5774642e01fSmrg{
578f7df2e56Smrg    XIPropertyPtr prop;
5794642e01fSmrg
580f7df2e56Smrg    prop = (XIPropertyPtr) malloc(sizeof(XIPropertyRec));
5814642e01fSmrg    if (!prop)
5824642e01fSmrg        return NULL;
5834642e01fSmrg
584f7df2e56Smrg    prop->next = NULL;
585f7df2e56Smrg    prop->propertyName = property;
586f7df2e56Smrg    prop->value.type = None;
5874642e01fSmrg    prop->value.format = 0;
588f7df2e56Smrg    prop->value.size = 0;
589f7df2e56Smrg    prop->value.data = NULL;
590f7df2e56Smrg    prop->deletable = TRUE;
5914642e01fSmrg
5924642e01fSmrg    return prop;
5934642e01fSmrg}
5944642e01fSmrg
5954642e01fSmrgstatic XIPropertyPtr
5964642e01fSmrgXIFetchDeviceProperty(DeviceIntPtr dev, Atom property)
5974642e01fSmrg{
598f7df2e56Smrg    XIPropertyPtr prop;
5994642e01fSmrg
6004642e01fSmrg    for (prop = dev->properties.properties; prop; prop = prop->next)
6014642e01fSmrg        if (prop->propertyName == property)
6024642e01fSmrg            return prop;
6034642e01fSmrg    return NULL;
6044642e01fSmrg}
6054642e01fSmrg
6064642e01fSmrgstatic void
607f7df2e56SmrgXIDestroyDeviceProperty(XIPropertyPtr prop)
6084642e01fSmrg{
6096747b715Smrg    free(prop->value.data);
6106747b715Smrg    free(prop);
6114642e01fSmrg}
6124642e01fSmrg
6134642e01fSmrg/* This function destroys all of the device's property-related stuff,
6144642e01fSmrg * including removing all device handlers.
6154642e01fSmrg * DO NOT CALL FROM THE DRIVER.
6164642e01fSmrg */
6174642e01fSmrgvoid
618f7df2e56SmrgXIDeleteAllDeviceProperties(DeviceIntPtr device)
6194642e01fSmrg{
620f7df2e56Smrg    XIPropertyPtr prop, next;
621f7df2e56Smrg    XIPropertyHandlerPtr curr_handler, next_handler;
6224642e01fSmrg
6237e31ba66Smrg    UpdateCurrentTimeIf();
624f7df2e56Smrg    for (prop = device->properties.properties; prop; prop = next) {
6254642e01fSmrg        next = prop->next;
6266747b715Smrg        send_property_event(device, prop->propertyName, XIPropertyDeleted);
6274642e01fSmrg        XIDestroyDeviceProperty(prop);
6284642e01fSmrg    }
6294642e01fSmrg
6306747b715Smrg    device->properties.properties = NULL;
6316747b715Smrg
6324642e01fSmrg    /* Now free all handlers */
6334642e01fSmrg    curr_handler = device->properties.handlers;
634f7df2e56Smrg    while (curr_handler) {
6354642e01fSmrg        next_handler = curr_handler->next;
6366747b715Smrg        free(curr_handler);
6374642e01fSmrg        curr_handler = next_handler;
6384642e01fSmrg    }
6396747b715Smrg
6406747b715Smrg    device->properties.handlers = NULL;
6414642e01fSmrg}
6424642e01fSmrg
6434642e01fSmrgint
644f7df2e56SmrgXIDeleteDeviceProperty(DeviceIntPtr device, Atom property, Bool fromClient)
6454642e01fSmrg{
646f7df2e56Smrg    XIPropertyPtr prop, *prev;
647f7df2e56Smrg    int rc = Success;
6484642e01fSmrg
649f7df2e56Smrg    for (prev = &device->properties.properties; (prop = *prev);
650f7df2e56Smrg         prev = &(prop->next))
6514642e01fSmrg        if (prop->propertyName == property)
6524642e01fSmrg            break;
6534642e01fSmrg
6546747b715Smrg    if (!prop)
6556747b715Smrg        return Success;
6566747b715Smrg
6574642e01fSmrg    if (fromClient && !prop->deletable)
6584642e01fSmrg        return BadAccess;
6594642e01fSmrg
6604642e01fSmrg    /* Ask handlers if we may delete the property */
661f7df2e56Smrg    if (device->properties.handlers) {
6624642e01fSmrg        XIPropertyHandlerPtr handler = device->properties.handlers;
663f7df2e56Smrg
664f7df2e56Smrg        while (handler) {
6654642e01fSmrg            if (handler->DeleteProperty)
6664642e01fSmrg                rc = handler->DeleteProperty(device, prop->propertyName);
6674642e01fSmrg            if (rc != Success)
6686747b715Smrg                return rc;
6694642e01fSmrg            handler = handler->next;
6704642e01fSmrg        }
6714642e01fSmrg    }
6724642e01fSmrg
673f7df2e56Smrg    if (prop) {
6747e31ba66Smrg        UpdateCurrentTimeIf();
6754642e01fSmrg        *prev = prop->next;
6766747b715Smrg        send_property_event(device, prop->propertyName, XIPropertyDeleted);
677f7df2e56Smrg        XIDestroyDeviceProperty(prop);
6784642e01fSmrg    }
6794642e01fSmrg
6804642e01fSmrg    return Success;
6814642e01fSmrg}
6824642e01fSmrg
6834642e01fSmrgint
684f7df2e56SmrgXIChangeDeviceProperty(DeviceIntPtr dev, Atom property, Atom type,
685f7df2e56Smrg                       int format, int mode, unsigned long len,
686f7df2e56Smrg                       const void *value, Bool sendevent)
6874642e01fSmrg{
688f7df2e56Smrg    XIPropertyPtr prop;
689f7df2e56Smrg    int size_in_bytes;
690f7df2e56Smrg    unsigned long total_len;
691f7df2e56Smrg    XIPropertyValuePtr prop_value;
692f7df2e56Smrg    XIPropertyValueRec new_value;
693f7df2e56Smrg    Bool add = FALSE;
694f7df2e56Smrg    int rc;
6954642e01fSmrg
6964642e01fSmrg    size_in_bytes = format >> 3;
6974642e01fSmrg
6984642e01fSmrg    /* first see if property already exists */
699f7df2e56Smrg    prop = XIFetchDeviceProperty(dev, property);
700f7df2e56Smrg    if (!prop) {                /* just add to list */
701f7df2e56Smrg        prop = XICreateDeviceProperty(property);
7024642e01fSmrg        if (!prop)
7036747b715Smrg            return BadAlloc;
7044642e01fSmrg        add = TRUE;
7054642e01fSmrg        mode = PropModeReplace;
7064642e01fSmrg    }
7074642e01fSmrg    prop_value = &prop->value;
7084642e01fSmrg
7094642e01fSmrg    /* To append or prepend to a property the request format and type
710f7df2e56Smrg       must match those of the already defined property.  The
711f7df2e56Smrg       existing format and type are irrelevant when using the mode
712f7df2e56Smrg       "PropModeReplace" since they will be written over. */
7134642e01fSmrg
7144642e01fSmrg    if ((format != prop_value->format) && (mode != PropModeReplace))
7156747b715Smrg        return BadMatch;
7164642e01fSmrg    if ((prop_value->type != type) && (mode != PropModeReplace))
7176747b715Smrg        return BadMatch;
7184642e01fSmrg    new_value = *prop_value;
7194642e01fSmrg    if (mode == PropModeReplace)
7204642e01fSmrg        total_len = len;
7214642e01fSmrg    else
7224642e01fSmrg        total_len = prop_value->size + len;
7234642e01fSmrg
724f7df2e56Smrg    if (mode == PropModeReplace || len > 0) {
725f7df2e56Smrg        void *new_data = NULL, *old_data = NULL;
7264642e01fSmrg
727f7df2e56Smrg        new_value.data = xallocarray(total_len, size_in_bytes);
728f7df2e56Smrg        if (!new_value.data && total_len && size_in_bytes) {
7294642e01fSmrg            if (add)
730f7df2e56Smrg                XIDestroyDeviceProperty(prop);
7314642e01fSmrg            return BadAlloc;
7324642e01fSmrg        }
7334642e01fSmrg        new_value.size = len;
7344642e01fSmrg        new_value.type = type;
7354642e01fSmrg        new_value.format = format;
7364642e01fSmrg
7374642e01fSmrg        switch (mode) {
7384642e01fSmrg        case PropModeReplace:
7394642e01fSmrg            new_data = new_value.data;
7404642e01fSmrg            old_data = NULL;
7414642e01fSmrg            break;
7424642e01fSmrg        case PropModeAppend:
743f7df2e56Smrg            new_data = (void *) (((char *) new_value.data) +
7444642e01fSmrg                                  (prop_value->size * size_in_bytes));
7454642e01fSmrg            old_data = new_value.data;
7464642e01fSmrg            break;
7474642e01fSmrg        case PropModePrepend:
7484642e01fSmrg            new_data = new_value.data;
749f7df2e56Smrg            old_data = (void *) (((char *) new_value.data) +
7504642e01fSmrg                                  (prop_value->size * size_in_bytes));
7514642e01fSmrg            break;
7524642e01fSmrg        }
7534642e01fSmrg        if (new_data)
754f7df2e56Smrg            memcpy((char *) new_data, value, len * size_in_bytes);
7554642e01fSmrg        if (old_data)
756f7df2e56Smrg            memcpy((char *) old_data, (char *) prop_value->data,
757f7df2e56Smrg                   prop_value->size * size_in_bytes);
7584642e01fSmrg
759f7df2e56Smrg        if (dev->properties.handlers) {
7604642e01fSmrg            XIPropertyHandlerPtr handler;
7614642e01fSmrg            BOOL checkonly = TRUE;
762f7df2e56Smrg
7634642e01fSmrg            /* run through all handlers with checkonly TRUE, then again with
7644642e01fSmrg             * checkonly FALSE. Handlers MUST return error codes on the
7654642e01fSmrg             * checkonly run, errors on the second run are ignored */
766f7df2e56Smrg            do {
7674642e01fSmrg                handler = dev->properties.handlers;
768f7df2e56Smrg                while (handler) {
769f7df2e56Smrg                    if (handler->SetProperty) {
7707e31ba66Smrg                        input_lock();
7714642e01fSmrg                        rc = handler->SetProperty(dev, prop->propertyName,
772f7df2e56Smrg                                                  &new_value, checkonly);
7737e31ba66Smrg                        input_unlock();
774f7df2e56Smrg                        if (checkonly && rc != Success) {
7756747b715Smrg                            free(new_value.data);
776f7df2e56Smrg                            if (add)
777f7df2e56Smrg                                XIDestroyDeviceProperty(prop);
7786747b715Smrg                            return rc;
7794642e01fSmrg                        }
7804642e01fSmrg                    }
7814642e01fSmrg                    handler = handler->next;
7824642e01fSmrg                }
7834642e01fSmrg                checkonly = !checkonly;
7844642e01fSmrg            } while (!checkonly);
7854642e01fSmrg        }
7866747b715Smrg        free(prop_value->data);
7874642e01fSmrg        *prop_value = new_value;
788f7df2e56Smrg    }
789f7df2e56Smrg    else if (len == 0) {
7904642e01fSmrg        /* do nothing */
7914642e01fSmrg    }
7924642e01fSmrg
793f7df2e56Smrg    if (add) {
7944642e01fSmrg        prop->next = dev->properties.properties;
7954642e01fSmrg        dev->properties.properties = prop;
7964642e01fSmrg    }
7974642e01fSmrg
7987e31ba66Smrg    if (sendevent) {
7997e31ba66Smrg        UpdateCurrentTimeIf();
8006747b715Smrg        send_property_event(dev, prop->propertyName,
801f7df2e56Smrg                            (add) ? XIPropertyCreated : XIPropertyModified);
8027e31ba66Smrg    }
8036747b715Smrg
8046747b715Smrg    return Success;
8054642e01fSmrg}
8064642e01fSmrg
8074642e01fSmrgint
808f7df2e56SmrgXIGetDeviceProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr *value)
8094642e01fSmrg{
810f7df2e56Smrg    XIPropertyPtr prop = XIFetchDeviceProperty(dev, property);
8114642e01fSmrg    int rc;
8124642e01fSmrg
813f7df2e56Smrg    if (!prop) {
8144642e01fSmrg        *value = NULL;
8154642e01fSmrg        return BadAtom;
8164642e01fSmrg    }
8174642e01fSmrg
8184642e01fSmrg    /* If we can, try to update the property value first */
819f7df2e56Smrg    if (dev->properties.handlers) {
8204642e01fSmrg        XIPropertyHandlerPtr handler = dev->properties.handlers;
821f7df2e56Smrg
822f7df2e56Smrg        while (handler) {
823f7df2e56Smrg            if (handler->GetProperty) {
8244642e01fSmrg                rc = handler->GetProperty(dev, prop->propertyName);
825f7df2e56Smrg                if (rc != Success) {
8264642e01fSmrg                    *value = NULL;
8274642e01fSmrg                    return rc;
8284642e01fSmrg                }
8294642e01fSmrg            }
8304642e01fSmrg            handler = handler->next;
8314642e01fSmrg        }
8324642e01fSmrg    }
8334642e01fSmrg
8344642e01fSmrg    *value = &prop->value;
8354642e01fSmrg    return Success;
8364642e01fSmrg}
8374642e01fSmrg
8384642e01fSmrgint
8394642e01fSmrgXISetDevicePropertyDeletable(DeviceIntPtr dev, Atom property, Bool deletable)
8404642e01fSmrg{
8414642e01fSmrg    XIPropertyPtr prop = XIFetchDeviceProperty(dev, property);
8424642e01fSmrg
8434642e01fSmrg    if (!prop)
8444642e01fSmrg        return BadAtom;
8454642e01fSmrg
8464642e01fSmrg    prop->deletable = deletable;
8474642e01fSmrg    return Success;
8484642e01fSmrg}
8494642e01fSmrg
8504642e01fSmrgint
851f7df2e56SmrgProcXListDeviceProperties(ClientPtr client)
8524642e01fSmrg{
853f7df2e56Smrg    Atom *atoms;
854f7df2e56Smrg    xListDevicePropertiesReply rep;
855f7df2e56Smrg    int natoms;
856f7df2e56Smrg    DeviceIntPtr dev;
857f7df2e56Smrg    int rc = Success;
8584642e01fSmrg
8594642e01fSmrg    REQUEST(xListDevicePropertiesReq);
8604642e01fSmrg    REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
8614642e01fSmrg
862f7df2e56Smrg    rc = dixLookupDevice(&dev, stuff->deviceid, client, DixListPropAccess);
8634642e01fSmrg    if (rc != Success)
8644642e01fSmrg        return rc;
8654642e01fSmrg
8666747b715Smrg    rc = list_atoms(dev, &natoms, &atoms);
8676747b715Smrg    if (rc != Success)
8686747b715Smrg        return rc;
8694642e01fSmrg
870f7df2e56Smrg    rep = (xListDevicePropertiesReply) {
871f7df2e56Smrg        .repType = X_Reply,
872f7df2e56Smrg        .RepType = X_ListDeviceProperties,
873f7df2e56Smrg        .sequenceNumber = client->sequence,
874f7df2e56Smrg        .length = natoms,
875f7df2e56Smrg        .nAtoms = natoms
876f7df2e56Smrg    };
8774642e01fSmrg
8784642e01fSmrg    WriteReplyToClient(client, sizeof(xListDevicePropertiesReply), &rep);
879f7df2e56Smrg    if (natoms) {
880f7df2e56Smrg        client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
8816747b715Smrg        WriteSwappedDataToClient(client, natoms * sizeof(Atom), atoms);
8826747b715Smrg        free(atoms);
8834642e01fSmrg    }
8844642e01fSmrg    return rc;
8854642e01fSmrg}
8864642e01fSmrg
8874642e01fSmrgint
888f7df2e56SmrgProcXChangeDeviceProperty(ClientPtr client)
8894642e01fSmrg{
8904642e01fSmrg    REQUEST(xChangeDevicePropertyReq);
891f7df2e56Smrg    DeviceIntPtr dev;
892f7df2e56Smrg    unsigned long len;
893e383896cSmrg    uint64_t totalSize;
894f7df2e56Smrg    int rc;
8954642e01fSmrg
8964642e01fSmrg    REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq);
8974642e01fSmrg    UpdateCurrentTime();
8984642e01fSmrg
899f7df2e56Smrg    rc = dixLookupDevice(&dev, stuff->deviceid, client, DixSetPropAccess);
9004642e01fSmrg    if (rc != Success)
9014642e01fSmrg        return rc;
9024642e01fSmrg
9036747b715Smrg    rc = check_change_property(client, stuff->property, stuff->type,
9046747b715Smrg                               stuff->format, stuff->mode, stuff->nUnits);
905e383896cSmrg    if (rc != Success)
906e383896cSmrg        return rc;
9074642e01fSmrg
9086747b715Smrg    len = stuff->nUnits;
9096747b715Smrg    if (len > (bytes_to_int32(0xffffffff - sizeof(xChangeDevicePropertyReq))))
9106747b715Smrg        return BadLength;
9114642e01fSmrg
912f7df2e56Smrg    totalSize = len * (stuff->format / 8);
9136747b715Smrg    REQUEST_FIXED_SIZE(xChangeDevicePropertyReq, totalSize);
9146747b715Smrg
9156747b715Smrg    rc = change_property(client, dev, stuff->property, stuff->type,
916f7df2e56Smrg                         stuff->format, stuff->mode, len, (void *) &stuff[1]);
9174642e01fSmrg    return rc;
9184642e01fSmrg}
9194642e01fSmrg
9204642e01fSmrgint
921f7df2e56SmrgProcXDeleteDeviceProperty(ClientPtr client)
9224642e01fSmrg{
9234642e01fSmrg    REQUEST(xDeleteDevicePropertyReq);
924f7df2e56Smrg    DeviceIntPtr dev;
925f7df2e56Smrg    int rc;
9264642e01fSmrg
9274642e01fSmrg    REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
9284642e01fSmrg    UpdateCurrentTime();
929f7df2e56Smrg    rc = dixLookupDevice(&dev, stuff->deviceid, client, DixSetPropAccess);
9304642e01fSmrg    if (rc != Success)
9314642e01fSmrg        return rc;
9324642e01fSmrg
933f7df2e56Smrg    if (!ValidAtom(stuff->property)) {
9344642e01fSmrg        client->errorValue = stuff->property;
9356747b715Smrg        return BadAtom;
9364642e01fSmrg    }
9374642e01fSmrg
9384642e01fSmrg    rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE);
9394642e01fSmrg    return rc;
9404642e01fSmrg}
9414642e01fSmrg
9424642e01fSmrgint
943f7df2e56SmrgProcXGetDeviceProperty(ClientPtr client)
9444642e01fSmrg{
9454642e01fSmrg    REQUEST(xGetDevicePropertyReq);
946f7df2e56Smrg    DeviceIntPtr dev;
947f7df2e56Smrg    int length;
948f7df2e56Smrg    int rc, format, nitems, bytes_after;
949f7df2e56Smrg    char *data;
950f7df2e56Smrg    Atom type;
951f7df2e56Smrg    xGetDevicePropertyReply reply;
9524642e01fSmrg
9534642e01fSmrg    REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
9544642e01fSmrg    if (stuff->delete)
9554642e01fSmrg        UpdateCurrentTime();
956f7df2e56Smrg    rc = dixLookupDevice(&dev, stuff->deviceid, client,
957f7df2e56Smrg                         stuff->delete ? DixSetPropAccess : DixGetPropAccess);
9584642e01fSmrg    if (rc != Success)
9594642e01fSmrg        return rc;
9604642e01fSmrg
9616747b715Smrg    rc = get_property(client, dev, stuff->property, stuff->type,
962f7df2e56Smrg                      stuff->delete, stuff->longOffset, stuff->longLength,
963f7df2e56Smrg                      &bytes_after, &type, &format, &nitems, &length, &data);
9644642e01fSmrg
9656747b715Smrg    if (rc != Success)
9666747b715Smrg        return rc;
9674642e01fSmrg
968f7df2e56Smrg    reply = (xGetDevicePropertyReply) {
969f7df2e56Smrg        .repType = X_Reply,
970f7df2e56Smrg        .RepType = X_GetDeviceProperty,
971f7df2e56Smrg        .sequenceNumber = client->sequence,
972f7df2e56Smrg        .length = bytes_to_int32(length),
973f7df2e56Smrg        .propertyType = type,
974f7df2e56Smrg        .bytesAfter = bytes_after,
975f7df2e56Smrg        .nItems = nitems,
976f7df2e56Smrg        .format = format,
977f7df2e56Smrg        .deviceid = dev->id
978f7df2e56Smrg    };
9794642e01fSmrg
9804642e01fSmrg    if (stuff->delete && (reply.bytesAfter == 0))
9816747b715Smrg        send_property_event(dev, stuff->property, XIPropertyDeleted);
9824642e01fSmrg
9834642e01fSmrg    WriteReplyToClient(client, sizeof(xGenericReply), &reply);
9846747b715Smrg
985f7df2e56Smrg    if (length) {
9864642e01fSmrg        switch (reply.format) {
987f7df2e56Smrg        case 32:
988f7df2e56Smrg            client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
989f7df2e56Smrg            break;
990f7df2e56Smrg        case 16:
991f7df2e56Smrg            client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write;
992f7df2e56Smrg            break;
993f7df2e56Smrg        default:
994f7df2e56Smrg            client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient;
995f7df2e56Smrg            break;
9964642e01fSmrg        }
9976747b715Smrg        WriteSwappedDataToClient(client, length, data);
9984642e01fSmrg    }
9994642e01fSmrg
10006747b715Smrg    /* delete the Property */
1001f7df2e56Smrg    if (stuff->delete && (reply.bytesAfter == 0)) {
10026747b715Smrg        XIPropertyPtr prop, *prev;
1003f7df2e56Smrg
1004f7df2e56Smrg        for (prev = &dev->properties.properties; (prop = *prev);
1005f7df2e56Smrg             prev = &prop->next) {
1006f7df2e56Smrg            if (prop->propertyName == stuff->property) {
10076747b715Smrg                *prev = prop->next;
10086747b715Smrg                XIDestroyDeviceProperty(prop);
10096747b715Smrg                break;
10106747b715Smrg            }
10116747b715Smrg        }
10124642e01fSmrg    }
10136747b715Smrg    return Success;
10144642e01fSmrg}
10154642e01fSmrg
10167e31ba66Smrgint _X_COLD
1017f7df2e56SmrgSProcXListDeviceProperties(ClientPtr client)
10184642e01fSmrg{
10194642e01fSmrg    REQUEST(xListDevicePropertiesReq);
10200b0d8713Smrg    REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
10214642e01fSmrg
1022f7df2e56Smrg    swaps(&stuff->length);
10234642e01fSmrg    return (ProcXListDeviceProperties(client));
10244642e01fSmrg}
10254642e01fSmrg
10267e31ba66Smrgint _X_COLD
1027f7df2e56SmrgSProcXChangeDeviceProperty(ClientPtr client)
10284642e01fSmrg{
10294642e01fSmrg    REQUEST(xChangeDevicePropertyReq);
10304642e01fSmrg
10319ace9065Smrg    REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq);
1032f7df2e56Smrg    swaps(&stuff->length);
1033f7df2e56Smrg    swapl(&stuff->property);
1034f7df2e56Smrg    swapl(&stuff->type);
1035f7df2e56Smrg    swapl(&stuff->nUnits);
10364642e01fSmrg    return (ProcXChangeDeviceProperty(client));
10374642e01fSmrg}
10384642e01fSmrg
10397e31ba66Smrgint _X_COLD
1040f7df2e56SmrgSProcXDeleteDeviceProperty(ClientPtr client)
10414642e01fSmrg{
10424642e01fSmrg    REQUEST(xDeleteDevicePropertyReq);
10430b0d8713Smrg    REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
10444642e01fSmrg
1045f7df2e56Smrg    swaps(&stuff->length);
1046f7df2e56Smrg    swapl(&stuff->property);
10474642e01fSmrg    return (ProcXDeleteDeviceProperty(client));
10484642e01fSmrg}
10494642e01fSmrg
10507e31ba66Smrgint _X_COLD
1051f7df2e56SmrgSProcXGetDeviceProperty(ClientPtr client)
10524642e01fSmrg{
10534642e01fSmrg    REQUEST(xGetDevicePropertyReq);
10540b0d8713Smrg    REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
10554642e01fSmrg
1056f7df2e56Smrg    swaps(&stuff->length);
1057f7df2e56Smrg    swapl(&stuff->property);
1058f7df2e56Smrg    swapl(&stuff->type);
1059f7df2e56Smrg    swapl(&stuff->longOffset);
1060f7df2e56Smrg    swapl(&stuff->longLength);
10614642e01fSmrg    return (ProcXGetDeviceProperty(client));
10624642e01fSmrg}
10634642e01fSmrg
10644642e01fSmrg/* Reply swapping */
10654642e01fSmrg
10667e31ba66Smrgvoid _X_COLD
10674642e01fSmrgSRepXListDeviceProperties(ClientPtr client, int size,
1068f7df2e56Smrg                          xListDevicePropertiesReply * rep)
10694642e01fSmrg{
1070f7df2e56Smrg    swaps(&rep->sequenceNumber);
1071f7df2e56Smrg    swapl(&rep->length);
1072f7df2e56Smrg    swaps(&rep->nAtoms);
10734642e01fSmrg    /* properties will be swapped later, see ProcXListDeviceProperties */
1074f7df2e56Smrg    WriteToClient(client, size, rep);
10754642e01fSmrg}
10764642e01fSmrg
10777e31ba66Smrgvoid _X_COLD
10784642e01fSmrgSRepXGetDeviceProperty(ClientPtr client, int size,
1079f7df2e56Smrg                       xGetDevicePropertyReply * rep)
10804642e01fSmrg{
1081f7df2e56Smrg    swaps(&rep->sequenceNumber);
1082f7df2e56Smrg    swapl(&rep->length);
1083f7df2e56Smrg    swapl(&rep->propertyType);
1084f7df2e56Smrg    swapl(&rep->bytesAfter);
1085f7df2e56Smrg    swapl(&rep->nItems);
10864642e01fSmrg    /* data will be swapped, see ProcXGetDeviceProperty */
1087f7df2e56Smrg    WriteToClient(client, size, rep);
10884642e01fSmrg}
10896747b715Smrg
10906747b715Smrg/* XI2 Request/reply handling */
10916747b715Smrgint
10926747b715SmrgProcXIListProperties(ClientPtr client)
10936747b715Smrg{
1094f7df2e56Smrg    Atom *atoms;
1095f7df2e56Smrg    xXIListPropertiesReply rep;
1096f7df2e56Smrg    int natoms;
1097f7df2e56Smrg    DeviceIntPtr dev;
1098f7df2e56Smrg    int rc = Success;
10996747b715Smrg
11006747b715Smrg    REQUEST(xXIListPropertiesReq);
11016747b715Smrg    REQUEST_SIZE_MATCH(xXIListPropertiesReq);
11026747b715Smrg
1103f7df2e56Smrg    rc = dixLookupDevice(&dev, stuff->deviceid, client, DixListPropAccess);
11046747b715Smrg    if (rc != Success)
11056747b715Smrg        return rc;
11066747b715Smrg
11076747b715Smrg    rc = list_atoms(dev, &natoms, &atoms);
11086747b715Smrg    if (rc != Success)
11096747b715Smrg        return rc;
11106747b715Smrg
1111f7df2e56Smrg    rep = (xXIListPropertiesReply) {
1112f7df2e56Smrg        .repType = X_Reply,
1113f7df2e56Smrg        .RepType = X_XIListProperties,
1114f7df2e56Smrg        .sequenceNumber = client->sequence,
1115f7df2e56Smrg        .length = natoms,
1116f7df2e56Smrg        .num_properties = natoms
1117f7df2e56Smrg    };
11186747b715Smrg
11196747b715Smrg    WriteReplyToClient(client, sizeof(xXIListPropertiesReply), &rep);
1120f7df2e56Smrg    if (natoms) {
1121f7df2e56Smrg        client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
11226747b715Smrg        WriteSwappedDataToClient(client, natoms * sizeof(Atom), atoms);
11236747b715Smrg        free(atoms);
11246747b715Smrg    }
11256747b715Smrg    return rc;
11266747b715Smrg}
11276747b715Smrg
11286747b715Smrgint
11296747b715SmrgProcXIChangeProperty(ClientPtr client)
11306747b715Smrg{
1131f7df2e56Smrg    int rc;
1132f7df2e56Smrg    DeviceIntPtr dev;
1133e383896cSmrg    uint64_t totalSize;
1134f7df2e56Smrg    unsigned long len;
11356747b715Smrg
11366747b715Smrg    REQUEST(xXIChangePropertyReq);
11376747b715Smrg    REQUEST_AT_LEAST_SIZE(xXIChangePropertyReq);
11386747b715Smrg    UpdateCurrentTime();
11396747b715Smrg
1140f7df2e56Smrg    rc = dixLookupDevice(&dev, stuff->deviceid, client, DixSetPropAccess);
11416747b715Smrg    if (rc != Success)
11426747b715Smrg        return rc;
11436747b715Smrg
11446747b715Smrg    rc = check_change_property(client, stuff->property, stuff->type,
11456747b715Smrg                               stuff->format, stuff->mode, stuff->num_items);
1146e383896cSmrg    if (rc != Success)
1147e383896cSmrg        return rc;
1148e383896cSmrg
11496747b715Smrg    len = stuff->num_items;
11506747b715Smrg    if (len > bytes_to_int32(0xffffffff - sizeof(xXIChangePropertyReq)))
11516747b715Smrg        return BadLength;
11526747b715Smrg
1153f7df2e56Smrg    totalSize = len * (stuff->format / 8);
11546747b715Smrg    REQUEST_FIXED_SIZE(xXIChangePropertyReq, totalSize);
11556747b715Smrg
11566747b715Smrg    rc = change_property(client, dev, stuff->property, stuff->type,
1157f7df2e56Smrg                         stuff->format, stuff->mode, len, (void *) &stuff[1]);
11586747b715Smrg    return rc;
11596747b715Smrg}
11606747b715Smrg
11616747b715Smrgint
11626747b715SmrgProcXIDeleteProperty(ClientPtr client)
11636747b715Smrg{
1164f7df2e56Smrg    DeviceIntPtr dev;
1165f7df2e56Smrg    int rc;
1166f7df2e56Smrg
11676747b715Smrg    REQUEST(xXIDeletePropertyReq);
11686747b715Smrg
11696747b715Smrg    REQUEST_SIZE_MATCH(xXIDeletePropertyReq);
11706747b715Smrg    UpdateCurrentTime();
1171f7df2e56Smrg    rc = dixLookupDevice(&dev, stuff->deviceid, client, DixSetPropAccess);
11726747b715Smrg    if (rc != Success)
11736747b715Smrg        return rc;
11746747b715Smrg
1175f7df2e56Smrg    if (!ValidAtom(stuff->property)) {
11766747b715Smrg        client->errorValue = stuff->property;
11776747b715Smrg        return BadAtom;
11786747b715Smrg    }
11796747b715Smrg
11806747b715Smrg    rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE);
11816747b715Smrg    return rc;
11826747b715Smrg}
11836747b715Smrg
11846747b715Smrgint
11856747b715SmrgProcXIGetProperty(ClientPtr client)
11866747b715Smrg{
11876747b715Smrg    REQUEST(xXIGetPropertyReq);
1188f7df2e56Smrg    DeviceIntPtr dev;
1189f7df2e56Smrg    xXIGetPropertyReply reply;
1190f7df2e56Smrg    int length;
1191f7df2e56Smrg    int rc, format, nitems, bytes_after;
1192f7df2e56Smrg    char *data;
1193f7df2e56Smrg    Atom type;
11946747b715Smrg
11956747b715Smrg    REQUEST_SIZE_MATCH(xXIGetPropertyReq);
11966747b715Smrg    if (stuff->delete)
11976747b715Smrg        UpdateCurrentTime();
1198f7df2e56Smrg    rc = dixLookupDevice(&dev, stuff->deviceid, client,
1199f7df2e56Smrg                         stuff->delete ? DixSetPropAccess : DixGetPropAccess);
12006747b715Smrg    if (rc != Success)
12016747b715Smrg        return rc;
12026747b715Smrg
12036747b715Smrg    rc = get_property(client, dev, stuff->property, stuff->type,
1204f7df2e56Smrg                      stuff->delete, stuff->offset, stuff->len,
1205f7df2e56Smrg                      &bytes_after, &type, &format, &nitems, &length, &data);
12066747b715Smrg
12076747b715Smrg    if (rc != Success)
12086747b715Smrg        return rc;
12096747b715Smrg
1210f7df2e56Smrg    reply = (xXIGetPropertyReply) {
1211f7df2e56Smrg        .repType = X_Reply,
1212f7df2e56Smrg        .RepType = X_XIGetProperty,
1213f7df2e56Smrg        .sequenceNumber = client->sequence,
1214f7df2e56Smrg        .length = bytes_to_int32(length),
1215f7df2e56Smrg        .type = type,
1216f7df2e56Smrg        .bytes_after = bytes_after,
1217f7df2e56Smrg        .num_items = nitems,
1218f7df2e56Smrg        .format = format
1219f7df2e56Smrg    };
12206747b715Smrg
12216747b715Smrg    if (length && stuff->delete && (reply.bytes_after == 0))
12226747b715Smrg        send_property_event(dev, stuff->property, XIPropertyDeleted);
12236747b715Smrg
12246747b715Smrg    WriteReplyToClient(client, sizeof(xXIGetPropertyReply), &reply);
12256747b715Smrg
1226f7df2e56Smrg    if (length) {
12276747b715Smrg        switch (reply.format) {
1228f7df2e56Smrg        case 32:
1229f7df2e56Smrg            client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
1230f7df2e56Smrg            break;
1231f7df2e56Smrg        case 16:
1232f7df2e56Smrg            client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write;
1233f7df2e56Smrg            break;
1234f7df2e56Smrg        default:
1235f7df2e56Smrg            client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient;
1236f7df2e56Smrg            break;
12376747b715Smrg        }
12386747b715Smrg        WriteSwappedDataToClient(client, length, data);
12396747b715Smrg    }
12406747b715Smrg
12416747b715Smrg    /* delete the Property */
1242f7df2e56Smrg    if (stuff->delete && (reply.bytes_after == 0)) {
12436747b715Smrg        XIPropertyPtr prop, *prev;
1244f7df2e56Smrg
1245f7df2e56Smrg        for (prev = &dev->properties.properties; (prop = *prev);
1246f7df2e56Smrg             prev = &prop->next) {
1247f7df2e56Smrg            if (prop->propertyName == stuff->property) {
12486747b715Smrg                *prev = prop->next;
12496747b715Smrg                XIDestroyDeviceProperty(prop);
12506747b715Smrg                break;
12516747b715Smrg            }
12526747b715Smrg        }
12536747b715Smrg    }
12546747b715Smrg
12556747b715Smrg    return Success;
12566747b715Smrg}
12576747b715Smrg
12587e31ba66Smrgint _X_COLD
12596747b715SmrgSProcXIListProperties(ClientPtr client)
12606747b715Smrg{
12616747b715Smrg    REQUEST(xXIListPropertiesReq);
12620b0d8713Smrg    REQUEST_SIZE_MATCH(xXIListPropertiesReq);
12636747b715Smrg
1264f7df2e56Smrg    swaps(&stuff->length);
1265f7df2e56Smrg    swaps(&stuff->deviceid);
12666747b715Smrg    return (ProcXIListProperties(client));
12676747b715Smrg}
12686747b715Smrg
12697e31ba66Smrgint _X_COLD
12706747b715SmrgSProcXIChangeProperty(ClientPtr client)
12716747b715Smrg{
12726747b715Smrg    REQUEST(xXIChangePropertyReq);
12736747b715Smrg
12749ace9065Smrg    REQUEST_AT_LEAST_SIZE(xXIChangePropertyReq);
1275f7df2e56Smrg    swaps(&stuff->length);
1276f7df2e56Smrg    swaps(&stuff->deviceid);
1277f7df2e56Smrg    swapl(&stuff->property);
1278f7df2e56Smrg    swapl(&stuff->type);
1279f7df2e56Smrg    swapl(&stuff->num_items);
12806747b715Smrg    return (ProcXIChangeProperty(client));
12816747b715Smrg}
12826747b715Smrg
12837e31ba66Smrgint _X_COLD
12846747b715SmrgSProcXIDeleteProperty(ClientPtr client)
12856747b715Smrg{
12866747b715Smrg    REQUEST(xXIDeletePropertyReq);
12870b0d8713Smrg    REQUEST_SIZE_MATCH(xXIDeletePropertyReq);
12886747b715Smrg
1289f7df2e56Smrg    swaps(&stuff->length);
1290f7df2e56Smrg    swaps(&stuff->deviceid);
1291f7df2e56Smrg    swapl(&stuff->property);
12926747b715Smrg    return (ProcXIDeleteProperty(client));
12936747b715Smrg}
12946747b715Smrg
12957e31ba66Smrgint _X_COLD
12966747b715SmrgSProcXIGetProperty(ClientPtr client)
12976747b715Smrg{
12986747b715Smrg    REQUEST(xXIGetPropertyReq);
12990b0d8713Smrg    REQUEST_SIZE_MATCH(xXIGetPropertyReq);
13006747b715Smrg
1301f7df2e56Smrg    swaps(&stuff->length);
1302f7df2e56Smrg    swaps(&stuff->deviceid);
1303f7df2e56Smrg    swapl(&stuff->property);
1304f7df2e56Smrg    swapl(&stuff->type);
1305f7df2e56Smrg    swapl(&stuff->offset);
1306f7df2e56Smrg    swapl(&stuff->len);
13076747b715Smrg    return (ProcXIGetProperty(client));
13086747b715Smrg}
13096747b715Smrg
13107e31ba66Smrgvoid _X_COLD
1311f7df2e56SmrgSRepXIListProperties(ClientPtr client, int size, xXIListPropertiesReply * rep)
13126747b715Smrg{
1313f7df2e56Smrg    swaps(&rep->sequenceNumber);
1314f7df2e56Smrg    swapl(&rep->length);
1315f7df2e56Smrg    swaps(&rep->num_properties);
13166747b715Smrg    /* properties will be swapped later, see ProcXIListProperties */
1317f7df2e56Smrg    WriteToClient(client, size, rep);
13186747b715Smrg}
13196747b715Smrg
13207e31ba66Smrgvoid _X_COLD
1321f7df2e56SmrgSRepXIGetProperty(ClientPtr client, int size, xXIGetPropertyReply * rep)
13226747b715Smrg{
1323f7df2e56Smrg    swaps(&rep->sequenceNumber);
1324f7df2e56Smrg    swapl(&rep->length);
1325f7df2e56Smrg    swapl(&rep->type);
1326f7df2e56Smrg    swapl(&rep->bytes_after);
1327f7df2e56Smrg    swapl(&rep->num_items);
13286747b715Smrg    /* data will be swapped, see ProcXIGetProperty */
1329f7df2e56Smrg    WriteToClient(client, size, rep);
13306747b715Smrg}
1331