xiproperty.c revision 0b0d8713
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 */
484642e01fSmrgstatic struct dev_properties
494642e01fSmrg{
504642e01fSmrg    Atom type;
514642e01fSmrg    char *name;
524642e01fSmrg} dev_properties[] = {
534642e01fSmrg    {0, XI_PROP_ENABLED},
546747b715Smrg    {0, XI_PROP_XTEST_DEVICE},
556747b715Smrg    {0, XATOM_FLOAT},
566747b715Smrg    {0, ACCEL_PROP_PROFILE_NUMBER},
576747b715Smrg    {0, ACCEL_PROP_CONSTANT_DECELERATION},
586747b715Smrg    {0, ACCEL_PROP_ADAPTIVE_DECELERATION},
596747b715Smrg    {0, ACCEL_PROP_VELOCITY_SCALING},
606747b715Smrg    {0, AXIS_LABEL_PROP},
616747b715Smrg    {0, AXIS_LABEL_PROP_REL_X},
626747b715Smrg    {0, AXIS_LABEL_PROP_REL_Y},
636747b715Smrg    {0, AXIS_LABEL_PROP_REL_Z},
646747b715Smrg    {0, AXIS_LABEL_PROP_REL_RX},
656747b715Smrg    {0, AXIS_LABEL_PROP_REL_RY},
666747b715Smrg    {0, AXIS_LABEL_PROP_REL_RZ},
676747b715Smrg    {0, AXIS_LABEL_PROP_REL_HWHEEL},
686747b715Smrg    {0, AXIS_LABEL_PROP_REL_DIAL},
696747b715Smrg    {0, AXIS_LABEL_PROP_REL_WHEEL},
706747b715Smrg    {0, AXIS_LABEL_PROP_REL_MISC},
716747b715Smrg    {0, AXIS_LABEL_PROP_ABS_X},
726747b715Smrg    {0, AXIS_LABEL_PROP_ABS_Y},
736747b715Smrg    {0, AXIS_LABEL_PROP_ABS_Z},
746747b715Smrg    {0, AXIS_LABEL_PROP_ABS_RX},
756747b715Smrg    {0, AXIS_LABEL_PROP_ABS_RY},
766747b715Smrg    {0, AXIS_LABEL_PROP_ABS_RZ},
776747b715Smrg    {0, AXIS_LABEL_PROP_ABS_THROTTLE},
786747b715Smrg    {0, AXIS_LABEL_PROP_ABS_RUDDER},
796747b715Smrg    {0, AXIS_LABEL_PROP_ABS_WHEEL},
806747b715Smrg    {0, AXIS_LABEL_PROP_ABS_GAS},
816747b715Smrg    {0, AXIS_LABEL_PROP_ABS_BRAKE},
826747b715Smrg    {0, AXIS_LABEL_PROP_ABS_HAT0X},
836747b715Smrg    {0, AXIS_LABEL_PROP_ABS_HAT0Y},
846747b715Smrg    {0, AXIS_LABEL_PROP_ABS_HAT1X},
856747b715Smrg    {0, AXIS_LABEL_PROP_ABS_HAT1Y},
866747b715Smrg    {0, AXIS_LABEL_PROP_ABS_HAT2X},
876747b715Smrg    {0, AXIS_LABEL_PROP_ABS_HAT2Y},
886747b715Smrg    {0, AXIS_LABEL_PROP_ABS_HAT3X},
896747b715Smrg    {0, AXIS_LABEL_PROP_ABS_HAT3Y},
906747b715Smrg    {0, AXIS_LABEL_PROP_ABS_PRESSURE},
916747b715Smrg    {0, AXIS_LABEL_PROP_ABS_DISTANCE},
926747b715Smrg    {0, AXIS_LABEL_PROP_ABS_TILT_X},
936747b715Smrg    {0, AXIS_LABEL_PROP_ABS_TILT_Y},
946747b715Smrg    {0, AXIS_LABEL_PROP_ABS_TOOL_WIDTH},
956747b715Smrg    {0, AXIS_LABEL_PROP_ABS_VOLUME},
966747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR},
976747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR},
986747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_WIDTH_MAJOR},
996747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_WIDTH_MINOR},
1006747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_ORIENTATION},
1016747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_POSITION_X},
1026747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_POSITION_Y},
1036747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_TOOL_TYPE},
1046747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_BLOB_ID},
1056747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_TRACKING_ID},
1066747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MT_PRESSURE},
1076747b715Smrg    {0, AXIS_LABEL_PROP_ABS_MISC},
1086747b715Smrg
1096747b715Smrg    {0, BTN_LABEL_PROP},
1106747b715Smrg    {0, BTN_LABEL_PROP_BTN_UNKNOWN},
1116747b715Smrg    {0, BTN_LABEL_PROP_BTN_WHEEL_UP},
1126747b715Smrg    {0, BTN_LABEL_PROP_BTN_WHEEL_DOWN},
1136747b715Smrg    {0, BTN_LABEL_PROP_BTN_HWHEEL_LEFT},
1146747b715Smrg    {0, BTN_LABEL_PROP_BTN_HWHEEL_RIGHT},
1156747b715Smrg    {0, BTN_LABEL_PROP_BTN_0},
1166747b715Smrg    {0, BTN_LABEL_PROP_BTN_1},
1176747b715Smrg    {0, BTN_LABEL_PROP_BTN_2},
1186747b715Smrg    {0, BTN_LABEL_PROP_BTN_3},
1196747b715Smrg    {0, BTN_LABEL_PROP_BTN_4},
1206747b715Smrg    {0, BTN_LABEL_PROP_BTN_5},
1216747b715Smrg    {0, BTN_LABEL_PROP_BTN_6},
1226747b715Smrg    {0, BTN_LABEL_PROP_BTN_7},
1236747b715Smrg    {0, BTN_LABEL_PROP_BTN_8},
1246747b715Smrg    {0, BTN_LABEL_PROP_BTN_9},
1256747b715Smrg
1266747b715Smrg    {0, BTN_LABEL_PROP_BTN_LEFT},
1276747b715Smrg    {0, BTN_LABEL_PROP_BTN_RIGHT},
1286747b715Smrg    {0, BTN_LABEL_PROP_BTN_MIDDLE},
1296747b715Smrg    {0, BTN_LABEL_PROP_BTN_SIDE},
1306747b715Smrg    {0, BTN_LABEL_PROP_BTN_EXTRA},
1316747b715Smrg    {0, BTN_LABEL_PROP_BTN_FORWARD},
1326747b715Smrg    {0, BTN_LABEL_PROP_BTN_BACK},
1336747b715Smrg    {0, BTN_LABEL_PROP_BTN_TASK},
1346747b715Smrg
1356747b715Smrg    {0, BTN_LABEL_PROP_BTN_TRIGGER},
1366747b715Smrg    {0, BTN_LABEL_PROP_BTN_THUMB},
1376747b715Smrg    {0, BTN_LABEL_PROP_BTN_THUMB2},
1386747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOP},
1396747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOP2},
1406747b715Smrg    {0, BTN_LABEL_PROP_BTN_PINKIE},
1416747b715Smrg    {0, BTN_LABEL_PROP_BTN_BASE},
1426747b715Smrg    {0, BTN_LABEL_PROP_BTN_BASE2},
1436747b715Smrg    {0, BTN_LABEL_PROP_BTN_BASE3},
1446747b715Smrg    {0, BTN_LABEL_PROP_BTN_BASE4},
1456747b715Smrg    {0, BTN_LABEL_PROP_BTN_BASE5},
1466747b715Smrg    {0, BTN_LABEL_PROP_BTN_BASE6},
1476747b715Smrg    {0, BTN_LABEL_PROP_BTN_DEAD},
1486747b715Smrg
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
1656747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOOL_PEN},
1666747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOOL_RUBBER},
1676747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOOL_BRUSH},
1686747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOOL_PENCIL},
1696747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOOL_AIRBRUSH},
1706747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOOL_FINGER},
1716747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOOL_MOUSE},
1726747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOOL_LENS},
1736747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOUCH},
1746747b715Smrg    {0, BTN_LABEL_PROP_BTN_STYLUS},
1756747b715Smrg    {0, BTN_LABEL_PROP_BTN_STYLUS2},
1766747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOOL_DOUBLETAP},
1776747b715Smrg    {0, BTN_LABEL_PROP_BTN_TOOL_TRIPLETAP},
1786747b715Smrg
1796747b715Smrg    {0, BTN_LABEL_PROP_BTN_GEAR_DOWN},
1806747b715Smrg    {0, BTN_LABEL_PROP_BTN_GEAR_UP},
1816747b715Smrg
1826747b715Smrg    {0, XI_PROP_TRANSFORM}
1834642e01fSmrg};
1844642e01fSmrg
1854642e01fSmrgstatic long XIPropHandlerID = 1;
1864642e01fSmrg
1876747b715Smrgstatic void send_property_event(DeviceIntPtr dev, Atom property, int what)
1886747b715Smrg{
1896747b715Smrg        devicePropertyNotify    event;
1906747b715Smrg        xXIPropertyEvent        xi2;
1916747b715Smrg        int state;
1926747b715Smrg
1936747b715Smrg        if (what == XIPropertyDeleted)
1946747b715Smrg            state = PropertyDelete;
1956747b715Smrg        else
1966747b715Smrg            state = PropertyNewValue;
1976747b715Smrg
1986747b715Smrg        event.type      = DevicePropertyNotify;
1996747b715Smrg        event.deviceid  = dev->id;
2006747b715Smrg        event.state     = state;
2016747b715Smrg        event.atom      = property;
2026747b715Smrg        event.time      = currentTime.milliseconds;
2036747b715Smrg        SendEventToAllWindows(dev, DevicePropertyNotifyMask,
2046747b715Smrg                              (xEvent*)&event, 1);
2056747b715Smrg
2066747b715Smrg        xi2.type        = GenericEvent;
2076747b715Smrg        xi2.extension   = IReqCode;
2086747b715Smrg        xi2.length      = 0;
2096747b715Smrg        xi2.evtype      = XI_PropertyEvent;
2106747b715Smrg        xi2.deviceid    = dev->id;
2116747b715Smrg        xi2.time        = currentTime.milliseconds;
2126747b715Smrg        xi2.property    = property;
2136747b715Smrg        xi2.what        = what;
2146747b715Smrg        SendEventToAllWindows(dev, GetEventFilter(dev, (xEvent*)&xi2),
2156747b715Smrg                              (xEvent*)&xi2, 1);
2166747b715Smrg}
2176747b715Smrg
2186747b715Smrgstatic int list_atoms(DeviceIntPtr dev, int *natoms, Atom **atoms_return)
2196747b715Smrg{
2206747b715Smrg    XIPropertyPtr prop;
2216747b715Smrg    Atom *atoms         = NULL;
2226747b715Smrg    int nprops          = 0;
2236747b715Smrg
2246747b715Smrg    for (prop = dev->properties.properties; prop; prop = prop->next)
2256747b715Smrg        nprops++;
2266747b715Smrg    if (nprops)
2276747b715Smrg    {
2286747b715Smrg        Atom *a;
2296747b715Smrg
2306747b715Smrg        atoms = malloc(nprops * sizeof(Atom));
2316747b715Smrg        if(!atoms)
2326747b715Smrg            return BadAlloc;
2336747b715Smrg        a = atoms;
2346747b715Smrg        for (prop = dev->properties.properties; prop; prop = prop->next, a++)
2356747b715Smrg            *a = prop->propertyName;
2366747b715Smrg    }
2376747b715Smrg
2386747b715Smrg    *natoms = nprops;
2396747b715Smrg    *atoms_return = atoms;
2406747b715Smrg    return Success;
2416747b715Smrg}
2426747b715Smrg
2436747b715Smrgstatic int
2446747b715Smrgget_property(ClientPtr client, DeviceIntPtr dev, Atom property, Atom type,
2456747b715Smrg             BOOL delete, int offset, int length,
2466747b715Smrg             int *bytes_after, Atom *type_return, int *format, int *nitems,
2476747b715Smrg             int *length_return, char **data)
2486747b715Smrg{
2496747b715Smrg    unsigned long n, len, ind;
2506747b715Smrg    int rc;
2516747b715Smrg    XIPropertyPtr prop;
2526747b715Smrg    XIPropertyValuePtr prop_value;
2536747b715Smrg
2546747b715Smrg    if (!ValidAtom(property))
2556747b715Smrg    {
2566747b715Smrg        client->errorValue = property;
2576747b715Smrg        return BadAtom;
2586747b715Smrg    }
2596747b715Smrg    if ((delete != xTrue) && (delete != xFalse))
2606747b715Smrg    {
2616747b715Smrg        client->errorValue = delete;
2626747b715Smrg        return BadValue;
2636747b715Smrg    }
2646747b715Smrg
2656747b715Smrg    if ((type != AnyPropertyType) && !ValidAtom(type))
2666747b715Smrg    {
2676747b715Smrg        client->errorValue = type;
2686747b715Smrg        return BadAtom;
2696747b715Smrg    }
2706747b715Smrg
2716747b715Smrg    for (prop = dev->properties.properties; prop; prop = prop->next)
2726747b715Smrg        if (prop->propertyName == property)
2736747b715Smrg            break;
2746747b715Smrg
2756747b715Smrg    if (!prop)
2766747b715Smrg    {
2776747b715Smrg        *bytes_after = 0;
2786747b715Smrg        *type_return = None;
2796747b715Smrg        *format = 0;
2806747b715Smrg        *nitems = 0;
2816747b715Smrg        *length_return = 0;
2826747b715Smrg        return Success;
2836747b715Smrg    }
2846747b715Smrg
2856747b715Smrg    rc = XIGetDeviceProperty(dev, property, &prop_value);
2866747b715Smrg    if (rc != Success)
2876747b715Smrg    {
2886747b715Smrg        client->errorValue = property;
2896747b715Smrg        return rc;
2906747b715Smrg    }
2916747b715Smrg
2926747b715Smrg    /* If the request type and actual type don't match. Return the
2936747b715Smrg    property information, but not the data. */
2946747b715Smrg
2956747b715Smrg    if (((type != prop_value->type) && (type != AnyPropertyType)))
2966747b715Smrg    {
2976747b715Smrg        *bytes_after = prop_value->size;
2986747b715Smrg        *format = prop_value->format;
2996747b715Smrg        *length_return = 0;
3006747b715Smrg        *nitems = 0;
3016747b715Smrg        *type_return = prop_value->type;
3026747b715Smrg        return Success;
3036747b715Smrg    }
3046747b715Smrg
3056747b715Smrg    /* Return type, format, value to client */
3066747b715Smrg    n = (prop_value->format/8) * prop_value->size; /* size (bytes) of prop */
3076747b715Smrg    ind = offset << 2;
3086747b715Smrg
3096747b715Smrg   /* If offset is invalid such that it causes "len" to
3106747b715Smrg            be negative, it's a value error. */
3116747b715Smrg
3126747b715Smrg    if (n < ind)
3136747b715Smrg    {
3146747b715Smrg        client->errorValue = offset;
3156747b715Smrg        return BadValue;
3166747b715Smrg    }
3176747b715Smrg
3186747b715Smrg    len = min(n - ind, 4 * length);
3196747b715Smrg
3206747b715Smrg    *bytes_after = n - (ind + len);
3216747b715Smrg    *format = prop_value->format;
3226747b715Smrg    *length_return = len;
3236747b715Smrg    if (prop_value->format)
3246747b715Smrg        *nitems = len / (prop_value->format / 8);
3256747b715Smrg    else
3266747b715Smrg        *nitems = 0;
3276747b715Smrg    *type_return = prop_value->type;
3286747b715Smrg
3296747b715Smrg    *data = (char*)prop_value->data + ind;
3306747b715Smrg
3316747b715Smrg    return Success;
3326747b715Smrg}
3336747b715Smrg
3346747b715Smrgstatic int
3356747b715Smrgcheck_change_property(ClientPtr client, Atom property, Atom type, int format,
3366747b715Smrg                      int mode, int nitems)
3376747b715Smrg{
3386747b715Smrg    if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
3396747b715Smrg        (mode != PropModePrepend))
3406747b715Smrg    {
3416747b715Smrg        client->errorValue = mode;
3426747b715Smrg        return BadValue;
3436747b715Smrg    }
3446747b715Smrg    if ((format != 8) && (format != 16) && (format != 32))
3456747b715Smrg    {
3466747b715Smrg        client->errorValue = format;
3476747b715Smrg        return BadValue;
3486747b715Smrg    }
3496747b715Smrg
3506747b715Smrg    if (!ValidAtom(property))
3516747b715Smrg    {
3526747b715Smrg        client->errorValue = property;
3536747b715Smrg        return BadAtom;
3546747b715Smrg    }
3556747b715Smrg    if (!ValidAtom(type))
3566747b715Smrg    {
3576747b715Smrg        client->errorValue = type;
3586747b715Smrg        return BadAtom;
3596747b715Smrg    }
3606747b715Smrg
3616747b715Smrg    return Success;
3626747b715Smrg}
3636747b715Smrg
3646747b715Smrgstatic int
3656747b715Smrgchange_property(ClientPtr client, DeviceIntPtr dev, Atom property, Atom type,
3666747b715Smrg                int format, int mode, int len, void *data)
3676747b715Smrg{
3686747b715Smrg    int rc = Success;
3696747b715Smrg
3706747b715Smrg    rc = XIChangeDeviceProperty(dev, property, type, format, mode, len, data, TRUE);
3716747b715Smrg    if (rc != Success)
3726747b715Smrg        client->errorValue = property;
3736747b715Smrg
3746747b715Smrg    return rc;
3756747b715Smrg}
3766747b715Smrg
3774642e01fSmrg/**
3786747b715Smrg * Return the atom assigned to the specified string or 0 if the atom isn't known
3794642e01fSmrg * to the DIX.
3804642e01fSmrg *
3814642e01fSmrg * If name is NULL, None is returned.
3824642e01fSmrg */
3836747b715SmrgAtom
3844642e01fSmrgXIGetKnownProperty(char *name)
3854642e01fSmrg{
3864642e01fSmrg    int i;
3874642e01fSmrg
3884642e01fSmrg    if (!name)
3894642e01fSmrg        return None;
3904642e01fSmrg
3914642e01fSmrg    for (i = 0; i < (sizeof(dev_properties)/sizeof(struct dev_properties)); i++)
3924642e01fSmrg    {
3936747b715Smrg        if (strcmp(name, dev_properties[i].name) == 0){
3946747b715Smrg            if (dev_properties[i].type == None){
3956747b715Smrg		dev_properties[i].type =
3966747b715Smrg			    MakeAtom(dev_properties[i].name,
3976747b715Smrg			             strlen(dev_properties[i].name),
3986747b715Smrg			             TRUE);
3996747b715Smrg            }
4006747b715Smrg
4014642e01fSmrg            return dev_properties[i].type;
4026747b715Smrg        }
4034642e01fSmrg    }
4044642e01fSmrg
4054642e01fSmrg    return 0;
4064642e01fSmrg}
4074642e01fSmrg
4086747b715Smrgvoid
4096747b715SmrgXIResetProperties(void)
4106747b715Smrg{
4116747b715Smrg    int i;
4126747b715Smrg
4136747b715Smrg    for (i = 0; i < (sizeof(dev_properties)/sizeof(struct dev_properties)); i++)
4146747b715Smrg        dev_properties[i].type = None;
4156747b715Smrg}
4166747b715Smrg
4174642e01fSmrg/**
4184642e01fSmrg * Convert the given property's value(s) into @nelem_return integer values and
4194642e01fSmrg * store them in @buf_return. If @nelem_return is larger than the number of
4204642e01fSmrg * values in the property, @nelem_return is set to the number of values in the
4214642e01fSmrg * property.
4224642e01fSmrg *
4234642e01fSmrg * If *@buf_return is NULL and @nelem_return is 0, memory is allocated
4244642e01fSmrg * automatically and must be freed by the caller.
4254642e01fSmrg *
4264642e01fSmrg * Possible return codes.
4274642e01fSmrg * Success ... No error.
4284642e01fSmrg * BadMatch ... Wrong atom type, atom is not XA_INTEGER
4294642e01fSmrg * BadAlloc ... NULL passed as buffer and allocation failed.
4304642e01fSmrg * BadLength ... @buff is NULL but @nelem_return is non-zero.
4314642e01fSmrg *
4324642e01fSmrg * @param val The property value
4334642e01fSmrg * @param nelem_return The maximum number of elements to return.
4344642e01fSmrg * @param buf_return Pointer to an array of at least @nelem_return values.
4354642e01fSmrg * @return Success or the error code if an error occured.
4364642e01fSmrg */
4374642e01fSmrg_X_EXPORT int
4384642e01fSmrgXIPropToInt(XIPropertyValuePtr val, int *nelem_return, int **buf_return)
4394642e01fSmrg{
4404642e01fSmrg    int i;
4414642e01fSmrg    int *buf;
4424642e01fSmrg
4434642e01fSmrg    if (val->type != XA_INTEGER)
4444642e01fSmrg        return BadMatch;
4454642e01fSmrg    if (!*buf_return && *nelem_return)
4464642e01fSmrg        return BadLength;
4474642e01fSmrg
4484642e01fSmrg    switch(val->format)
4494642e01fSmrg    {
4504642e01fSmrg        case 8:
4514642e01fSmrg        case 16:
4524642e01fSmrg        case 32:
4534642e01fSmrg            break;
4544642e01fSmrg        default:
4554642e01fSmrg            return BadValue;
4564642e01fSmrg    }
4574642e01fSmrg
4584642e01fSmrg    buf = *buf_return;
4594642e01fSmrg
4604642e01fSmrg    if (!buf && !(*nelem_return))
4614642e01fSmrg    {
4626747b715Smrg        buf = calloc(val->size, sizeof(int));
4634642e01fSmrg        if (!buf)
4644642e01fSmrg            return BadAlloc;
4654642e01fSmrg        *buf_return = buf;
4664642e01fSmrg        *nelem_return = val->size;
4674642e01fSmrg    } else if (val->size < *nelem_return)
4684642e01fSmrg        *nelem_return = val->size;
4694642e01fSmrg
4704642e01fSmrg    for (i = 0; i < val->size && i < *nelem_return; i++)
4714642e01fSmrg    {
4724642e01fSmrg        switch(val->format)
4734642e01fSmrg        {
4744642e01fSmrg            case 8:  buf[i] = ((CARD8*)val->data)[i]; break;
4754642e01fSmrg            case 16: buf[i] = ((CARD16*)val->data)[i]; break;
4764642e01fSmrg            case 32: buf[i] = ((CARD32*)val->data)[i]; break;
4774642e01fSmrg        }
4784642e01fSmrg    }
4794642e01fSmrg
4804642e01fSmrg    return Success;
4814642e01fSmrg}
4824642e01fSmrg
4834642e01fSmrg/**
4844642e01fSmrg * Convert the given property's value(s) into @nelem_return float values and
4854642e01fSmrg * store them in @buf_return. If @nelem_return is larger than the number of
4864642e01fSmrg * values in the property, @nelem_return is set to the number of values in the
4874642e01fSmrg * property.
4884642e01fSmrg *
4894642e01fSmrg * If *@buf_return is NULL and @nelem_return is 0, memory is allocated
4904642e01fSmrg * automatically and must be freed by the caller.
4914642e01fSmrg *
4924642e01fSmrg * Possible errors returned:
4934642e01fSmrg * Success
4944642e01fSmrg * BadMatch ... Wrong atom type, atom is not XA_FLOAT
4954642e01fSmrg * BadValue ... Wrong format, format is not 32
4964642e01fSmrg * BadAlloc ... NULL passed as buffer and allocation failed.
4974642e01fSmrg * BadLength ... @buff is NULL but @nelem_return is non-zero.
4984642e01fSmrg *
4994642e01fSmrg * @param val The property value
5004642e01fSmrg * @param nelem_return The maximum number of elements to return.
5014642e01fSmrg * @param buf_return Pointer to an array of at least @nelem_return values.
5024642e01fSmrg * @return Success or the error code if an error occured.
5034642e01fSmrg */
5044642e01fSmrg_X_EXPORT int
5054642e01fSmrgXIPropToFloat(XIPropertyValuePtr val, int *nelem_return, float **buf_return)
5064642e01fSmrg{
5074642e01fSmrg    int i;
5084642e01fSmrg    float *buf;
5094642e01fSmrg
5104642e01fSmrg    if (!val->type || val->type != XIGetKnownProperty(XATOM_FLOAT))
5114642e01fSmrg        return BadMatch;
5124642e01fSmrg
5134642e01fSmrg    if (val->format != 32)
5144642e01fSmrg        return BadValue;
5154642e01fSmrg    if (!*buf_return && *nelem_return)
5164642e01fSmrg        return BadLength;
5174642e01fSmrg
5184642e01fSmrg    buf = *buf_return;
5194642e01fSmrg
5204642e01fSmrg    if (!buf && !(*nelem_return))
5214642e01fSmrg    {
5226747b715Smrg        buf = calloc(val->size, sizeof(float));
5234642e01fSmrg        if (!buf)
5244642e01fSmrg            return BadAlloc;
5254642e01fSmrg        *buf_return = buf;
5264642e01fSmrg        *nelem_return = val->size;
5274642e01fSmrg    } else if (val->size < *nelem_return)
5284642e01fSmrg        *nelem_return = val->size;
5294642e01fSmrg
5304642e01fSmrg    for (i = 0; i < val->size && i < *nelem_return; i++)
5314642e01fSmrg           buf[i] = ((float*)val->data)[i];
5324642e01fSmrg
5334642e01fSmrg    return Success;
5344642e01fSmrg}
5354642e01fSmrg
5364642e01fSmrg/* Registers a new property handler on the given device and returns a unique
5374642e01fSmrg * identifier for this handler. This identifier is required to unregister the
5384642e01fSmrg * property handler again.
5394642e01fSmrg * @return The handler's identifier or 0 if an error occured.
5404642e01fSmrg */
5414642e01fSmrglong
5424642e01fSmrgXIRegisterPropertyHandler(DeviceIntPtr         dev,
5434642e01fSmrg                          int (*SetProperty) (DeviceIntPtr dev,
5444642e01fSmrg                                              Atom property,
5454642e01fSmrg                                              XIPropertyValuePtr prop,
5464642e01fSmrg                                              BOOL checkonly),
5474642e01fSmrg                          int (*GetProperty) (DeviceIntPtr dev,
5484642e01fSmrg                                              Atom property),
5494642e01fSmrg                          int (*DeleteProperty) (DeviceIntPtr dev,
5504642e01fSmrg                                                 Atom property))
5514642e01fSmrg{
5524642e01fSmrg    XIPropertyHandlerPtr new_handler;
5534642e01fSmrg
5546747b715Smrg    new_handler = calloc(1, sizeof(XIPropertyHandler));
5554642e01fSmrg    if (!new_handler)
5564642e01fSmrg        return 0;
5574642e01fSmrg
5584642e01fSmrg    new_handler->id = XIPropHandlerID++;
5594642e01fSmrg    new_handler->SetProperty = SetProperty;
5604642e01fSmrg    new_handler->GetProperty = GetProperty;
5614642e01fSmrg    new_handler->DeleteProperty = DeleteProperty;
5624642e01fSmrg    new_handler->next = dev->properties.handlers;
5634642e01fSmrg    dev->properties.handlers = new_handler;
5644642e01fSmrg
5654642e01fSmrg    return new_handler->id;
5664642e01fSmrg}
5674642e01fSmrg
5684642e01fSmrgvoid
5694642e01fSmrgXIUnregisterPropertyHandler(DeviceIntPtr dev, long id)
5704642e01fSmrg{
5714642e01fSmrg    XIPropertyHandlerPtr curr, prev = NULL;
5724642e01fSmrg
5734642e01fSmrg    curr = dev->properties.handlers;
5744642e01fSmrg    while(curr && curr->id != id)
5754642e01fSmrg    {
5764642e01fSmrg        prev = curr;
5774642e01fSmrg        curr = curr->next;
5784642e01fSmrg    }
5794642e01fSmrg
5804642e01fSmrg    if (!curr)
5814642e01fSmrg        return;
5824642e01fSmrg
5834642e01fSmrg    if (!prev) /* first one */
5844642e01fSmrg        dev->properties.handlers = curr->next;
5854642e01fSmrg    else
5864642e01fSmrg        prev->next = curr->next;
5874642e01fSmrg
5886747b715Smrg    free(curr);
5894642e01fSmrg}
5904642e01fSmrg
5914642e01fSmrgstatic XIPropertyPtr
5924642e01fSmrgXICreateDeviceProperty (Atom property)
5934642e01fSmrg{
5944642e01fSmrg    XIPropertyPtr   prop;
5954642e01fSmrg
5966747b715Smrg    prop = (XIPropertyPtr)malloc(sizeof(XIPropertyRec));
5974642e01fSmrg    if (!prop)
5984642e01fSmrg        return NULL;
5994642e01fSmrg
6004642e01fSmrg    prop->next          = NULL;
6014642e01fSmrg    prop->propertyName  = property;
6024642e01fSmrg    prop->value.type   = None;
6034642e01fSmrg    prop->value.format = 0;
6044642e01fSmrg    prop->value.size   = 0;
6054642e01fSmrg    prop->value.data   = NULL;
6064642e01fSmrg    prop->deletable    = TRUE;
6074642e01fSmrg
6084642e01fSmrg    return prop;
6094642e01fSmrg}
6104642e01fSmrg
6114642e01fSmrgstatic XIPropertyPtr
6124642e01fSmrgXIFetchDeviceProperty(DeviceIntPtr dev, Atom property)
6134642e01fSmrg{
6144642e01fSmrg    XIPropertyPtr   prop;
6154642e01fSmrg
6164642e01fSmrg    for (prop = dev->properties.properties; prop; prop = prop->next)
6174642e01fSmrg        if (prop->propertyName == property)
6184642e01fSmrg            return prop;
6194642e01fSmrg    return NULL;
6204642e01fSmrg}
6214642e01fSmrg
6224642e01fSmrgstatic void
6234642e01fSmrgXIDestroyDeviceProperty (XIPropertyPtr prop)
6244642e01fSmrg{
6256747b715Smrg    free(prop->value.data);
6266747b715Smrg    free(prop);
6274642e01fSmrg}
6284642e01fSmrg
6294642e01fSmrg/* This function destroys all of the device's property-related stuff,
6304642e01fSmrg * including removing all device handlers.
6314642e01fSmrg * DO NOT CALL FROM THE DRIVER.
6324642e01fSmrg */
6334642e01fSmrgvoid
6344642e01fSmrgXIDeleteAllDeviceProperties (DeviceIntPtr device)
6354642e01fSmrg{
6364642e01fSmrg    XIPropertyPtr               prop, next;
6374642e01fSmrg    XIPropertyHandlerPtr        curr_handler, next_handler;
6384642e01fSmrg
6394642e01fSmrg    for (prop = device->properties.properties; prop; prop = next)
6404642e01fSmrg    {
6414642e01fSmrg        next = prop->next;
6426747b715Smrg        send_property_event(device, prop->propertyName, XIPropertyDeleted);
6434642e01fSmrg        XIDestroyDeviceProperty(prop);
6444642e01fSmrg    }
6454642e01fSmrg
6466747b715Smrg    device->properties.properties = NULL;
6476747b715Smrg
6484642e01fSmrg    /* Now free all handlers */
6494642e01fSmrg    curr_handler = device->properties.handlers;
6504642e01fSmrg    while(curr_handler)
6514642e01fSmrg    {
6524642e01fSmrg        next_handler = curr_handler->next;
6536747b715Smrg        free(curr_handler);
6544642e01fSmrg        curr_handler = next_handler;
6554642e01fSmrg    }
6566747b715Smrg
6576747b715Smrg    device->properties.handlers = NULL;
6584642e01fSmrg}
6594642e01fSmrg
6604642e01fSmrg
6614642e01fSmrgint
6624642e01fSmrgXIDeleteDeviceProperty (DeviceIntPtr device, Atom property, Bool fromClient)
6634642e01fSmrg{
6644642e01fSmrg    XIPropertyPtr               prop, *prev;
6654642e01fSmrg    int                         rc = Success;
6664642e01fSmrg
6674642e01fSmrg    for (prev = &device->properties.properties; (prop = *prev); prev = &(prop->next))
6684642e01fSmrg        if (prop->propertyName == property)
6694642e01fSmrg            break;
6704642e01fSmrg
6716747b715Smrg    if (!prop)
6726747b715Smrg        return Success;
6736747b715Smrg
6744642e01fSmrg    if (fromClient && !prop->deletable)
6754642e01fSmrg        return BadAccess;
6764642e01fSmrg
6774642e01fSmrg    /* Ask handlers if we may delete the property */
6784642e01fSmrg    if (device->properties.handlers)
6794642e01fSmrg    {
6804642e01fSmrg        XIPropertyHandlerPtr handler = device->properties.handlers;
6814642e01fSmrg        while(handler)
6824642e01fSmrg        {
6834642e01fSmrg            if (handler->DeleteProperty)
6844642e01fSmrg                rc = handler->DeleteProperty(device, prop->propertyName);
6854642e01fSmrg            if (rc != Success)
6866747b715Smrg                return rc;
6874642e01fSmrg            handler = handler->next;
6884642e01fSmrg        }
6894642e01fSmrg    }
6904642e01fSmrg
6914642e01fSmrg    if (prop)
6924642e01fSmrg    {
6934642e01fSmrg        *prev = prop->next;
6946747b715Smrg        send_property_event(device, prop->propertyName, XIPropertyDeleted);
6954642e01fSmrg        XIDestroyDeviceProperty (prop);
6964642e01fSmrg    }
6974642e01fSmrg
6984642e01fSmrg    return Success;
6994642e01fSmrg}
7004642e01fSmrg
7014642e01fSmrgint
7024642e01fSmrgXIChangeDeviceProperty (DeviceIntPtr dev, Atom property, Atom type,
7034642e01fSmrg                        int format, int mode, unsigned long len,
7049ace9065Smrg                        const pointer value, Bool sendevent)
7054642e01fSmrg{
7064642e01fSmrg    XIPropertyPtr               prop;
7074642e01fSmrg    int                         size_in_bytes;
7084642e01fSmrg    int                         total_size;
7094642e01fSmrg    unsigned long               total_len;
7104642e01fSmrg    XIPropertyValuePtr          prop_value;
7114642e01fSmrg    XIPropertyValueRec          new_value;
7124642e01fSmrg    Bool                        add = FALSE;
7134642e01fSmrg    int                         rc;
7144642e01fSmrg
7154642e01fSmrg    size_in_bytes = format >> 3;
7164642e01fSmrg
7174642e01fSmrg    /* first see if property already exists */
7184642e01fSmrg    prop = XIFetchDeviceProperty (dev, property);
7194642e01fSmrg    if (!prop)   /* just add to list */
7204642e01fSmrg    {
7214642e01fSmrg        prop = XICreateDeviceProperty (property);
7224642e01fSmrg        if (!prop)
7236747b715Smrg            return BadAlloc;
7244642e01fSmrg        add = TRUE;
7254642e01fSmrg        mode = PropModeReplace;
7264642e01fSmrg    }
7274642e01fSmrg    prop_value = &prop->value;
7284642e01fSmrg
7294642e01fSmrg    /* To append or prepend to a property the request format and type
7304642e01fSmrg     must match those of the already defined property.  The
7314642e01fSmrg     existing format and type are irrelevant when using the mode
7324642e01fSmrg     "PropModeReplace" since they will be written over. */
7334642e01fSmrg
7344642e01fSmrg    if ((format != prop_value->format) && (mode != PropModeReplace))
7356747b715Smrg        return BadMatch;
7364642e01fSmrg    if ((prop_value->type != type) && (mode != PropModeReplace))
7376747b715Smrg        return BadMatch;
7384642e01fSmrg    new_value = *prop_value;
7394642e01fSmrg    if (mode == PropModeReplace)
7404642e01fSmrg        total_len = len;
7414642e01fSmrg    else
7424642e01fSmrg        total_len = prop_value->size + len;
7434642e01fSmrg
7444642e01fSmrg    if (mode == PropModeReplace || len > 0)
7454642e01fSmrg    {
7464642e01fSmrg        pointer            new_data = NULL, old_data = NULL;
7474642e01fSmrg
7484642e01fSmrg        total_size = total_len * size_in_bytes;
7496747b715Smrg        new_value.data = (pointer)malloc(total_size);
7504642e01fSmrg        if (!new_value.data && total_size)
7514642e01fSmrg        {
7524642e01fSmrg            if (add)
7534642e01fSmrg                XIDestroyDeviceProperty (prop);
7544642e01fSmrg            return BadAlloc;
7554642e01fSmrg        }
7564642e01fSmrg        new_value.size = len;
7574642e01fSmrg        new_value.type = type;
7584642e01fSmrg        new_value.format = format;
7594642e01fSmrg
7604642e01fSmrg        switch (mode) {
7614642e01fSmrg        case PropModeReplace:
7624642e01fSmrg            new_data = new_value.data;
7634642e01fSmrg            old_data = NULL;
7644642e01fSmrg            break;
7654642e01fSmrg        case PropModeAppend:
7664642e01fSmrg            new_data = (pointer) (((char *) new_value.data) +
7674642e01fSmrg                                  (prop_value->size * size_in_bytes));
7684642e01fSmrg            old_data = new_value.data;
7694642e01fSmrg            break;
7704642e01fSmrg        case PropModePrepend:
7714642e01fSmrg            new_data = new_value.data;
7724642e01fSmrg            old_data = (pointer) (((char *) new_value.data) +
7734642e01fSmrg                                  (prop_value->size * size_in_bytes));
7744642e01fSmrg            break;
7754642e01fSmrg        }
7764642e01fSmrg        if (new_data)
7774642e01fSmrg            memcpy ((char *) new_data, (char *) value, len * size_in_bytes);
7784642e01fSmrg        if (old_data)
7794642e01fSmrg            memcpy ((char *) old_data, (char *) prop_value->data,
7804642e01fSmrg                    prop_value->size * size_in_bytes);
7814642e01fSmrg
7824642e01fSmrg        if (dev->properties.handlers)
7834642e01fSmrg        {
7844642e01fSmrg            XIPropertyHandlerPtr handler;
7854642e01fSmrg            BOOL checkonly = TRUE;
7864642e01fSmrg            /* run through all handlers with checkonly TRUE, then again with
7874642e01fSmrg             * checkonly FALSE. Handlers MUST return error codes on the
7884642e01fSmrg             * checkonly run, errors on the second run are ignored */
7894642e01fSmrg            do
7904642e01fSmrg            {
7914642e01fSmrg                handler = dev->properties.handlers;
7924642e01fSmrg                while(handler)
7934642e01fSmrg                {
7944642e01fSmrg                    if (handler->SetProperty)
7954642e01fSmrg                    {
7964642e01fSmrg                        rc = handler->SetProperty(dev, prop->propertyName,
7974642e01fSmrg                                &new_value, checkonly);
7984642e01fSmrg                        if (checkonly && rc != Success)
7994642e01fSmrg                        {
8006747b715Smrg                            free(new_value.data);
8016747b715Smrg                            return rc;
8024642e01fSmrg                        }
8034642e01fSmrg                    }
8044642e01fSmrg                    handler = handler->next;
8054642e01fSmrg                }
8064642e01fSmrg                checkonly = !checkonly;
8074642e01fSmrg            } while (!checkonly);
8084642e01fSmrg        }
8096747b715Smrg        free(prop_value->data);
8104642e01fSmrg        *prop_value = new_value;
8114642e01fSmrg    } else if (len == 0)
8124642e01fSmrg    {
8134642e01fSmrg        /* do nothing */
8144642e01fSmrg    }
8154642e01fSmrg
8164642e01fSmrg    if (add)
8174642e01fSmrg    {
8184642e01fSmrg        prop->next = dev->properties.properties;
8194642e01fSmrg        dev->properties.properties = prop;
8204642e01fSmrg    }
8214642e01fSmrg
8224642e01fSmrg    if (sendevent)
8236747b715Smrg        send_property_event(dev, prop->propertyName,
8246747b715Smrg                            (add) ?  XIPropertyCreated : XIPropertyModified);
8256747b715Smrg
8266747b715Smrg    return Success;
8274642e01fSmrg}
8284642e01fSmrg
8294642e01fSmrgint
8304642e01fSmrgXIGetDeviceProperty (DeviceIntPtr dev, Atom property, XIPropertyValuePtr *value)
8314642e01fSmrg{
8324642e01fSmrg    XIPropertyPtr   prop = XIFetchDeviceProperty (dev, property);
8334642e01fSmrg    int rc;
8344642e01fSmrg
8354642e01fSmrg    if (!prop)
8364642e01fSmrg    {
8374642e01fSmrg        *value = NULL;
8384642e01fSmrg        return BadAtom;
8394642e01fSmrg    }
8404642e01fSmrg
8414642e01fSmrg    /* If we can, try to update the property value first */
8424642e01fSmrg    if (dev->properties.handlers)
8434642e01fSmrg    {
8444642e01fSmrg        XIPropertyHandlerPtr handler = dev->properties.handlers;
8454642e01fSmrg        while(handler)
8464642e01fSmrg        {
8474642e01fSmrg            if (handler->GetProperty)
8484642e01fSmrg            {
8494642e01fSmrg                rc = handler->GetProperty(dev, prop->propertyName);
8504642e01fSmrg                if (rc != Success)
8514642e01fSmrg                {
8524642e01fSmrg                    *value = NULL;
8534642e01fSmrg                    return rc;
8544642e01fSmrg                }
8554642e01fSmrg            }
8564642e01fSmrg            handler = handler->next;
8574642e01fSmrg        }
8584642e01fSmrg    }
8594642e01fSmrg
8604642e01fSmrg    *value = &prop->value;
8614642e01fSmrg    return Success;
8624642e01fSmrg}
8634642e01fSmrg
8644642e01fSmrgint
8654642e01fSmrgXISetDevicePropertyDeletable(DeviceIntPtr dev, Atom property, Bool deletable)
8664642e01fSmrg{
8674642e01fSmrg    XIPropertyPtr prop = XIFetchDeviceProperty(dev, property);
8684642e01fSmrg
8694642e01fSmrg    if (!prop)
8704642e01fSmrg        return BadAtom;
8714642e01fSmrg
8724642e01fSmrg    prop->deletable = deletable;
8734642e01fSmrg    return Success;
8744642e01fSmrg}
8754642e01fSmrg
8764642e01fSmrgint
8774642e01fSmrgProcXListDeviceProperties (ClientPtr client)
8784642e01fSmrg{
8796747b715Smrg    Atom                        *atoms;
8804642e01fSmrg    xListDevicePropertiesReply  rep;
8816747b715Smrg    int                         natoms;
8824642e01fSmrg    DeviceIntPtr                dev;
8834642e01fSmrg    int                         rc = Success;
8844642e01fSmrg
8854642e01fSmrg    REQUEST(xListDevicePropertiesReq);
8864642e01fSmrg    REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
8874642e01fSmrg
8886747b715Smrg    rc = dixLookupDevice (&dev, stuff->deviceid, client, DixListPropAccess);
8894642e01fSmrg    if (rc != Success)
8904642e01fSmrg        return rc;
8914642e01fSmrg
8926747b715Smrg    rc = list_atoms(dev, &natoms, &atoms);
8936747b715Smrg    if (rc != Success)
8946747b715Smrg        return rc;
8954642e01fSmrg
8964642e01fSmrg    rep.repType = X_Reply;
8974642e01fSmrg    rep.RepType = X_ListDeviceProperties;
8986747b715Smrg    rep.length = natoms;
8994642e01fSmrg    rep.sequenceNumber = client->sequence;
9006747b715Smrg    rep.nAtoms = natoms;
9014642e01fSmrg
9024642e01fSmrg    WriteReplyToClient(client, sizeof(xListDevicePropertiesReply), &rep);
9036747b715Smrg    if (natoms)
9044642e01fSmrg    {
9054642e01fSmrg        client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
9066747b715Smrg        WriteSwappedDataToClient(client, natoms * sizeof(Atom), atoms);
9076747b715Smrg        free(atoms);
9084642e01fSmrg    }
9094642e01fSmrg    return rc;
9104642e01fSmrg}
9114642e01fSmrg
9124642e01fSmrgint
9134642e01fSmrgProcXChangeDeviceProperty (ClientPtr client)
9144642e01fSmrg{
9154642e01fSmrg    REQUEST(xChangeDevicePropertyReq);
9164642e01fSmrg    DeviceIntPtr        dev;
9174642e01fSmrg    unsigned long       len;
9184642e01fSmrg    int                 totalSize;
9194642e01fSmrg    int                 rc;
9204642e01fSmrg
9214642e01fSmrg    REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq);
9224642e01fSmrg    UpdateCurrentTime();
9234642e01fSmrg
9246747b715Smrg    rc = dixLookupDevice (&dev, stuff->deviceid, client, DixSetPropAccess);
9254642e01fSmrg    if (rc != Success)
9264642e01fSmrg        return rc;
9274642e01fSmrg
9286747b715Smrg    rc = check_change_property(client, stuff->property, stuff->type,
9296747b715Smrg                               stuff->format, stuff->mode, stuff->nUnits);
9304642e01fSmrg
9316747b715Smrg    len = stuff->nUnits;
9326747b715Smrg    if (len > (bytes_to_int32(0xffffffff - sizeof(xChangeDevicePropertyReq))))
9336747b715Smrg        return BadLength;
9344642e01fSmrg
9356747b715Smrg    totalSize = len * (stuff->format/8);
9366747b715Smrg    REQUEST_FIXED_SIZE(xChangeDevicePropertyReq, totalSize);
9376747b715Smrg
9386747b715Smrg    rc = change_property(client, dev, stuff->property, stuff->type,
9396747b715Smrg                         stuff->format, stuff->mode, len, (void*)&stuff[1]);
9404642e01fSmrg    return rc;
9414642e01fSmrg}
9424642e01fSmrg
9434642e01fSmrgint
9444642e01fSmrgProcXDeleteDeviceProperty (ClientPtr client)
9454642e01fSmrg{
9464642e01fSmrg    REQUEST(xDeleteDevicePropertyReq);
9474642e01fSmrg    DeviceIntPtr        dev;
9484642e01fSmrg    int                 rc;
9494642e01fSmrg
9504642e01fSmrg    REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
9514642e01fSmrg    UpdateCurrentTime();
9526747b715Smrg    rc =  dixLookupDevice (&dev, stuff->deviceid, client, DixSetPropAccess);
9534642e01fSmrg    if (rc != Success)
9544642e01fSmrg        return rc;
9554642e01fSmrg
9564642e01fSmrg    if (!ValidAtom(stuff->property))
9574642e01fSmrg    {
9584642e01fSmrg        client->errorValue = stuff->property;
9596747b715Smrg        return BadAtom;
9604642e01fSmrg    }
9614642e01fSmrg
9624642e01fSmrg    rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE);
9634642e01fSmrg    return rc;
9644642e01fSmrg}
9654642e01fSmrg
9664642e01fSmrgint
9674642e01fSmrgProcXGetDeviceProperty (ClientPtr client)
9684642e01fSmrg{
9694642e01fSmrg    REQUEST(xGetDevicePropertyReq);
9704642e01fSmrg    DeviceIntPtr                dev;
9716747b715Smrg    int                         length;
9726747b715Smrg    int                         rc, format, nitems, bytes_after;
9736747b715Smrg    char                        *data;
9746747b715Smrg    Atom                        type;
9754642e01fSmrg    xGetDevicePropertyReply     reply;
9764642e01fSmrg
9774642e01fSmrg    REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
9784642e01fSmrg    if (stuff->delete)
9794642e01fSmrg        UpdateCurrentTime();
9804642e01fSmrg    rc = dixLookupDevice (&dev, stuff->deviceid, client,
9816747b715Smrg                           stuff->delete ? DixSetPropAccess :
9826747b715Smrg                           DixGetPropAccess);
9834642e01fSmrg    if (rc != Success)
9844642e01fSmrg        return rc;
9854642e01fSmrg
9866747b715Smrg    rc = get_property(client, dev, stuff->property, stuff->type,
9876747b715Smrg            stuff->delete, stuff->longOffset, stuff->longLength,
9886747b715Smrg            &bytes_after, &type, &format, &nitems, &length, &data);
9894642e01fSmrg
9906747b715Smrg    if (rc != Success)
9916747b715Smrg        return rc;
9924642e01fSmrg
9934642e01fSmrg    reply.repType = X_Reply;
9944642e01fSmrg    reply.RepType = X_GetDeviceProperty;
9954642e01fSmrg    reply.sequenceNumber = client->sequence;
9964642e01fSmrg    reply.deviceid = dev->id;
9976747b715Smrg    reply.nItems = nitems;
9986747b715Smrg    reply.format = format;
9996747b715Smrg    reply.bytesAfter = bytes_after;
10006747b715Smrg    reply.propertyType = type;
10016747b715Smrg    reply.length = bytes_to_int32(length);
10024642e01fSmrg
10034642e01fSmrg    if (stuff->delete && (reply.bytesAfter == 0))
10046747b715Smrg        send_property_event(dev, stuff->property, XIPropertyDeleted);
10054642e01fSmrg
10064642e01fSmrg    WriteReplyToClient(client, sizeof(xGenericReply), &reply);
10076747b715Smrg
10086747b715Smrg    if (length)
10094642e01fSmrg    {
10104642e01fSmrg        switch (reply.format) {
10116747b715Smrg            case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break;
10126747b715Smrg            case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break;
10136747b715Smrg            default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break;
10144642e01fSmrg        }
10156747b715Smrg        WriteSwappedDataToClient(client, length, data);
10164642e01fSmrg    }
10174642e01fSmrg
10186747b715Smrg    /* delete the Property */
10194642e01fSmrg    if (stuff->delete && (reply.bytesAfter == 0))
10206747b715Smrg    {
10216747b715Smrg        XIPropertyPtr prop, *prev;
10226747b715Smrg        for (prev = &dev->properties.properties; (prop = *prev); prev = &prop->next)
10236747b715Smrg        {
10246747b715Smrg            if (prop->propertyName == stuff->property)
10256747b715Smrg            {
10266747b715Smrg                *prev = prop->next;
10276747b715Smrg                XIDestroyDeviceProperty(prop);
10286747b715Smrg                break;
10296747b715Smrg            }
10306747b715Smrg        }
10314642e01fSmrg    }
10326747b715Smrg    return Success;
10334642e01fSmrg}
10344642e01fSmrg
10354642e01fSmrg
10364642e01fSmrgint
10374642e01fSmrgSProcXListDeviceProperties (ClientPtr client)
10384642e01fSmrg{
10394642e01fSmrg    char n;
10404642e01fSmrg    REQUEST(xListDevicePropertiesReq);
10410b0d8713Smrg    REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
10424642e01fSmrg
10434642e01fSmrg    swaps(&stuff->length, n);
10444642e01fSmrg    return (ProcXListDeviceProperties(client));
10454642e01fSmrg}
10464642e01fSmrg
10474642e01fSmrgint
10484642e01fSmrgSProcXChangeDeviceProperty (ClientPtr client)
10494642e01fSmrg{
10504642e01fSmrg    char n;
10514642e01fSmrg    REQUEST(xChangeDevicePropertyReq);
10524642e01fSmrg
10539ace9065Smrg    REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq);
10544642e01fSmrg    swaps(&stuff->length, n);
10554642e01fSmrg    swapl(&stuff->property, n);
10564642e01fSmrg    swapl(&stuff->type, n);
10574642e01fSmrg    swapl(&stuff->nUnits, n);
10584642e01fSmrg    return (ProcXChangeDeviceProperty(client));
10594642e01fSmrg}
10604642e01fSmrg
10614642e01fSmrgint
10624642e01fSmrgSProcXDeleteDeviceProperty (ClientPtr client)
10634642e01fSmrg{
10644642e01fSmrg    char n;
10654642e01fSmrg    REQUEST(xDeleteDevicePropertyReq);
10660b0d8713Smrg    REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
10674642e01fSmrg
10684642e01fSmrg    swaps(&stuff->length, n);
10694642e01fSmrg    swapl(&stuff->property, n);
10704642e01fSmrg    return (ProcXDeleteDeviceProperty(client));
10714642e01fSmrg}
10724642e01fSmrg
10734642e01fSmrgint
10744642e01fSmrgSProcXGetDeviceProperty (ClientPtr client)
10754642e01fSmrg{
10764642e01fSmrg    char n;
10774642e01fSmrg    REQUEST(xGetDevicePropertyReq);
10780b0d8713Smrg    REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
10794642e01fSmrg
10804642e01fSmrg    swaps(&stuff->length, n);
10814642e01fSmrg    swapl(&stuff->property, n);
10824642e01fSmrg    swapl(&stuff->type, n);
10834642e01fSmrg    swapl(&stuff->longOffset, n);
10844642e01fSmrg    swapl(&stuff->longLength, n);
10854642e01fSmrg    return (ProcXGetDeviceProperty(client));
10864642e01fSmrg}
10874642e01fSmrg
10884642e01fSmrg
10894642e01fSmrg/* Reply swapping */
10904642e01fSmrg
10914642e01fSmrgvoid
10924642e01fSmrgSRepXListDeviceProperties(ClientPtr client, int size,
10934642e01fSmrg                          xListDevicePropertiesReply *rep)
10944642e01fSmrg{
10954642e01fSmrg    char n;
10964642e01fSmrg    swaps(&rep->sequenceNumber, n);
10974642e01fSmrg    swapl(&rep->length, n);
10984642e01fSmrg    swaps(&rep->nAtoms, n);
10994642e01fSmrg    /* properties will be swapped later, see ProcXListDeviceProperties */
11004642e01fSmrg    WriteToClient(client, size, (char*)rep);
11014642e01fSmrg}
11024642e01fSmrg
11034642e01fSmrgvoid
11044642e01fSmrgSRepXGetDeviceProperty(ClientPtr client, int size,
11054642e01fSmrg                       xGetDevicePropertyReply *rep)
11064642e01fSmrg{
11074642e01fSmrg    char n;
11084642e01fSmrg
11094642e01fSmrg    swaps(&rep->sequenceNumber, n);
11104642e01fSmrg    swapl(&rep->length, n);
11114642e01fSmrg    swapl(&rep->propertyType, n);
11124642e01fSmrg    swapl(&rep->bytesAfter, n);
11134642e01fSmrg    swapl(&rep->nItems, n);
11144642e01fSmrg    /* data will be swapped, see ProcXGetDeviceProperty */
11154642e01fSmrg    WriteToClient(client, size, (char*)rep);
11164642e01fSmrg}
11176747b715Smrg
11186747b715Smrg/* XI2 Request/reply handling */
11196747b715Smrgint
11206747b715SmrgProcXIListProperties(ClientPtr client)
11216747b715Smrg{
11226747b715Smrg    Atom                        *atoms;
11236747b715Smrg    xXIListPropertiesReply      rep;
11246747b715Smrg    int                         natoms;
11256747b715Smrg    DeviceIntPtr                dev;
11266747b715Smrg    int                         rc = Success;
11276747b715Smrg
11286747b715Smrg    REQUEST(xXIListPropertiesReq);
11296747b715Smrg    REQUEST_SIZE_MATCH(xXIListPropertiesReq);
11306747b715Smrg
11316747b715Smrg    rc = dixLookupDevice (&dev, stuff->deviceid, client, DixListPropAccess);
11326747b715Smrg    if (rc != Success)
11336747b715Smrg        return rc;
11346747b715Smrg
11356747b715Smrg    rc = list_atoms(dev, &natoms, &atoms);
11366747b715Smrg    if (rc != Success)
11376747b715Smrg        return rc;
11386747b715Smrg
11396747b715Smrg    rep.repType = X_Reply;
11406747b715Smrg    rep.RepType = X_XIListProperties;
11416747b715Smrg    rep.length = natoms;
11426747b715Smrg    rep.sequenceNumber = client->sequence;
11436747b715Smrg    rep.num_properties = natoms;
11446747b715Smrg
11456747b715Smrg    WriteReplyToClient(client, sizeof(xXIListPropertiesReply), &rep);
11466747b715Smrg    if (natoms)
11476747b715Smrg    {
11486747b715Smrg        client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
11496747b715Smrg        WriteSwappedDataToClient(client, natoms * sizeof(Atom), atoms);
11506747b715Smrg        free(atoms);
11516747b715Smrg    }
11526747b715Smrg    return rc;
11536747b715Smrg}
11546747b715Smrg
11556747b715Smrgint
11566747b715SmrgProcXIChangeProperty(ClientPtr client)
11576747b715Smrg{
11586747b715Smrg    int                 rc;
11596747b715Smrg    DeviceIntPtr        dev;
11606747b715Smrg    int                 totalSize;
11616747b715Smrg    unsigned long       len;
11626747b715Smrg
11636747b715Smrg    REQUEST(xXIChangePropertyReq);
11646747b715Smrg    REQUEST_AT_LEAST_SIZE(xXIChangePropertyReq);
11656747b715Smrg    UpdateCurrentTime();
11666747b715Smrg
11676747b715Smrg    rc = dixLookupDevice (&dev, stuff->deviceid, client, DixSetPropAccess);
11686747b715Smrg    if (rc != Success)
11696747b715Smrg        return rc;
11706747b715Smrg
11716747b715Smrg    rc = check_change_property(client, stuff->property, stuff->type,
11726747b715Smrg                               stuff->format, stuff->mode, stuff->num_items);
11736747b715Smrg    len = stuff->num_items;
11746747b715Smrg    if (len > bytes_to_int32(0xffffffff - sizeof(xXIChangePropertyReq)))
11756747b715Smrg        return BadLength;
11766747b715Smrg
11776747b715Smrg    totalSize = len * (stuff->format/8);
11786747b715Smrg    REQUEST_FIXED_SIZE(xXIChangePropertyReq, totalSize);
11796747b715Smrg
11806747b715Smrg    rc = change_property(client, dev, stuff->property, stuff->type,
11816747b715Smrg                         stuff->format, stuff->mode, len, (void*)&stuff[1]);
11826747b715Smrg    return rc;
11836747b715Smrg}
11846747b715Smrg
11856747b715Smrgint
11866747b715SmrgProcXIDeleteProperty(ClientPtr client)
11876747b715Smrg{
11886747b715Smrg    DeviceIntPtr        dev;
11896747b715Smrg    int                 rc;
11906747b715Smrg    REQUEST(xXIDeletePropertyReq);
11916747b715Smrg
11926747b715Smrg    REQUEST_SIZE_MATCH(xXIDeletePropertyReq);
11936747b715Smrg    UpdateCurrentTime();
11946747b715Smrg    rc =  dixLookupDevice (&dev, stuff->deviceid, client, DixSetPropAccess);
11956747b715Smrg    if (rc != Success)
11966747b715Smrg        return rc;
11976747b715Smrg
11986747b715Smrg    if (!ValidAtom(stuff->property))
11996747b715Smrg    {
12006747b715Smrg        client->errorValue = stuff->property;
12016747b715Smrg        return BadAtom;
12026747b715Smrg    }
12036747b715Smrg
12046747b715Smrg    rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE);
12056747b715Smrg    return rc;
12066747b715Smrg}
12076747b715Smrg
12086747b715Smrg
12096747b715Smrgint
12106747b715SmrgProcXIGetProperty(ClientPtr client)
12116747b715Smrg{
12126747b715Smrg    REQUEST(xXIGetPropertyReq);
12136747b715Smrg    DeviceIntPtr                dev;
12146747b715Smrg    xXIGetPropertyReply         reply;
12156747b715Smrg    int                         length;
12166747b715Smrg    int                         rc, format, nitems, bytes_after;
12176747b715Smrg    char                        *data;
12186747b715Smrg    Atom                        type;
12196747b715Smrg
12206747b715Smrg    REQUEST_SIZE_MATCH(xXIGetPropertyReq);
12216747b715Smrg    if (stuff->delete)
12226747b715Smrg        UpdateCurrentTime();
12236747b715Smrg    rc = dixLookupDevice (&dev, stuff->deviceid, client,
12246747b715Smrg                           stuff->delete ? DixSetPropAccess :
12256747b715Smrg                           DixGetPropAccess);
12266747b715Smrg    if (rc != Success)
12276747b715Smrg        return rc;
12286747b715Smrg
12296747b715Smrg    rc = get_property(client, dev, stuff->property, stuff->type,
12306747b715Smrg            stuff->delete, stuff->offset, stuff->len,
12316747b715Smrg            &bytes_after, &type, &format, &nitems, &length, &data);
12326747b715Smrg
12336747b715Smrg    if (rc != Success)
12346747b715Smrg        return rc;
12356747b715Smrg
12366747b715Smrg    reply.repType = X_Reply;
12376747b715Smrg    reply.RepType = X_XIGetProperty;
12386747b715Smrg    reply.sequenceNumber = client->sequence;
12396747b715Smrg    reply.num_items = nitems;
12406747b715Smrg    reply.format = format;
12416747b715Smrg    reply.bytes_after = bytes_after;
12426747b715Smrg    reply.type = type;
12436747b715Smrg    reply.length = bytes_to_int32(length);
12446747b715Smrg
12456747b715Smrg    if (length && stuff->delete && (reply.bytes_after == 0))
12466747b715Smrg        send_property_event(dev, stuff->property, XIPropertyDeleted);
12476747b715Smrg
12486747b715Smrg    WriteReplyToClient(client, sizeof(xXIGetPropertyReply), &reply);
12496747b715Smrg
12506747b715Smrg    if (length)
12516747b715Smrg    {
12526747b715Smrg        switch (reply.format) {
12536747b715Smrg            case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break;
12546747b715Smrg            case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break;
12556747b715Smrg            default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break;
12566747b715Smrg        }
12576747b715Smrg        WriteSwappedDataToClient(client, length, data);
12586747b715Smrg    }
12596747b715Smrg
12606747b715Smrg    /* delete the Property */
12616747b715Smrg    if (stuff->delete && (reply.bytes_after == 0))
12626747b715Smrg    {
12636747b715Smrg        XIPropertyPtr prop, *prev;
12646747b715Smrg        for (prev = &dev->properties.properties; (prop = *prev); prev = &prop->next)
12656747b715Smrg        {
12666747b715Smrg            if (prop->propertyName == stuff->property)
12676747b715Smrg            {
12686747b715Smrg                *prev = prop->next;
12696747b715Smrg                XIDestroyDeviceProperty(prop);
12706747b715Smrg                break;
12716747b715Smrg            }
12726747b715Smrg        }
12736747b715Smrg    }
12746747b715Smrg
12756747b715Smrg    return Success;
12766747b715Smrg}
12776747b715Smrg
12786747b715Smrgint
12796747b715SmrgSProcXIListProperties(ClientPtr client)
12806747b715Smrg{
12816747b715Smrg    char n;
12826747b715Smrg    REQUEST(xXIListPropertiesReq);
12830b0d8713Smrg    REQUEST_SIZE_MATCH(xXIListPropertiesReq);
12846747b715Smrg
12856747b715Smrg    swaps(&stuff->length, n);
12866747b715Smrg    swaps(&stuff->deviceid, n);
12876747b715Smrg    return (ProcXIListProperties(client));
12886747b715Smrg}
12896747b715Smrg
12906747b715Smrgint
12916747b715SmrgSProcXIChangeProperty(ClientPtr client)
12926747b715Smrg{
12936747b715Smrg    char n;
12946747b715Smrg    REQUEST(xXIChangePropertyReq);
12956747b715Smrg
12969ace9065Smrg    REQUEST_AT_LEAST_SIZE(xXIChangePropertyReq);
12976747b715Smrg    swaps(&stuff->length, n);
12986747b715Smrg    swaps(&stuff->deviceid, n);
12996747b715Smrg    swapl(&stuff->property, n);
13006747b715Smrg    swapl(&stuff->type, n);
13016747b715Smrg    swapl(&stuff->num_items, n);
13026747b715Smrg    return (ProcXIChangeProperty(client));
13036747b715Smrg}
13046747b715Smrg
13056747b715Smrgint
13066747b715SmrgSProcXIDeleteProperty(ClientPtr client)
13076747b715Smrg{
13086747b715Smrg    char n;
13096747b715Smrg    REQUEST(xXIDeletePropertyReq);
13100b0d8713Smrg    REQUEST_SIZE_MATCH(xXIDeletePropertyReq);
13116747b715Smrg
13126747b715Smrg    swaps(&stuff->length, n);
13136747b715Smrg    swaps(&stuff->deviceid, n);
13146747b715Smrg    swapl(&stuff->property, n);
13156747b715Smrg    return (ProcXIDeleteProperty(client));
13166747b715Smrg}
13176747b715Smrg
13186747b715Smrgint
13196747b715SmrgSProcXIGetProperty(ClientPtr client)
13206747b715Smrg{
13216747b715Smrg    char n;
13226747b715Smrg    REQUEST(xXIGetPropertyReq);
13230b0d8713Smrg    REQUEST_SIZE_MATCH(xXIGetPropertyReq);
13246747b715Smrg
13256747b715Smrg    swaps(&stuff->length, n);
13266747b715Smrg    swaps(&stuff->deviceid, n);
13276747b715Smrg    swapl(&stuff->property, n);
13286747b715Smrg    swapl(&stuff->type, n);
13296747b715Smrg    swapl(&stuff->offset, n);
13306747b715Smrg    swapl(&stuff->len, n);
13316747b715Smrg    return (ProcXIGetProperty(client));
13326747b715Smrg}
13336747b715Smrg
13346747b715Smrg
13356747b715Smrgvoid
13366747b715SmrgSRepXIListProperties(ClientPtr client, int size,
13376747b715Smrg                     xXIListPropertiesReply *rep)
13386747b715Smrg{
13396747b715Smrg    char n;
13406747b715Smrg    swaps(&rep->sequenceNumber, n);
13416747b715Smrg    swapl(&rep->length, n);
13426747b715Smrg    swaps(&rep->num_properties, n);
13436747b715Smrg    /* properties will be swapped later, see ProcXIListProperties */
13446747b715Smrg    WriteToClient(client, size, (char*)rep);
13456747b715Smrg}
13466747b715Smrg
13476747b715Smrgvoid
13486747b715SmrgSRepXIGetProperty(ClientPtr client, int size,
13496747b715Smrg                  xXIGetPropertyReply *rep)
13506747b715Smrg{
13516747b715Smrg    char n;
13526747b715Smrg
13536747b715Smrg    swaps(&rep->sequenceNumber, n);
13546747b715Smrg    swapl(&rep->length, n);
13556747b715Smrg    swapl(&rep->type, n);
13566747b715Smrg    swapl(&rep->bytes_after, n);
13576747b715Smrg    swapl(&rep->num_items, n);
13586747b715Smrg    /* data will be swapped, see ProcXIGetProperty */
13596747b715Smrg    WriteToClient(client, size, (char*)rep);
13606747b715Smrg}
1361