xiproperty.c revision 5a112b11
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; 893f7df2e56Smrg int 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); 9054642e01fSmrg 9066747b715Smrg len = stuff->nUnits; 9076747b715Smrg if (len > (bytes_to_int32(0xffffffff - sizeof(xChangeDevicePropertyReq)))) 9086747b715Smrg return BadLength; 9094642e01fSmrg 910f7df2e56Smrg totalSize = len * (stuff->format / 8); 9116747b715Smrg REQUEST_FIXED_SIZE(xChangeDevicePropertyReq, totalSize); 9126747b715Smrg 9136747b715Smrg rc = change_property(client, dev, stuff->property, stuff->type, 914f7df2e56Smrg stuff->format, stuff->mode, len, (void *) &stuff[1]); 9154642e01fSmrg return rc; 9164642e01fSmrg} 9174642e01fSmrg 9184642e01fSmrgint 919f7df2e56SmrgProcXDeleteDeviceProperty(ClientPtr client) 9204642e01fSmrg{ 9214642e01fSmrg REQUEST(xDeleteDevicePropertyReq); 922f7df2e56Smrg DeviceIntPtr dev; 923f7df2e56Smrg int rc; 9244642e01fSmrg 9254642e01fSmrg REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq); 9264642e01fSmrg UpdateCurrentTime(); 927f7df2e56Smrg rc = dixLookupDevice(&dev, stuff->deviceid, client, DixSetPropAccess); 9284642e01fSmrg if (rc != Success) 9294642e01fSmrg return rc; 9304642e01fSmrg 931f7df2e56Smrg if (!ValidAtom(stuff->property)) { 9324642e01fSmrg client->errorValue = stuff->property; 9336747b715Smrg return BadAtom; 9344642e01fSmrg } 9354642e01fSmrg 9364642e01fSmrg rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE); 9374642e01fSmrg return rc; 9384642e01fSmrg} 9394642e01fSmrg 9404642e01fSmrgint 941f7df2e56SmrgProcXGetDeviceProperty(ClientPtr client) 9424642e01fSmrg{ 9434642e01fSmrg REQUEST(xGetDevicePropertyReq); 944f7df2e56Smrg DeviceIntPtr dev; 945f7df2e56Smrg int length; 946f7df2e56Smrg int rc, format, nitems, bytes_after; 947f7df2e56Smrg char *data; 948f7df2e56Smrg Atom type; 949f7df2e56Smrg xGetDevicePropertyReply reply; 9504642e01fSmrg 9514642e01fSmrg REQUEST_SIZE_MATCH(xGetDevicePropertyReq); 9524642e01fSmrg if (stuff->delete) 9534642e01fSmrg UpdateCurrentTime(); 954f7df2e56Smrg rc = dixLookupDevice(&dev, stuff->deviceid, client, 955f7df2e56Smrg stuff->delete ? DixSetPropAccess : DixGetPropAccess); 9564642e01fSmrg if (rc != Success) 9574642e01fSmrg return rc; 9584642e01fSmrg 9596747b715Smrg rc = get_property(client, dev, stuff->property, stuff->type, 960f7df2e56Smrg stuff->delete, stuff->longOffset, stuff->longLength, 961f7df2e56Smrg &bytes_after, &type, &format, &nitems, &length, &data); 9624642e01fSmrg 9636747b715Smrg if (rc != Success) 9646747b715Smrg return rc; 9654642e01fSmrg 966f7df2e56Smrg reply = (xGetDevicePropertyReply) { 967f7df2e56Smrg .repType = X_Reply, 968f7df2e56Smrg .RepType = X_GetDeviceProperty, 969f7df2e56Smrg .sequenceNumber = client->sequence, 970f7df2e56Smrg .length = bytes_to_int32(length), 971f7df2e56Smrg .propertyType = type, 972f7df2e56Smrg .bytesAfter = bytes_after, 973f7df2e56Smrg .nItems = nitems, 974f7df2e56Smrg .format = format, 975f7df2e56Smrg .deviceid = dev->id 976f7df2e56Smrg }; 9774642e01fSmrg 9784642e01fSmrg if (stuff->delete && (reply.bytesAfter == 0)) 9796747b715Smrg send_property_event(dev, stuff->property, XIPropertyDeleted); 9804642e01fSmrg 9814642e01fSmrg WriteReplyToClient(client, sizeof(xGenericReply), &reply); 9826747b715Smrg 983f7df2e56Smrg if (length) { 9844642e01fSmrg switch (reply.format) { 985f7df2e56Smrg case 32: 986f7df2e56Smrg client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write; 987f7df2e56Smrg break; 988f7df2e56Smrg case 16: 989f7df2e56Smrg client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write; 990f7df2e56Smrg break; 991f7df2e56Smrg default: 992f7df2e56Smrg client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient; 993f7df2e56Smrg break; 9944642e01fSmrg } 9956747b715Smrg WriteSwappedDataToClient(client, length, data); 9964642e01fSmrg } 9974642e01fSmrg 9986747b715Smrg /* delete the Property */ 999f7df2e56Smrg if (stuff->delete && (reply.bytesAfter == 0)) { 10006747b715Smrg XIPropertyPtr prop, *prev; 1001f7df2e56Smrg 1002f7df2e56Smrg for (prev = &dev->properties.properties; (prop = *prev); 1003f7df2e56Smrg prev = &prop->next) { 1004f7df2e56Smrg if (prop->propertyName == stuff->property) { 10056747b715Smrg *prev = prop->next; 10066747b715Smrg XIDestroyDeviceProperty(prop); 10076747b715Smrg break; 10086747b715Smrg } 10096747b715Smrg } 10104642e01fSmrg } 10116747b715Smrg return Success; 10124642e01fSmrg} 10134642e01fSmrg 10147e31ba66Smrgint _X_COLD 1015f7df2e56SmrgSProcXListDeviceProperties(ClientPtr client) 10164642e01fSmrg{ 10174642e01fSmrg REQUEST(xListDevicePropertiesReq); 10180b0d8713Smrg REQUEST_SIZE_MATCH(xListDevicePropertiesReq); 10194642e01fSmrg 1020f7df2e56Smrg swaps(&stuff->length); 10214642e01fSmrg return (ProcXListDeviceProperties(client)); 10224642e01fSmrg} 10234642e01fSmrg 10247e31ba66Smrgint _X_COLD 1025f7df2e56SmrgSProcXChangeDeviceProperty(ClientPtr client) 10264642e01fSmrg{ 10274642e01fSmrg REQUEST(xChangeDevicePropertyReq); 10284642e01fSmrg 10299ace9065Smrg REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq); 1030f7df2e56Smrg swaps(&stuff->length); 1031f7df2e56Smrg swapl(&stuff->property); 1032f7df2e56Smrg swapl(&stuff->type); 1033f7df2e56Smrg swapl(&stuff->nUnits); 10344642e01fSmrg return (ProcXChangeDeviceProperty(client)); 10354642e01fSmrg} 10364642e01fSmrg 10377e31ba66Smrgint _X_COLD 1038f7df2e56SmrgSProcXDeleteDeviceProperty(ClientPtr client) 10394642e01fSmrg{ 10404642e01fSmrg REQUEST(xDeleteDevicePropertyReq); 10410b0d8713Smrg REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq); 10424642e01fSmrg 1043f7df2e56Smrg swaps(&stuff->length); 1044f7df2e56Smrg swapl(&stuff->property); 10454642e01fSmrg return (ProcXDeleteDeviceProperty(client)); 10464642e01fSmrg} 10474642e01fSmrg 10487e31ba66Smrgint _X_COLD 1049f7df2e56SmrgSProcXGetDeviceProperty(ClientPtr client) 10504642e01fSmrg{ 10514642e01fSmrg REQUEST(xGetDevicePropertyReq); 10520b0d8713Smrg REQUEST_SIZE_MATCH(xGetDevicePropertyReq); 10534642e01fSmrg 1054f7df2e56Smrg swaps(&stuff->length); 1055f7df2e56Smrg swapl(&stuff->property); 1056f7df2e56Smrg swapl(&stuff->type); 1057f7df2e56Smrg swapl(&stuff->longOffset); 1058f7df2e56Smrg swapl(&stuff->longLength); 10594642e01fSmrg return (ProcXGetDeviceProperty(client)); 10604642e01fSmrg} 10614642e01fSmrg 10624642e01fSmrg/* Reply swapping */ 10634642e01fSmrg 10647e31ba66Smrgvoid _X_COLD 10654642e01fSmrgSRepXListDeviceProperties(ClientPtr client, int size, 1066f7df2e56Smrg xListDevicePropertiesReply * rep) 10674642e01fSmrg{ 1068f7df2e56Smrg swaps(&rep->sequenceNumber); 1069f7df2e56Smrg swapl(&rep->length); 1070f7df2e56Smrg swaps(&rep->nAtoms); 10714642e01fSmrg /* properties will be swapped later, see ProcXListDeviceProperties */ 1072f7df2e56Smrg WriteToClient(client, size, rep); 10734642e01fSmrg} 10744642e01fSmrg 10757e31ba66Smrgvoid _X_COLD 10764642e01fSmrgSRepXGetDeviceProperty(ClientPtr client, int size, 1077f7df2e56Smrg xGetDevicePropertyReply * rep) 10784642e01fSmrg{ 1079f7df2e56Smrg swaps(&rep->sequenceNumber); 1080f7df2e56Smrg swapl(&rep->length); 1081f7df2e56Smrg swapl(&rep->propertyType); 1082f7df2e56Smrg swapl(&rep->bytesAfter); 1083f7df2e56Smrg swapl(&rep->nItems); 10844642e01fSmrg /* data will be swapped, see ProcXGetDeviceProperty */ 1085f7df2e56Smrg WriteToClient(client, size, rep); 10864642e01fSmrg} 10876747b715Smrg 10886747b715Smrg/* XI2 Request/reply handling */ 10896747b715Smrgint 10906747b715SmrgProcXIListProperties(ClientPtr client) 10916747b715Smrg{ 1092f7df2e56Smrg Atom *atoms; 1093f7df2e56Smrg xXIListPropertiesReply rep; 1094f7df2e56Smrg int natoms; 1095f7df2e56Smrg DeviceIntPtr dev; 1096f7df2e56Smrg int rc = Success; 10976747b715Smrg 10986747b715Smrg REQUEST(xXIListPropertiesReq); 10996747b715Smrg REQUEST_SIZE_MATCH(xXIListPropertiesReq); 11006747b715Smrg 1101f7df2e56Smrg rc = dixLookupDevice(&dev, stuff->deviceid, client, DixListPropAccess); 11026747b715Smrg if (rc != Success) 11036747b715Smrg return rc; 11046747b715Smrg 11056747b715Smrg rc = list_atoms(dev, &natoms, &atoms); 11066747b715Smrg if (rc != Success) 11076747b715Smrg return rc; 11086747b715Smrg 1109f7df2e56Smrg rep = (xXIListPropertiesReply) { 1110f7df2e56Smrg .repType = X_Reply, 1111f7df2e56Smrg .RepType = X_XIListProperties, 1112f7df2e56Smrg .sequenceNumber = client->sequence, 1113f7df2e56Smrg .length = natoms, 1114f7df2e56Smrg .num_properties = natoms 1115f7df2e56Smrg }; 11166747b715Smrg 11176747b715Smrg WriteReplyToClient(client, sizeof(xXIListPropertiesReply), &rep); 1118f7df2e56Smrg if (natoms) { 1119f7df2e56Smrg client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; 11206747b715Smrg WriteSwappedDataToClient(client, natoms * sizeof(Atom), atoms); 11216747b715Smrg free(atoms); 11226747b715Smrg } 11236747b715Smrg return rc; 11246747b715Smrg} 11256747b715Smrg 11266747b715Smrgint 11276747b715SmrgProcXIChangeProperty(ClientPtr client) 11286747b715Smrg{ 1129f7df2e56Smrg int rc; 1130f7df2e56Smrg DeviceIntPtr dev; 1131f7df2e56Smrg int totalSize; 1132f7df2e56Smrg unsigned long len; 11336747b715Smrg 11346747b715Smrg REQUEST(xXIChangePropertyReq); 11356747b715Smrg REQUEST_AT_LEAST_SIZE(xXIChangePropertyReq); 11366747b715Smrg UpdateCurrentTime(); 11376747b715Smrg 1138f7df2e56Smrg rc = dixLookupDevice(&dev, stuff->deviceid, client, DixSetPropAccess); 11396747b715Smrg if (rc != Success) 11406747b715Smrg return rc; 11416747b715Smrg 11426747b715Smrg rc = check_change_property(client, stuff->property, stuff->type, 11436747b715Smrg stuff->format, stuff->mode, stuff->num_items); 11446747b715Smrg len = stuff->num_items; 11456747b715Smrg if (len > bytes_to_int32(0xffffffff - sizeof(xXIChangePropertyReq))) 11466747b715Smrg return BadLength; 11476747b715Smrg 1148f7df2e56Smrg totalSize = len * (stuff->format / 8); 11496747b715Smrg REQUEST_FIXED_SIZE(xXIChangePropertyReq, totalSize); 11506747b715Smrg 11516747b715Smrg rc = change_property(client, dev, stuff->property, stuff->type, 1152f7df2e56Smrg stuff->format, stuff->mode, len, (void *) &stuff[1]); 11536747b715Smrg return rc; 11546747b715Smrg} 11556747b715Smrg 11566747b715Smrgint 11576747b715SmrgProcXIDeleteProperty(ClientPtr client) 11586747b715Smrg{ 1159f7df2e56Smrg DeviceIntPtr dev; 1160f7df2e56Smrg int rc; 1161f7df2e56Smrg 11626747b715Smrg REQUEST(xXIDeletePropertyReq); 11636747b715Smrg 11646747b715Smrg REQUEST_SIZE_MATCH(xXIDeletePropertyReq); 11656747b715Smrg UpdateCurrentTime(); 1166f7df2e56Smrg rc = dixLookupDevice(&dev, stuff->deviceid, client, DixSetPropAccess); 11676747b715Smrg if (rc != Success) 11686747b715Smrg return rc; 11696747b715Smrg 1170f7df2e56Smrg if (!ValidAtom(stuff->property)) { 11716747b715Smrg client->errorValue = stuff->property; 11726747b715Smrg return BadAtom; 11736747b715Smrg } 11746747b715Smrg 11756747b715Smrg rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE); 11766747b715Smrg return rc; 11776747b715Smrg} 11786747b715Smrg 11796747b715Smrgint 11806747b715SmrgProcXIGetProperty(ClientPtr client) 11816747b715Smrg{ 11826747b715Smrg REQUEST(xXIGetPropertyReq); 1183f7df2e56Smrg DeviceIntPtr dev; 1184f7df2e56Smrg xXIGetPropertyReply reply; 1185f7df2e56Smrg int length; 1186f7df2e56Smrg int rc, format, nitems, bytes_after; 1187f7df2e56Smrg char *data; 1188f7df2e56Smrg Atom type; 11896747b715Smrg 11906747b715Smrg REQUEST_SIZE_MATCH(xXIGetPropertyReq); 11916747b715Smrg if (stuff->delete) 11926747b715Smrg UpdateCurrentTime(); 1193f7df2e56Smrg rc = dixLookupDevice(&dev, stuff->deviceid, client, 1194f7df2e56Smrg stuff->delete ? DixSetPropAccess : DixGetPropAccess); 11956747b715Smrg if (rc != Success) 11966747b715Smrg return rc; 11976747b715Smrg 11986747b715Smrg rc = get_property(client, dev, stuff->property, stuff->type, 1199f7df2e56Smrg stuff->delete, stuff->offset, stuff->len, 1200f7df2e56Smrg &bytes_after, &type, &format, &nitems, &length, &data); 12016747b715Smrg 12026747b715Smrg if (rc != Success) 12036747b715Smrg return rc; 12046747b715Smrg 1205f7df2e56Smrg reply = (xXIGetPropertyReply) { 1206f7df2e56Smrg .repType = X_Reply, 1207f7df2e56Smrg .RepType = X_XIGetProperty, 1208f7df2e56Smrg .sequenceNumber = client->sequence, 1209f7df2e56Smrg .length = bytes_to_int32(length), 1210f7df2e56Smrg .type = type, 1211f7df2e56Smrg .bytes_after = bytes_after, 1212f7df2e56Smrg .num_items = nitems, 1213f7df2e56Smrg .format = format 1214f7df2e56Smrg }; 12156747b715Smrg 12166747b715Smrg if (length && stuff->delete && (reply.bytes_after == 0)) 12176747b715Smrg send_property_event(dev, stuff->property, XIPropertyDeleted); 12186747b715Smrg 12196747b715Smrg WriteReplyToClient(client, sizeof(xXIGetPropertyReply), &reply); 12206747b715Smrg 1221f7df2e56Smrg if (length) { 12226747b715Smrg switch (reply.format) { 1223f7df2e56Smrg case 32: 1224f7df2e56Smrg client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write; 1225f7df2e56Smrg break; 1226f7df2e56Smrg case 16: 1227f7df2e56Smrg client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write; 1228f7df2e56Smrg break; 1229f7df2e56Smrg default: 1230f7df2e56Smrg client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient; 1231f7df2e56Smrg break; 12326747b715Smrg } 12336747b715Smrg WriteSwappedDataToClient(client, length, data); 12346747b715Smrg } 12356747b715Smrg 12366747b715Smrg /* delete the Property */ 1237f7df2e56Smrg if (stuff->delete && (reply.bytes_after == 0)) { 12386747b715Smrg XIPropertyPtr prop, *prev; 1239f7df2e56Smrg 1240f7df2e56Smrg for (prev = &dev->properties.properties; (prop = *prev); 1241f7df2e56Smrg prev = &prop->next) { 1242f7df2e56Smrg if (prop->propertyName == stuff->property) { 12436747b715Smrg *prev = prop->next; 12446747b715Smrg XIDestroyDeviceProperty(prop); 12456747b715Smrg break; 12466747b715Smrg } 12476747b715Smrg } 12486747b715Smrg } 12496747b715Smrg 12506747b715Smrg return Success; 12516747b715Smrg} 12526747b715Smrg 12537e31ba66Smrgint _X_COLD 12546747b715SmrgSProcXIListProperties(ClientPtr client) 12556747b715Smrg{ 12566747b715Smrg REQUEST(xXIListPropertiesReq); 12570b0d8713Smrg REQUEST_SIZE_MATCH(xXIListPropertiesReq); 12586747b715Smrg 1259f7df2e56Smrg swaps(&stuff->length); 1260f7df2e56Smrg swaps(&stuff->deviceid); 12616747b715Smrg return (ProcXIListProperties(client)); 12626747b715Smrg} 12636747b715Smrg 12647e31ba66Smrgint _X_COLD 12656747b715SmrgSProcXIChangeProperty(ClientPtr client) 12666747b715Smrg{ 12676747b715Smrg REQUEST(xXIChangePropertyReq); 12686747b715Smrg 12699ace9065Smrg REQUEST_AT_LEAST_SIZE(xXIChangePropertyReq); 1270f7df2e56Smrg swaps(&stuff->length); 1271f7df2e56Smrg swaps(&stuff->deviceid); 1272f7df2e56Smrg swapl(&stuff->property); 1273f7df2e56Smrg swapl(&stuff->type); 1274f7df2e56Smrg swapl(&stuff->num_items); 12756747b715Smrg return (ProcXIChangeProperty(client)); 12766747b715Smrg} 12776747b715Smrg 12787e31ba66Smrgint _X_COLD 12796747b715SmrgSProcXIDeleteProperty(ClientPtr client) 12806747b715Smrg{ 12816747b715Smrg REQUEST(xXIDeletePropertyReq); 12820b0d8713Smrg REQUEST_SIZE_MATCH(xXIDeletePropertyReq); 12836747b715Smrg 1284f7df2e56Smrg swaps(&stuff->length); 1285f7df2e56Smrg swaps(&stuff->deviceid); 1286f7df2e56Smrg swapl(&stuff->property); 12876747b715Smrg return (ProcXIDeleteProperty(client)); 12886747b715Smrg} 12896747b715Smrg 12907e31ba66Smrgint _X_COLD 12916747b715SmrgSProcXIGetProperty(ClientPtr client) 12926747b715Smrg{ 12936747b715Smrg REQUEST(xXIGetPropertyReq); 12940b0d8713Smrg REQUEST_SIZE_MATCH(xXIGetPropertyReq); 12956747b715Smrg 1296f7df2e56Smrg swaps(&stuff->length); 1297f7df2e56Smrg swaps(&stuff->deviceid); 1298f7df2e56Smrg swapl(&stuff->property); 1299f7df2e56Smrg swapl(&stuff->type); 1300f7df2e56Smrg swapl(&stuff->offset); 1301f7df2e56Smrg swapl(&stuff->len); 13026747b715Smrg return (ProcXIGetProperty(client)); 13036747b715Smrg} 13046747b715Smrg 13057e31ba66Smrgvoid _X_COLD 1306f7df2e56SmrgSRepXIListProperties(ClientPtr client, int size, xXIListPropertiesReply * rep) 13076747b715Smrg{ 1308f7df2e56Smrg swaps(&rep->sequenceNumber); 1309f7df2e56Smrg swapl(&rep->length); 1310f7df2e56Smrg swaps(&rep->num_properties); 13116747b715Smrg /* properties will be swapped later, see ProcXIListProperties */ 1312f7df2e56Smrg WriteToClient(client, size, rep); 13136747b715Smrg} 13146747b715Smrg 13157e31ba66Smrgvoid _X_COLD 1316f7df2e56SmrgSRepXIGetProperty(ClientPtr client, int size, xXIGetPropertyReply * rep) 13176747b715Smrg{ 1318f7df2e56Smrg swaps(&rep->sequenceNumber); 1319f7df2e56Smrg swapl(&rep->length); 1320f7df2e56Smrg swapl(&rep->type); 1321f7df2e56Smrg swapl(&rep->bytes_after); 1322f7df2e56Smrg swapl(&rep->num_items); 13236747b715Smrg /* data will be swapped, see ProcXIGetProperty */ 1324f7df2e56Smrg WriteToClient(client, size, rep); 13256747b715Smrg} 1326