xiquerydevice.c revision 7e31ba66
16747b715Smrg/* 26747b715Smrg * Copyright © 2009 Red Hat, Inc. 36747b715Smrg * 46747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a 56747b715Smrg * copy of this software and associated documentation files (the "Software"), 66747b715Smrg * to deal in the Software without restriction, including without limitation 76747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 86747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the 96747b715Smrg * Software is furnished to do so, subject to the following conditions: 106747b715Smrg * 116747b715Smrg * The above copyright notice and this permission notice (including the next 126747b715Smrg * paragraph) shall be included in all copies or substantial portions of the 136747b715Smrg * Software. 146747b715Smrg * 156747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 166747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 176747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 186747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 196747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 206747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 216747b715Smrg * DEALINGS IN THE SOFTWARE. 226747b715Smrg * 236747b715Smrg * Authors: Peter Hutterer 246747b715Smrg * 256747b715Smrg */ 266747b715Smrg 276747b715Smrg/** 286747b715Smrg * @file Protocol handling for the XIQueryDevice request/reply. 296747b715Smrg */ 306747b715Smrg 316747b715Smrg#ifdef HAVE_DIX_CONFIG_H 326747b715Smrg#include <dix-config.h> 336747b715Smrg#endif 346747b715Smrg 356747b715Smrg#include "inputstr.h" 366747b715Smrg#include <X11/X.h> 376747b715Smrg#include <X11/Xatom.h> 386747b715Smrg#include <X11/extensions/XI2proto.h> 396747b715Smrg#include "xkbstr.h" 406747b715Smrg#include "xkbsrv.h" 416747b715Smrg#include "xserver-properties.h" 426747b715Smrg#include "exevents.h" 436747b715Smrg#include "xace.h" 44f7df2e56Smrg#include "inpututils.h" 456747b715Smrg 466747b715Smrg#include "xiquerydevice.h" 476747b715Smrg 486747b715Smrgstatic Bool ShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr d); 496747b715Smrgstatic int 50f7df2e56Smrg ListDeviceInfo(ClientPtr client, DeviceIntPtr dev, xXIDeviceInfo * info); 516747b715Smrgstatic int SizeDeviceInfo(DeviceIntPtr dev); 52f7df2e56Smrgstatic void SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo * info); 537e31ba66Smrgint _X_COLD 546747b715SmrgSProcXIQueryDevice(ClientPtr client) 556747b715Smrg{ 566747b715Smrg REQUEST(xXIQueryDeviceReq); 570b0d8713Smrg REQUEST_SIZE_MATCH(xXIQueryDeviceReq); 586747b715Smrg 59f7df2e56Smrg swaps(&stuff->length); 60f7df2e56Smrg swaps(&stuff->deviceid); 616747b715Smrg 626747b715Smrg return ProcXIQueryDevice(client); 636747b715Smrg} 646747b715Smrg 656747b715Smrgint 666747b715SmrgProcXIQueryDevice(ClientPtr client) 676747b715Smrg{ 686747b715Smrg xXIQueryDeviceReply rep; 696747b715Smrg DeviceIntPtr dev = NULL; 706747b715Smrg int rc = Success; 716747b715Smrg int i = 0, len = 0; 726747b715Smrg char *info, *ptr; 736747b715Smrg Bool *skip = NULL; 746747b715Smrg 756747b715Smrg REQUEST(xXIQueryDeviceReq); 766747b715Smrg REQUEST_SIZE_MATCH(xXIQueryDeviceReq); 776747b715Smrg 78f7df2e56Smrg if (stuff->deviceid != XIAllDevices && 79f7df2e56Smrg stuff->deviceid != XIAllMasterDevices) { 806747b715Smrg rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess); 81f7df2e56Smrg if (rc != Success) { 826747b715Smrg client->errorValue = stuff->deviceid; 836747b715Smrg return rc; 846747b715Smrg } 856747b715Smrg len += SizeDeviceInfo(dev); 866747b715Smrg } 87f7df2e56Smrg else { 886747b715Smrg skip = calloc(sizeof(Bool), inputInfo.numDevices); 896747b715Smrg if (!skip) 906747b715Smrg return BadAlloc; 916747b715Smrg 92f7df2e56Smrg for (dev = inputInfo.devices; dev; dev = dev->next, i++) { 936747b715Smrg skip[i] = ShouldSkipDevice(client, stuff->deviceid, dev); 946747b715Smrg if (!skip[i]) 956747b715Smrg len += SizeDeviceInfo(dev); 966747b715Smrg } 976747b715Smrg 98f7df2e56Smrg for (dev = inputInfo.off_devices; dev; dev = dev->next, i++) { 996747b715Smrg skip[i] = ShouldSkipDevice(client, stuff->deviceid, dev); 1006747b715Smrg if (!skip[i]) 1016747b715Smrg len += SizeDeviceInfo(dev); 1026747b715Smrg } 1036747b715Smrg } 1046747b715Smrg 1056747b715Smrg info = calloc(1, len); 1069ace9065Smrg if (!info) { 1079ace9065Smrg free(skip); 1086747b715Smrg return BadAlloc; 1099ace9065Smrg } 1106747b715Smrg 111f7df2e56Smrg rep = (xXIQueryDeviceReply) { 112f7df2e56Smrg .repType = X_Reply, 113f7df2e56Smrg .RepType = X_XIQueryDevice, 114f7df2e56Smrg .sequenceNumber = client->sequence, 115f7df2e56Smrg .length = len / 4, 116f7df2e56Smrg .num_devices = 0 117f7df2e56Smrg }; 1186747b715Smrg 1196747b715Smrg ptr = info; 120f7df2e56Smrg if (dev) { 121f7df2e56Smrg len = ListDeviceInfo(client, dev, (xXIDeviceInfo *) info); 1226747b715Smrg if (client->swapped) 123f7df2e56Smrg SwapDeviceInfo(dev, (xXIDeviceInfo *) info); 1246747b715Smrg info += len; 1256747b715Smrg rep.num_devices = 1; 126f7df2e56Smrg } 127f7df2e56Smrg else { 1286747b715Smrg i = 0; 129f7df2e56Smrg for (dev = inputInfo.devices; dev; dev = dev->next, i++) { 130f7df2e56Smrg if (!skip[i]) { 131f7df2e56Smrg len = ListDeviceInfo(client, dev, (xXIDeviceInfo *) info); 1326747b715Smrg if (client->swapped) 133f7df2e56Smrg SwapDeviceInfo(dev, (xXIDeviceInfo *) info); 1346747b715Smrg info += len; 1356747b715Smrg rep.num_devices++; 1366747b715Smrg } 1376747b715Smrg } 1386747b715Smrg 139f7df2e56Smrg for (dev = inputInfo.off_devices; dev; dev = dev->next, i++) { 140f7df2e56Smrg if (!skip[i]) { 141f7df2e56Smrg len = ListDeviceInfo(client, dev, (xXIDeviceInfo *) info); 1426747b715Smrg if (client->swapped) 143f7df2e56Smrg SwapDeviceInfo(dev, (xXIDeviceInfo *) info); 1446747b715Smrg info += len; 1456747b715Smrg rep.num_devices++; 1466747b715Smrg } 1476747b715Smrg } 1486747b715Smrg } 1496747b715Smrg 1509ace9065Smrg len = rep.length * 4; 1516747b715Smrg WriteReplyToClient(client, sizeof(xXIQueryDeviceReply), &rep); 1529ace9065Smrg WriteToClient(client, len, ptr); 1536747b715Smrg free(ptr); 1546747b715Smrg free(skip); 1556747b715Smrg return rc; 1566747b715Smrg} 1576747b715Smrg 1586747b715Smrgvoid 159f7df2e56SmrgSRepXIQueryDevice(ClientPtr client, int size, xXIQueryDeviceReply * rep) 1606747b715Smrg{ 161f7df2e56Smrg swaps(&rep->sequenceNumber); 162f7df2e56Smrg swapl(&rep->length); 163f7df2e56Smrg swaps(&rep->num_devices); 1646747b715Smrg 1656747b715Smrg /* Device info is already swapped, see ProcXIQueryDevice */ 1666747b715Smrg 167f7df2e56Smrg WriteToClient(client, size, rep); 1686747b715Smrg} 1696747b715Smrg 1706747b715Smrg/** 1716747b715Smrg * @return Whether the device should be included in the returned list. 1726747b715Smrg */ 1736747b715Smrgstatic Bool 1746747b715SmrgShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr dev) 1756747b715Smrg{ 1766747b715Smrg /* if all devices are not being queried, only master devices are */ 177f7df2e56Smrg if (deviceid == XIAllDevices || IsMaster(dev)) { 1786747b715Smrg int rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess); 179f7df2e56Smrg 1806747b715Smrg if (rc == Success) 1816747b715Smrg return FALSE; 1826747b715Smrg } 1836747b715Smrg return TRUE; 1846747b715Smrg} 1856747b715Smrg 1866747b715Smrg/** 1876747b715Smrg * @return The number of bytes needed to store this device's xXIDeviceInfo 1886747b715Smrg * (and its classes). 1896747b715Smrg */ 1906747b715Smrgstatic int 1916747b715SmrgSizeDeviceInfo(DeviceIntPtr dev) 1926747b715Smrg{ 1936747b715Smrg int len = sizeof(xXIDeviceInfo); 1946747b715Smrg 1956747b715Smrg /* 4-padded name */ 1966747b715Smrg len += pad_to_int32(strlen(dev->name)); 1976747b715Smrg 1986747b715Smrg return len + SizeDeviceClasses(dev); 1996747b715Smrg 2006747b715Smrg} 2016747b715Smrg 2026747b715Smrg/* 2036747b715Smrg * @return The number of bytes needed to store this device's classes. 2046747b715Smrg */ 2056747b715Smrgint 2066747b715SmrgSizeDeviceClasses(DeviceIntPtr dev) 2076747b715Smrg{ 2086747b715Smrg int len = 0; 2096747b715Smrg 210f7df2e56Smrg if (dev->button) { 2116747b715Smrg len += sizeof(xXIButtonInfo); 2126747b715Smrg len += dev->button->numButtons * sizeof(Atom); 2136747b715Smrg len += pad_to_int32(bits_to_bytes(dev->button->numButtons)); 2146747b715Smrg } 2156747b715Smrg 216f7df2e56Smrg if (dev->key) { 2176747b715Smrg XkbDescPtr xkb = dev->key->xkbInfo->desc; 218f7df2e56Smrg 2196747b715Smrg len += sizeof(xXIKeyInfo); 2206747b715Smrg len += (xkb->max_key_code - xkb->min_key_code + 1) * sizeof(uint32_t); 2216747b715Smrg } 2226747b715Smrg 223f7df2e56Smrg if (dev->valuator) { 224f7df2e56Smrg int i; 225f7df2e56Smrg 226f7df2e56Smrg len += (sizeof(xXIValuatorInfo)) * dev->valuator->numAxes; 227f7df2e56Smrg 228f7df2e56Smrg for (i = 0; i < dev->valuator->numAxes; i++) { 229f7df2e56Smrg if (dev->valuator->axes[i].scroll.type != SCROLL_TYPE_NONE) 230f7df2e56Smrg len += sizeof(xXIScrollInfo); 231f7df2e56Smrg } 232f7df2e56Smrg } 233f7df2e56Smrg 234f7df2e56Smrg if (dev->touch) 235f7df2e56Smrg len += sizeof(xXITouchInfo); 2366747b715Smrg 2376747b715Smrg return len; 2386747b715Smrg} 2396747b715Smrg 2407e31ba66Smrg/** 2417e31ba66Smrg * Get pointers to button information areas holding button mask and labels. 2427e31ba66Smrg */ 2437e31ba66Smrgstatic void 2447e31ba66SmrgButtonInfoData(xXIButtonInfo *info, int *mask_words, unsigned char **mask, 2457e31ba66Smrg Atom **atoms) 2467e31ba66Smrg{ 2477e31ba66Smrg *mask_words = bytes_to_int32(bits_to_bytes(info->num_buttons)); 2487e31ba66Smrg *mask = (unsigned char*) &info[1]; 2497e31ba66Smrg *atoms = (Atom*) ((*mask) + (*mask_words) * 4); 2507e31ba66Smrg} 2517e31ba66Smrg 2526747b715Smrg/** 2536747b715Smrg * Write button information into info. 2546747b715Smrg * @return Number of bytes written into info. 2556747b715Smrg */ 2566747b715Smrgint 257f7df2e56SmrgListButtonInfo(DeviceIntPtr dev, xXIButtonInfo * info, Bool reportState) 2586747b715Smrg{ 2596747b715Smrg unsigned char *bits; 2607e31ba66Smrg Atom *labels; 2616747b715Smrg int mask_len; 2626747b715Smrg int i; 2636747b715Smrg 2646747b715Smrg if (!dev || !dev->button) 265f7df2e56Smrg return 0; 2666747b715Smrg 2676747b715Smrg info->type = ButtonClass; 2686747b715Smrg info->num_buttons = dev->button->numButtons; 2697e31ba66Smrg ButtonInfoData(info, &mask_len, &bits, &labels); 2706747b715Smrg info->length = bytes_to_int32(sizeof(xXIButtonInfo)) + 271f7df2e56Smrg info->num_buttons + mask_len; 2726747b715Smrg info->sourceid = dev->button->sourceid; 2736747b715Smrg 2746747b715Smrg memset(bits, 0, mask_len * 4); 2756747b715Smrg 2766747b715Smrg if (reportState) 277f7df2e56Smrg for (i = 0; i < dev->button->numButtons; i++) 278f7df2e56Smrg if (BitIsOn(dev->button->down, i)) 279f7df2e56Smrg SetBit(bits, i); 2806747b715Smrg 2817e31ba66Smrg memcpy(labels, dev->button->labels, dev->button->numButtons * sizeof(Atom)); 2826747b715Smrg 2836747b715Smrg return info->length * 4; 2846747b715Smrg} 2856747b715Smrg 2866747b715Smrgstatic void 287f7df2e56SmrgSwapButtonInfo(DeviceIntPtr dev, xXIButtonInfo * info) 2886747b715Smrg{ 2896747b715Smrg Atom *btn; 2907e31ba66Smrg int mask_len; 2917e31ba66Smrg unsigned char *mask; 2927e31ba66Smrg 2936747b715Smrg int i; 2947e31ba66Smrg ButtonInfoData(info, &mask_len, &mask, &btn); 2956747b715Smrg 296f7df2e56Smrg swaps(&info->type); 297f7df2e56Smrg swaps(&info->length); 298f7df2e56Smrg swaps(&info->sourceid); 299f7df2e56Smrg 3007e31ba66Smrg for (i = 0 ; i < info->num_buttons; i++, btn++) 301f7df2e56Smrg swapl(btn); 3026747b715Smrg 303f7df2e56Smrg swaps(&info->num_buttons); 3046747b715Smrg} 3056747b715Smrg 3066747b715Smrg/** 3076747b715Smrg * Write key information into info. 3086747b715Smrg * @return Number of bytes written into info. 3096747b715Smrg */ 3106747b715Smrgint 311f7df2e56SmrgListKeyInfo(DeviceIntPtr dev, xXIKeyInfo * info) 3126747b715Smrg{ 3136747b715Smrg int i; 3146747b715Smrg XkbDescPtr xkb = dev->key->xkbInfo->desc; 3156747b715Smrg uint32_t *kc; 3166747b715Smrg 3176747b715Smrg info->type = KeyClass; 3186747b715Smrg info->num_keycodes = xkb->max_key_code - xkb->min_key_code + 1; 319f7df2e56Smrg info->length = sizeof(xXIKeyInfo) / 4 + info->num_keycodes; 3206747b715Smrg info->sourceid = dev->key->sourceid; 3216747b715Smrg 322f7df2e56Smrg kc = (uint32_t *) &info[1]; 3236747b715Smrg for (i = xkb->min_key_code; i <= xkb->max_key_code; i++, kc++) 3246747b715Smrg *kc = i; 3256747b715Smrg 3266747b715Smrg return info->length * 4; 3276747b715Smrg} 3286747b715Smrg 3296747b715Smrgstatic void 330f7df2e56SmrgSwapKeyInfo(DeviceIntPtr dev, xXIKeyInfo * info) 3316747b715Smrg{ 3326747b715Smrg uint32_t *key; 3336747b715Smrg int i; 3346747b715Smrg 335f7df2e56Smrg swaps(&info->type); 336f7df2e56Smrg swaps(&info->length); 337f7df2e56Smrg swaps(&info->sourceid); 3386747b715Smrg 339f7df2e56Smrg for (i = 0, key = (uint32_t *) &info[1]; i < info->num_keycodes; 340f7df2e56Smrg i++, key++) 341f7df2e56Smrg swapl(key); 342f7df2e56Smrg 343f7df2e56Smrg swaps(&info->num_keycodes); 3446747b715Smrg} 3456747b715Smrg 3466747b715Smrg/** 3476747b715Smrg * List axis information for the given axis. 3486747b715Smrg * 3496747b715Smrg * @return The number of bytes written into info. 3506747b715Smrg */ 3516747b715Smrgint 352f7df2e56SmrgListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo * info, int axisnumber, 353f7df2e56Smrg Bool reportState) 3546747b715Smrg{ 3556747b715Smrg ValuatorClassPtr v = dev->valuator; 3566747b715Smrg 3576747b715Smrg info->type = ValuatorClass; 358f7df2e56Smrg info->length = sizeof(xXIValuatorInfo) / 4; 3596747b715Smrg info->label = v->axes[axisnumber].label; 3606747b715Smrg info->min.integral = v->axes[axisnumber].min_value; 3616747b715Smrg info->min.frac = 0; 3626747b715Smrg info->max.integral = v->axes[axisnumber].max_value; 3636747b715Smrg info->max.frac = 0; 364f7df2e56Smrg info->value = double_to_fp3232(v->axisVal[axisnumber]); 3656747b715Smrg info->resolution = v->axes[axisnumber].resolution; 3666747b715Smrg info->number = axisnumber; 3679ace9065Smrg info->mode = valuator_get_mode(dev, axisnumber); 3686747b715Smrg info->sourceid = v->sourceid; 3696747b715Smrg 3706747b715Smrg if (!reportState) 371f7df2e56Smrg info->value = info->min; 3726747b715Smrg 3736747b715Smrg return info->length * 4; 3746747b715Smrg} 3756747b715Smrg 3766747b715Smrgstatic void 377f7df2e56SmrgSwapValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo * info) 378f7df2e56Smrg{ 379f7df2e56Smrg swaps(&info->type); 380f7df2e56Smrg swaps(&info->length); 381f7df2e56Smrg swapl(&info->label); 382f7df2e56Smrg swapl(&info->min.integral); 383f7df2e56Smrg swapl(&info->min.frac); 384f7df2e56Smrg swapl(&info->max.integral); 385f7df2e56Smrg swapl(&info->max.frac); 3867e31ba66Smrg swapl(&info->value.integral); 3877e31ba66Smrg swapl(&info->value.frac); 3887e31ba66Smrg swapl(&info->resolution); 389f7df2e56Smrg swaps(&info->number); 390f7df2e56Smrg swaps(&info->sourceid); 391f7df2e56Smrg} 392f7df2e56Smrg 393f7df2e56Smrgint 394f7df2e56SmrgListScrollInfo(DeviceIntPtr dev, xXIScrollInfo * info, int axisnumber) 3956747b715Smrg{ 396f7df2e56Smrg ValuatorClassPtr v = dev->valuator; 397f7df2e56Smrg AxisInfoPtr axis = &v->axes[axisnumber]; 398f7df2e56Smrg 399f7df2e56Smrg if (axis->scroll.type == SCROLL_TYPE_NONE) 400f7df2e56Smrg return 0; 401f7df2e56Smrg 402f7df2e56Smrg info->type = XIScrollClass; 403f7df2e56Smrg info->length = sizeof(xXIScrollInfo) / 4; 404f7df2e56Smrg info->number = axisnumber; 405f7df2e56Smrg switch (axis->scroll.type) { 406f7df2e56Smrg case SCROLL_TYPE_VERTICAL: 407f7df2e56Smrg info->scroll_type = XIScrollTypeVertical; 408f7df2e56Smrg break; 409f7df2e56Smrg case SCROLL_TYPE_HORIZONTAL: 410f7df2e56Smrg info->scroll_type = XIScrollTypeHorizontal; 411f7df2e56Smrg break; 412f7df2e56Smrg default: 413f7df2e56Smrg ErrorF("[Xi] Unknown scroll type %d. This is a bug.\n", 414f7df2e56Smrg axis->scroll.type); 415f7df2e56Smrg break; 416f7df2e56Smrg } 417f7df2e56Smrg info->increment = double_to_fp3232(axis->scroll.increment); 418f7df2e56Smrg info->sourceid = v->sourceid; 419f7df2e56Smrg 420f7df2e56Smrg info->flags = 0; 421f7df2e56Smrg 422f7df2e56Smrg if (axis->scroll.flags & SCROLL_FLAG_DONT_EMULATE) 423f7df2e56Smrg info->flags |= XIScrollFlagNoEmulation; 424f7df2e56Smrg if (axis->scroll.flags & SCROLL_FLAG_PREFERRED) 425f7df2e56Smrg info->flags |= XIScrollFlagPreferred; 426f7df2e56Smrg 427f7df2e56Smrg return info->length * 4; 4286747b715Smrg} 4296747b715Smrg 430f7df2e56Smrgstatic void 431f7df2e56SmrgSwapScrollInfo(DeviceIntPtr dev, xXIScrollInfo * info) 4326747b715Smrg{ 433f7df2e56Smrg swaps(&info->type); 434f7df2e56Smrg swaps(&info->length); 435f7df2e56Smrg swaps(&info->number); 436f7df2e56Smrg swaps(&info->sourceid); 437f7df2e56Smrg swaps(&info->scroll_type); 438f7df2e56Smrg swapl(&info->increment.integral); 439f7df2e56Smrg swapl(&info->increment.frac); 440f7df2e56Smrg} 441f7df2e56Smrg 442f7df2e56Smrg/** 443f7df2e56Smrg * List multitouch information 444f7df2e56Smrg * 445f7df2e56Smrg * @return The number of bytes written into info. 446f7df2e56Smrg */ 447f7df2e56Smrgint 448f7df2e56SmrgListTouchInfo(DeviceIntPtr dev, xXITouchInfo * touch) 449f7df2e56Smrg{ 450f7df2e56Smrg touch->type = XITouchClass; 451f7df2e56Smrg touch->length = sizeof(xXITouchInfo) >> 2; 452f7df2e56Smrg touch->sourceid = dev->touch->sourceid; 453f7df2e56Smrg touch->mode = dev->touch->mode; 454f7df2e56Smrg touch->num_touches = dev->touch->num_touches; 455f7df2e56Smrg 456f7df2e56Smrg return touch->length << 2; 457f7df2e56Smrg} 458f7df2e56Smrg 459f7df2e56Smrgstatic void 460f7df2e56SmrgSwapTouchInfo(DeviceIntPtr dev, xXITouchInfo * touch) 461f7df2e56Smrg{ 462f7df2e56Smrg swaps(&touch->type); 463f7df2e56Smrg swaps(&touch->length); 464f7df2e56Smrg swaps(&touch->sourceid); 465f7df2e56Smrg} 466f7df2e56Smrg 467f7df2e56Smrgint 468f7df2e56SmrgGetDeviceUse(DeviceIntPtr dev, uint16_t * attachment) 469f7df2e56Smrg{ 470f7df2e56Smrg DeviceIntPtr master = GetMaster(dev, MASTER_ATTACHED); 4716747b715Smrg int use; 4726747b715Smrg 473f7df2e56Smrg if (IsMaster(dev)) { 4746747b715Smrg DeviceIntPtr paired = GetPairedDevice(dev); 475f7df2e56Smrg 4766747b715Smrg use = IsPointerDevice(dev) ? XIMasterPointer : XIMasterKeyboard; 4776747b715Smrg *attachment = (paired ? paired->id : 0); 478f7df2e56Smrg } 479f7df2e56Smrg else if (!IsFloating(dev)) { 4806747b715Smrg use = IsPointerDevice(master) ? XISlavePointer : XISlaveKeyboard; 4816747b715Smrg *attachment = master->id; 482f7df2e56Smrg } 483f7df2e56Smrg else 4846747b715Smrg use = XIFloatingSlave; 4856747b715Smrg 4866747b715Smrg return use; 4876747b715Smrg} 4886747b715Smrg 4896747b715Smrg/** 4906747b715Smrg * Write the info for device dev into the buffer pointed to by info. 4916747b715Smrg * 4926747b715Smrg * @return The number of bytes used. 4936747b715Smrg */ 4946747b715Smrgstatic int 495f7df2e56SmrgListDeviceInfo(ClientPtr client, DeviceIntPtr dev, xXIDeviceInfo * info) 4966747b715Smrg{ 497f7df2e56Smrg char *any = (char *) &info[1]; 4986747b715Smrg int len = 0, total_len = 0; 4996747b715Smrg 5006747b715Smrg info->deviceid = dev->id; 5016747b715Smrg info->use = GetDeviceUse(dev, &info->attachment); 5026747b715Smrg info->num_classes = 0; 5036747b715Smrg info->name_len = strlen(dev->name); 5046747b715Smrg info->enabled = dev->enabled; 5056747b715Smrg total_len = sizeof(xXIDeviceInfo); 5066747b715Smrg 5076747b715Smrg len = pad_to_int32(info->name_len); 5086747b715Smrg memset(any, 0, len); 5096747b715Smrg strncpy(any, dev->name, info->name_len); 5106747b715Smrg any += len; 5116747b715Smrg total_len += len; 5126747b715Smrg 5136747b715Smrg total_len += ListDeviceClasses(client, dev, any, &info->num_classes); 5146747b715Smrg return total_len; 5156747b715Smrg} 5166747b715Smrg 5176747b715Smrg/** 5186747b715Smrg * Write the class info of the device into the memory pointed to by any, set 5196747b715Smrg * nclasses to the number of classes in total and return the number of bytes 5206747b715Smrg * written. 5216747b715Smrg */ 5226747b715Smrgint 5236747b715SmrgListDeviceClasses(ClientPtr client, DeviceIntPtr dev, 524f7df2e56Smrg char *any, uint16_t * nclasses) 5256747b715Smrg{ 5266747b715Smrg int total_len = 0; 5276747b715Smrg int len; 5286747b715Smrg int i; 5296747b715Smrg int rc; 5306747b715Smrg 5316747b715Smrg /* Check if the current device state should be suppressed */ 5326747b715Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess); 5336747b715Smrg 534f7df2e56Smrg if (dev->button) { 5356747b715Smrg (*nclasses)++; 536f7df2e56Smrg len = ListButtonInfo(dev, (xXIButtonInfo *) any, rc == Success); 5376747b715Smrg any += len; 5386747b715Smrg total_len += len; 5396747b715Smrg } 5406747b715Smrg 541f7df2e56Smrg if (dev->key) { 5426747b715Smrg (*nclasses)++; 543f7df2e56Smrg len = ListKeyInfo(dev, (xXIKeyInfo *) any); 5446747b715Smrg any += len; 5456747b715Smrg total_len += len; 5466747b715Smrg } 5476747b715Smrg 548f7df2e56Smrg for (i = 0; dev->valuator && i < dev->valuator->numAxes; i++) { 5496747b715Smrg (*nclasses)++; 550f7df2e56Smrg len = ListValuatorInfo(dev, (xXIValuatorInfo *) any, i, rc == Success); 551f7df2e56Smrg any += len; 552f7df2e56Smrg total_len += len; 553f7df2e56Smrg } 554f7df2e56Smrg 555f7df2e56Smrg for (i = 0; dev->valuator && i < dev->valuator->numAxes; i++) { 556f7df2e56Smrg len = ListScrollInfo(dev, (xXIScrollInfo *) any, i); 557f7df2e56Smrg if (len) 558f7df2e56Smrg (*nclasses)++; 559f7df2e56Smrg any += len; 560f7df2e56Smrg total_len += len; 561f7df2e56Smrg } 562f7df2e56Smrg 563f7df2e56Smrg if (dev->touch) { 564f7df2e56Smrg (*nclasses)++; 565f7df2e56Smrg len = ListTouchInfo(dev, (xXITouchInfo *) any); 5666747b715Smrg any += len; 5676747b715Smrg total_len += len; 5686747b715Smrg } 5696747b715Smrg 5706747b715Smrg return total_len; 5716747b715Smrg} 5726747b715Smrg 5736747b715Smrgstatic void 574f7df2e56SmrgSwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo * info) 5756747b715Smrg{ 576f7df2e56Smrg char *any = (char *) &info[1]; 5776747b715Smrg int i; 5786747b715Smrg 5796747b715Smrg /* Skip over name */ 5806747b715Smrg any += pad_to_int32(info->name_len); 5816747b715Smrg 582f7df2e56Smrg for (i = 0; i < info->num_classes; i++) { 583f7df2e56Smrg int len = ((xXIAnyInfo *) any)->length; 584f7df2e56Smrg 585f7df2e56Smrg switch (((xXIAnyInfo *) any)->type) { 586f7df2e56Smrg case XIButtonClass: 587f7df2e56Smrg SwapButtonInfo(dev, (xXIButtonInfo *) any); 588f7df2e56Smrg break; 589f7df2e56Smrg case XIKeyClass: 590f7df2e56Smrg SwapKeyInfo(dev, (xXIKeyInfo *) any); 591f7df2e56Smrg break; 592f7df2e56Smrg case XIValuatorClass: 593f7df2e56Smrg SwapValuatorInfo(dev, (xXIValuatorInfo *) any); 594f7df2e56Smrg break; 595f7df2e56Smrg case XIScrollClass: 596f7df2e56Smrg SwapScrollInfo(dev, (xXIScrollInfo *) any); 597f7df2e56Smrg break; 598f7df2e56Smrg case XITouchClass: 599f7df2e56Smrg SwapTouchInfo(dev, (xXITouchInfo *) any); 600f7df2e56Smrg break; 601f7df2e56Smrg 6026747b715Smrg } 6036747b715Smrg 6046747b715Smrg any += len * 4; 6056747b715Smrg } 6066747b715Smrg 607f7df2e56Smrg swaps(&info->deviceid); 608f7df2e56Smrg swaps(&info->use); 609f7df2e56Smrg swaps(&info->attachment); 610f7df2e56Smrg swaps(&info->num_classes); 611f7df2e56Smrg swaps(&info->name_len); 6126747b715Smrg 6136747b715Smrg} 614