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