xichangehierarchy.c revision 0b0d8713
16747b715Smrg/* 26747b715Smrg * Copyright 2007-2008 Peter Hutterer 36747b715Smrg * Copyright 2009 Red Hat, Inc. 46747b715Smrg * 56747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a 66747b715Smrg * copy of this software and associated documentation files (the "Software"), 76747b715Smrg * to deal in the Software without restriction, including without limitation 86747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 96747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the 106747b715Smrg * Software is furnished to do so, subject to the following conditions: 116747b715Smrg * 126747b715Smrg * The above copyright notice and this permission notice (including the next 136747b715Smrg * paragraph) shall be included in all copies or substantial portions of the 146747b715Smrg * Software. 156747b715Smrg * 166747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 176747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 186747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 196747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 206747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 216747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 226747b715Smrg * DEALINGS IN THE SOFTWARE. 236747b715Smrg * 246747b715Smrg * Author: Peter Hutterer, University of South Australia, NICTA 256747b715Smrg */ 266747b715Smrg 276747b715Smrg/*********************************************************************** 286747b715Smrg * 296747b715Smrg * Request change in the device hierarchy. 306747b715Smrg * 316747b715Smrg */ 326747b715Smrg 336747b715Smrg 346747b715Smrg#ifdef HAVE_DIX_CONFIG_H 356747b715Smrg#include <dix-config.h> 366747b715Smrg#endif 376747b715Smrg 386747b715Smrg#include <X11/X.h> /* for inputstr.h */ 396747b715Smrg#include <X11/Xproto.h> /* Request macro */ 406747b715Smrg#include "inputstr.h" /* DeviceIntPtr */ 416747b715Smrg#include "windowstr.h" /* window structure */ 426747b715Smrg#include "scrnintstr.h" /* screen structure */ 436747b715Smrg#include <X11/extensions/XI.h> 446747b715Smrg#include <X11/extensions/XI2proto.h> 456747b715Smrg#include <X11/extensions/geproto.h> 466747b715Smrg#include "extnsionst.h" 476747b715Smrg#include "exevents.h" 486747b715Smrg#include "exglobals.h" 496747b715Smrg#include "geext.h" 506747b715Smrg#include "xace.h" 516747b715Smrg#include "xiquerydevice.h" /* for GetDeviceUse */ 526747b715Smrg 536747b715Smrg#include "xkbsrv.h" 546747b715Smrg 556747b715Smrg#include "xichangehierarchy.h" 566747b715Smrg 576747b715Smrg/** 586747b715Smrg * Send the current state of the device hierarchy to all clients. 596747b715Smrg */ 606747b715Smrgvoid XISendDeviceHierarchyEvent(int flags[MAXDEVICES]) 616747b715Smrg{ 626747b715Smrg xXIHierarchyEvent *ev; 636747b715Smrg xXIHierarchyInfo *info; 646747b715Smrg DeviceIntRec dummyDev; 656747b715Smrg DeviceIntPtr dev; 666747b715Smrg int i; 676747b715Smrg 686747b715Smrg if (!flags) 696747b715Smrg return; 706747b715Smrg 716747b715Smrg ev = calloc(1, sizeof(xXIHierarchyEvent) + 726747b715Smrg MAXDEVICES * sizeof(xXIHierarchyInfo)); 739ace9065Smrg if (!ev) 749ace9065Smrg return; 756747b715Smrg ev->type = GenericEvent; 766747b715Smrg ev->extension = IReqCode; 776747b715Smrg ev->evtype = XI_HierarchyChanged; 786747b715Smrg ev->time = GetTimeInMillis(); 796747b715Smrg ev->flags = 0; 806747b715Smrg ev->num_info = inputInfo.numDevices; 816747b715Smrg 826747b715Smrg info = (xXIHierarchyInfo*)&ev[1]; 836747b715Smrg for (dev = inputInfo.devices; dev; dev = dev->next) 846747b715Smrg { 856747b715Smrg info->deviceid = dev->id; 866747b715Smrg info->enabled = dev->enabled; 876747b715Smrg info->use = GetDeviceUse(dev, &info->attachment); 886747b715Smrg info->flags = flags[dev->id]; 896747b715Smrg ev->flags |= info->flags; 906747b715Smrg info++; 916747b715Smrg } 926747b715Smrg for (dev = inputInfo.off_devices; dev; dev = dev->next) 936747b715Smrg { 946747b715Smrg info->deviceid = dev->id; 956747b715Smrg info->enabled = dev->enabled; 966747b715Smrg info->use = GetDeviceUse(dev, &info->attachment); 976747b715Smrg info->flags = flags[dev->id]; 986747b715Smrg ev->flags |= info->flags; 996747b715Smrg info++; 1006747b715Smrg } 1016747b715Smrg 1026747b715Smrg 1036747b715Smrg for (i = 0; i < MAXDEVICES; i++) 1046747b715Smrg { 1056747b715Smrg if (flags[i] & (XIMasterRemoved | XISlaveRemoved)) 1066747b715Smrg { 1076747b715Smrg info->deviceid = i; 1086747b715Smrg info->enabled = FALSE; 1096747b715Smrg info->flags = flags[i]; 1106747b715Smrg info->use = 0; 1116747b715Smrg ev->flags |= info->flags; 1126747b715Smrg ev->num_info++; 1136747b715Smrg info++; 1146747b715Smrg } 1156747b715Smrg } 1166747b715Smrg 1176747b715Smrg ev->length = bytes_to_int32(ev->num_info * sizeof(xXIHierarchyInfo)); 1186747b715Smrg 1196747b715Smrg dummyDev.id = XIAllDevices; 1206747b715Smrg SendEventToAllWindows(&dummyDev, (XI_HierarchyChangedMask >> 8), (xEvent*)ev, 1); 1216747b715Smrg free(ev); 1226747b715Smrg} 1236747b715Smrg 1246747b715Smrg 1256747b715Smrg/*********************************************************************** 1266747b715Smrg * 1276747b715Smrg * This procedure allows a client to change the device hierarchy through 1286747b715Smrg * adding new master devices, removing them, etc. 1296747b715Smrg * 1306747b715Smrg */ 1316747b715Smrg 1326747b715Smrgint SProcXIChangeHierarchy(ClientPtr client) 1336747b715Smrg{ 1346747b715Smrg char n; 1356747b715Smrg 1366747b715Smrg REQUEST(xXIChangeHierarchyReq); 1376747b715Smrg swaps(&stuff->length, n); 1386747b715Smrg return (ProcXIChangeHierarchy(client)); 1396747b715Smrg} 1406747b715Smrg 1419ace9065Smrgstatic int 1429ace9065Smrgadd_master(ClientPtr client, xXIAddMasterInfo *c, int flags[MAXDEVICES]) 1439ace9065Smrg{ 1449ace9065Smrg DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd; 1459ace9065Smrg char* name; 1469ace9065Smrg int rc; 1479ace9065Smrg 1489ace9065Smrg name = calloc(c->name_len + 1, sizeof(char)); 1499ace9065Smrg strncpy(name, (char*)&c[1], c->name_len); 1509ace9065Smrg 1519ace9065Smrg rc = AllocDevicePair(client, name, &ptr, &keybd, 1529ace9065Smrg CorePointerProc, CoreKeyboardProc, TRUE); 1539ace9065Smrg if (rc != Success) 1549ace9065Smrg goto unwind; 1559ace9065Smrg 1569ace9065Smrg if (!c->send_core) 1579ace9065Smrg ptr->coreEvents = keybd->coreEvents = FALSE; 1589ace9065Smrg 1599ace9065Smrg /* Allocate virtual slave devices for xtest events */ 1609ace9065Smrg rc = AllocXTestDevice(client, name, &XTestptr, &XTestkeybd, ptr, keybd); 1619ace9065Smrg if (rc != Success) 1629ace9065Smrg { 1639ace9065Smrg DeleteInputDeviceRequest(ptr); 1649ace9065Smrg DeleteInputDeviceRequest(keybd); 1659ace9065Smrg goto unwind; 1669ace9065Smrg } 1679ace9065Smrg 1689ace9065Smrg ActivateDevice(ptr, FALSE); 1699ace9065Smrg ActivateDevice(keybd, FALSE); 1709ace9065Smrg flags[ptr->id] |= XIMasterAdded; 1719ace9065Smrg flags[keybd->id] |= XIMasterAdded; 1729ace9065Smrg 1739ace9065Smrg ActivateDevice(XTestptr, FALSE); 1749ace9065Smrg ActivateDevice(XTestkeybd, FALSE); 1759ace9065Smrg flags[XTestptr->id] |= XISlaveAdded; 1769ace9065Smrg flags[XTestkeybd->id] |= XISlaveAdded; 1779ace9065Smrg 1789ace9065Smrg if (c->enable) 1799ace9065Smrg { 1809ace9065Smrg EnableDevice(ptr, FALSE); 1819ace9065Smrg EnableDevice(keybd, FALSE); 1829ace9065Smrg flags[ptr->id] |= XIDeviceEnabled; 1839ace9065Smrg flags[keybd->id] |= XIDeviceEnabled; 1849ace9065Smrg 1859ace9065Smrg EnableDevice(XTestptr, FALSE); 1869ace9065Smrg EnableDevice(XTestkeybd, FALSE); 1879ace9065Smrg flags[XTestptr->id] |= XIDeviceEnabled; 1889ace9065Smrg flags[XTestkeybd->id] |= XIDeviceEnabled; 1899ace9065Smrg } 1909ace9065Smrg 1919ace9065Smrg /* Attach the XTest virtual devices to the newly 1929ace9065Smrg created master device */ 1939ace9065Smrg AttachDevice(NULL, XTestptr, ptr); 1949ace9065Smrg AttachDevice(NULL, XTestkeybd, keybd); 1959ace9065Smrg flags[XTestptr->id] |= XISlaveAttached; 1969ace9065Smrg flags[XTestkeybd->id] |= XISlaveAttached; 1979ace9065Smrg 1989ace9065Smrgunwind: 1999ace9065Smrg free(name); 2009ace9065Smrg return rc; 2019ace9065Smrg} 2029ace9065Smrg 203475c125cSmrgstatic void 204475c125cSmrgdisable_clientpointer(DeviceIntPtr dev) 205475c125cSmrg{ 206475c125cSmrg int i; 207475c125cSmrg 208475c125cSmrg for (i = 0; i < currentMaxClients; i++) 209475c125cSmrg { 210475c125cSmrg ClientPtr client = clients[i]; 211475c125cSmrg if (client && client->clientPtr == dev) 212475c125cSmrg client->clientPtr = NULL; 213475c125cSmrg } 214475c125cSmrg} 215475c125cSmrg 2169ace9065Smrgstatic int 2179ace9065Smrgremove_master(ClientPtr client, xXIRemoveMasterInfo *r, 2189ace9065Smrg int flags[MAXDEVICES]) 2199ace9065Smrg{ 2209ace9065Smrg DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd; 2219ace9065Smrg int rc = Success; 2229ace9065Smrg 2239ace9065Smrg if (r->return_mode != XIAttachToMaster && 2249ace9065Smrg r->return_mode != XIFloating) 2259ace9065Smrg return BadValue; 2269ace9065Smrg 2279ace9065Smrg rc = dixLookupDevice(&ptr, r->deviceid, client, DixDestroyAccess); 2289ace9065Smrg if (rc != Success) 2299ace9065Smrg goto unwind; 2309ace9065Smrg 2319ace9065Smrg if (!IsMaster(ptr)) 2329ace9065Smrg { 2339ace9065Smrg client->errorValue = r->deviceid; 2349ace9065Smrg rc = BadDevice; 2359ace9065Smrg goto unwind; 2369ace9065Smrg } 2379ace9065Smrg 2389ace9065Smrg /* XXX: For now, don't allow removal of VCP, VCK */ 2399ace9065Smrg if (ptr == inputInfo.pointer || ptr == inputInfo.keyboard) 2409ace9065Smrg { 2419ace9065Smrg rc = BadDevice; 2429ace9065Smrg goto unwind; 2439ace9065Smrg } 2449ace9065Smrg 2459ace9065Smrg 2469ace9065Smrg ptr = GetMaster(ptr, MASTER_POINTER); 2479ace9065Smrg rc = dixLookupDevice(&ptr, ptr->id, client, DixDestroyAccess); 2489ace9065Smrg if (rc != Success) 2499ace9065Smrg goto unwind; 2509ace9065Smrg keybd = GetMaster(ptr, MASTER_KEYBOARD); 2519ace9065Smrg rc = dixLookupDevice(&keybd, keybd->id, client, DixDestroyAccess); 2529ace9065Smrg if (rc != Success) 2539ace9065Smrg goto unwind; 2549ace9065Smrg 2559ace9065Smrg XTestptr = GetXTestDevice(ptr); 2569ace9065Smrg rc = dixLookupDevice(&XTestptr, XTestptr->id, client, DixDestroyAccess); 2579ace9065Smrg if (rc != Success) 2589ace9065Smrg goto unwind; 2599ace9065Smrg 2609ace9065Smrg XTestkeybd = GetXTestDevice(keybd); 2619ace9065Smrg rc = dixLookupDevice(&XTestkeybd, XTestkeybd->id, client, 2629ace9065Smrg DixDestroyAccess); 2639ace9065Smrg if (rc != Success) 2649ace9065Smrg goto unwind; 2659ace9065Smrg 266475c125cSmrg disable_clientpointer(ptr); 267475c125cSmrg 2689ace9065Smrg /* Disabling sends the devices floating, reattach them if 2699ace9065Smrg * desired. */ 2709ace9065Smrg if (r->return_mode == XIAttachToMaster) 2719ace9065Smrg { 2729ace9065Smrg DeviceIntPtr attached, 2739ace9065Smrg newptr, 2749ace9065Smrg newkeybd; 2759ace9065Smrg 2769ace9065Smrg rc = dixLookupDevice(&newptr, r->return_pointer, client, DixAddAccess); 2779ace9065Smrg if (rc != Success) 2789ace9065Smrg goto unwind; 2799ace9065Smrg 2809ace9065Smrg if (!IsMaster(newptr)) 2819ace9065Smrg { 2829ace9065Smrg client->errorValue = r->return_pointer; 2839ace9065Smrg rc = BadDevice; 2849ace9065Smrg goto unwind; 2859ace9065Smrg } 2869ace9065Smrg 2879ace9065Smrg rc = dixLookupDevice(&newkeybd, r->return_keyboard, 2889ace9065Smrg client, DixAddAccess); 2899ace9065Smrg if (rc != Success) 2909ace9065Smrg goto unwind; 2919ace9065Smrg 2929ace9065Smrg if (!IsMaster(newkeybd)) 2939ace9065Smrg { 2949ace9065Smrg client->errorValue = r->return_keyboard; 2959ace9065Smrg rc = BadDevice; 2969ace9065Smrg goto unwind; 2979ace9065Smrg } 2989ace9065Smrg 2999ace9065Smrg for (attached = inputInfo.devices; attached; attached = attached->next) 3009ace9065Smrg { 3019ace9065Smrg if (!IsMaster(attached)) { 3029ace9065Smrg if (attached->u.master == ptr) 3039ace9065Smrg { 3049ace9065Smrg AttachDevice(client, attached, newptr); 3059ace9065Smrg flags[attached->id] |= XISlaveAttached; 3069ace9065Smrg } 3079ace9065Smrg if (attached->u.master == keybd) 3089ace9065Smrg { 3099ace9065Smrg AttachDevice(client, attached, newkeybd); 3109ace9065Smrg flags[attached->id] |= XISlaveAttached; 3119ace9065Smrg } 3129ace9065Smrg } 3139ace9065Smrg } 3149ace9065Smrg } 3159ace9065Smrg 3169ace9065Smrg /* can't disable until we removed pairing */ 3179ace9065Smrg keybd->spriteInfo->paired = NULL; 3189ace9065Smrg ptr->spriteInfo->paired = NULL; 3199ace9065Smrg XTestptr->spriteInfo->paired = NULL; 3209ace9065Smrg XTestkeybd->spriteInfo->paired = NULL; 3219ace9065Smrg 3229ace9065Smrg /* disable the remove the devices, XTest devices must be done first 3239ace9065Smrg else the sprites they rely on will be destroyed */ 3249ace9065Smrg DisableDevice(XTestptr, FALSE); 3259ace9065Smrg DisableDevice(XTestkeybd, FALSE); 3269ace9065Smrg DisableDevice(keybd, FALSE); 3279ace9065Smrg DisableDevice(ptr, FALSE); 3289ace9065Smrg flags[XTestptr->id] |= XIDeviceDisabled | XISlaveDetached; 3299ace9065Smrg flags[XTestkeybd->id] |= XIDeviceDisabled | XISlaveDetached; 3309ace9065Smrg flags[keybd->id] |= XIDeviceDisabled; 3319ace9065Smrg flags[ptr->id] |= XIDeviceDisabled; 3329ace9065Smrg 3339ace9065Smrg RemoveDevice(XTestptr, FALSE); 3349ace9065Smrg RemoveDevice(XTestkeybd, FALSE); 3359ace9065Smrg RemoveDevice(keybd, FALSE); 3369ace9065Smrg RemoveDevice(ptr, FALSE); 3379ace9065Smrg flags[XTestptr->id] |= XISlaveRemoved; 3389ace9065Smrg flags[XTestkeybd->id] |= XISlaveRemoved; 3399ace9065Smrg flags[keybd->id] |= XIMasterRemoved; 3409ace9065Smrg flags[ptr->id] |= XIMasterRemoved; 3419ace9065Smrg 3429ace9065Smrgunwind: 3439ace9065Smrg return rc; 3449ace9065Smrg} 3459ace9065Smrg 3469ace9065Smrgstatic int 3479ace9065Smrgdetach_slave(ClientPtr client, xXIDetachSlaveInfo *c, int flags[MAXDEVICES]) 3489ace9065Smrg{ 3499ace9065Smrg DeviceIntPtr dev; 3509ace9065Smrg int rc; 3519ace9065Smrg 3529ace9065Smrg rc = dixLookupDevice(&dev, c->deviceid, client, DixManageAccess); 3539ace9065Smrg if (rc != Success) 3549ace9065Smrg goto unwind; 3559ace9065Smrg 3569ace9065Smrg if (IsMaster(dev)) 3579ace9065Smrg { 3589ace9065Smrg client->errorValue = c->deviceid; 3599ace9065Smrg rc = BadDevice; 3609ace9065Smrg goto unwind; 3619ace9065Smrg } 3629ace9065Smrg 3639ace9065Smrg /* Don't allow changes to XTest Devices, these are fixed */ 3649ace9065Smrg if (IsXTestDevice(dev, NULL)) 3659ace9065Smrg { 3669ace9065Smrg client->errorValue = c->deviceid; 3679ace9065Smrg rc = BadDevice; 3689ace9065Smrg goto unwind; 3699ace9065Smrg } 3709ace9065Smrg 3719ace9065Smrg ReleaseButtonsAndKeys(dev); 3729ace9065Smrg AttachDevice(client, dev, NULL); 3739ace9065Smrg flags[dev->id] |= XISlaveDetached; 3749ace9065Smrg 3759ace9065Smrgunwind: 3769ace9065Smrg return rc; 3779ace9065Smrg} 3789ace9065Smrg 3799ace9065Smrgstatic int 3809ace9065Smrgattach_slave(ClientPtr client, xXIAttachSlaveInfo *c, 3819ace9065Smrg int flags[MAXDEVICES]) 3829ace9065Smrg{ 3839ace9065Smrg DeviceIntPtr dev; 3849ace9065Smrg DeviceIntPtr newmaster; 3859ace9065Smrg int rc; 3869ace9065Smrg 3879ace9065Smrg rc = dixLookupDevice(&dev, c->deviceid, client, DixManageAccess); 3889ace9065Smrg if (rc != Success) 3899ace9065Smrg goto unwind; 3909ace9065Smrg 3919ace9065Smrg if (IsMaster(dev)) 3929ace9065Smrg { 3939ace9065Smrg client->errorValue = c->deviceid; 3949ace9065Smrg rc = BadDevice; 3959ace9065Smrg goto unwind; 3969ace9065Smrg } 3979ace9065Smrg 3989ace9065Smrg /* Don't allow changes to XTest Devices, these are fixed */ 3999ace9065Smrg if (IsXTestDevice(dev, NULL)) 4009ace9065Smrg { 4019ace9065Smrg client->errorValue = c->deviceid; 4029ace9065Smrg rc = BadDevice; 4039ace9065Smrg goto unwind; 4049ace9065Smrg } 4059ace9065Smrg 4069ace9065Smrg rc = dixLookupDevice(&newmaster, c->new_master, client, DixAddAccess); 4079ace9065Smrg if (rc != Success) 4089ace9065Smrg goto unwind; 4099ace9065Smrg if (!IsMaster(newmaster)) 4109ace9065Smrg { 4119ace9065Smrg client->errorValue = c->new_master; 4129ace9065Smrg rc = BadDevice; 4139ace9065Smrg goto unwind; 4149ace9065Smrg } 4159ace9065Smrg 4169ace9065Smrg if (!((IsPointerDevice(newmaster) && IsPointerDevice(dev)) || 4179ace9065Smrg (IsKeyboardDevice(newmaster) && IsKeyboardDevice(dev)))) 4189ace9065Smrg { 4199ace9065Smrg rc = BadDevice; 4209ace9065Smrg goto unwind; 4219ace9065Smrg } 4229ace9065Smrg 4239ace9065Smrg ReleaseButtonsAndKeys(dev); 4249ace9065Smrg AttachDevice(client, dev, newmaster); 4259ace9065Smrg flags[dev->id] |= XISlaveAttached; 4269ace9065Smrg 4279ace9065Smrgunwind: 4289ace9065Smrg return rc; 4299ace9065Smrg} 4309ace9065Smrg 4319ace9065Smrg 4329ace9065Smrg 4336747b715Smrg#define SWAPIF(cmd) if (client->swapped) { cmd; } 4346747b715Smrg 4356747b715Smrgint 4366747b715SmrgProcXIChangeHierarchy(ClientPtr client) 4376747b715Smrg{ 4386747b715Smrg xXIAnyHierarchyChangeInfo *any; 4390b0d8713Smrg size_t len; /* length of data remaining in request */ 4406747b715Smrg char n; 4416747b715Smrg int rc = Success; 4426747b715Smrg int flags[MAXDEVICES] = {0}; 4436747b715Smrg 4446747b715Smrg REQUEST(xXIChangeHierarchyReq); 4456747b715Smrg REQUEST_AT_LEAST_SIZE(xXIChangeHierarchyReq); 4466747b715Smrg 4476747b715Smrg if (!stuff->num_changes) 4486747b715Smrg return rc; 4496747b715Smrg 4500b0d8713Smrg if (stuff->length > (INT_MAX >> 2)) 4510b0d8713Smrg return BadAlloc; 4520b0d8713Smrg len = (stuff->length << 2) - sizeof(xXIAnyHierarchyChangeInfo); 4530b0d8713Smrg 4546747b715Smrg any = (xXIAnyHierarchyChangeInfo*)&stuff[1]; 4556747b715Smrg while(stuff->num_changes--) 4566747b715Smrg { 4570b0d8713Smrg if (len < sizeof(xXIAnyHierarchyChangeInfo)) { 4580b0d8713Smrg rc = BadLength; 4590b0d8713Smrg goto unwind; 4600b0d8713Smrg } 4610b0d8713Smrg 4626747b715Smrg SWAPIF(swapl(&any->type, n)); 4636747b715Smrg SWAPIF(swaps(&any->length, n)); 4646747b715Smrg 4650b0d8713Smrg if ((any->length > (INT_MAX >> 2)) || (len < (any->length << 2))) 4666747b715Smrg return BadLength; 4676747b715Smrg 4680b0d8713Smrg#define CHANGE_SIZE_MATCH(type) \ 4690b0d8713Smrg do { \ 4700b0d8713Smrg if ((len < sizeof(type)) || (any->length != (sizeof(type) >> 2))) { \ 4710b0d8713Smrg rc = BadLength; \ 4720b0d8713Smrg goto unwind; \ 4730b0d8713Smrg } \ 4740b0d8713Smrg } while(0) 4750b0d8713Smrg 4766747b715Smrg switch(any->type) 4776747b715Smrg { 4786747b715Smrg case XIAddMaster: 4796747b715Smrg { 4806747b715Smrg xXIAddMasterInfo* c = (xXIAddMasterInfo*)any; 4810b0d8713Smrg /* Variable length, due to appended name string */ 4820b0d8713Smrg if (len < sizeof(xXIAddMasterInfo)) { 4830b0d8713Smrg rc = BadLength; 4840b0d8713Smrg goto unwind; 4850b0d8713Smrg } 4866747b715Smrg SWAPIF(swaps(&c->name_len, n)); 4870b0d8713Smrg if (c->name_len > (len - sizeof(xXIAddMasterInfo))) { 4880b0d8713Smrg rc = BadLength; 4890b0d8713Smrg goto unwind; 4900b0d8713Smrg } 4916747b715Smrg 4929ace9065Smrg rc = add_master(client, c, flags); 4936747b715Smrg if (rc != Success) 4946747b715Smrg goto unwind; 4956747b715Smrg } 4966747b715Smrg break; 4976747b715Smrg case XIRemoveMaster: 4986747b715Smrg { 4996747b715Smrg xXIRemoveMasterInfo* r = (xXIRemoveMasterInfo*)any; 5006747b715Smrg 5010b0d8713Smrg CHANGE_SIZE_MATCH(xXIRemoveMasterInfo); 5029ace9065Smrg rc = remove_master(client, r, flags); 5036747b715Smrg if (rc != Success) 5046747b715Smrg goto unwind; 5056747b715Smrg } 5066747b715Smrg break; 5076747b715Smrg case XIDetachSlave: 5086747b715Smrg { 5096747b715Smrg xXIDetachSlaveInfo* c = (xXIDetachSlaveInfo*)any; 5106747b715Smrg 5110b0d8713Smrg CHANGE_SIZE_MATCH(xXIDetachSlaveInfo); 5129ace9065Smrg rc = detach_slave(client, c, flags); 5136747b715Smrg if (rc != Success) 5146747b715Smrg goto unwind; 5156747b715Smrg } 5166747b715Smrg break; 5176747b715Smrg case XIAttachSlave: 5186747b715Smrg { 5196747b715Smrg xXIAttachSlaveInfo* c = (xXIAttachSlaveInfo*)any; 5206747b715Smrg 5210b0d8713Smrg CHANGE_SIZE_MATCH(xXIAttachSlaveInfo); 5229ace9065Smrg rc = attach_slave(client, c, flags); 5236747b715Smrg if (rc != Success) 5246747b715Smrg goto unwind; 5256747b715Smrg } 5266747b715Smrg break; 5276747b715Smrg } 5286747b715Smrg 5290b0d8713Smrg len -= any->length * 4; 5306747b715Smrg any = (xXIAnyHierarchyChangeInfo*)((char*)any + any->length * 4); 5316747b715Smrg } 5326747b715Smrg 5336747b715Smrgunwind: 5346747b715Smrg 5356747b715Smrg XISendDeviceHierarchyEvent(flags); 5366747b715Smrg return rc; 5376747b715Smrg} 5386747b715Smrg 539