xiquerydevice.c revision f7df2e56
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);
536747b715Smrgint
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
2406747b715Smrg/**
2416747b715Smrg * Write button information into info.
2426747b715Smrg * @return Number of bytes written into info.
2436747b715Smrg */
2446747b715Smrgint
245f7df2e56SmrgListButtonInfo(DeviceIntPtr dev, xXIButtonInfo * info, Bool reportState)
2466747b715Smrg{
2476747b715Smrg    unsigned char *bits;
2486747b715Smrg    int mask_len;
2496747b715Smrg    int i;
2506747b715Smrg
2516747b715Smrg    if (!dev || !dev->button)
252f7df2e56Smrg        return 0;
2536747b715Smrg
2546747b715Smrg    mask_len = bytes_to_int32(bits_to_bytes(dev->button->numButtons));
2556747b715Smrg
2566747b715Smrg    info->type = ButtonClass;
2576747b715Smrg    info->num_buttons = dev->button->numButtons;
2586747b715Smrg    info->length = bytes_to_int32(sizeof(xXIButtonInfo)) +
259f7df2e56Smrg        info->num_buttons + mask_len;
2606747b715Smrg    info->sourceid = dev->button->sourceid;
2616747b715Smrg
262f7df2e56Smrg    bits = (unsigned char *) &info[1];
2636747b715Smrg    memset(bits, 0, mask_len * 4);
2646747b715Smrg
2656747b715Smrg    if (reportState)
266f7df2e56Smrg        for (i = 0; i < dev->button->numButtons; i++)
267f7df2e56Smrg            if (BitIsOn(dev->button->down, i))
268f7df2e56Smrg                SetBit(bits, i);
2696747b715Smrg
2706747b715Smrg    bits += mask_len * 4;
2716747b715Smrg    memcpy(bits, dev->button->labels, dev->button->numButtons * sizeof(Atom));
2726747b715Smrg
2736747b715Smrg    return info->length * 4;
2746747b715Smrg}
2756747b715Smrg
2766747b715Smrgstatic void
277f7df2e56SmrgSwapButtonInfo(DeviceIntPtr dev, xXIButtonInfo * info)
2786747b715Smrg{
2796747b715Smrg    Atom *btn;
2806747b715Smrg    int i;
2816747b715Smrg
282f7df2e56Smrg    swaps(&info->type);
283f7df2e56Smrg    swaps(&info->length);
284f7df2e56Smrg    swaps(&info->sourceid);
285f7df2e56Smrg
286f7df2e56Smrg    for (i = 0, btn = (Atom *) &info[1]; i < info->num_buttons; i++, btn++)
287f7df2e56Smrg        swapl(btn);
2886747b715Smrg
289f7df2e56Smrg    swaps(&info->num_buttons);
2906747b715Smrg}
2916747b715Smrg
2926747b715Smrg/**
2936747b715Smrg * Write key information into info.
2946747b715Smrg * @return Number of bytes written into info.
2956747b715Smrg */
2966747b715Smrgint
297f7df2e56SmrgListKeyInfo(DeviceIntPtr dev, xXIKeyInfo * info)
2986747b715Smrg{
2996747b715Smrg    int i;
3006747b715Smrg    XkbDescPtr xkb = dev->key->xkbInfo->desc;
3016747b715Smrg    uint32_t *kc;
3026747b715Smrg
3036747b715Smrg    info->type = KeyClass;
3046747b715Smrg    info->num_keycodes = xkb->max_key_code - xkb->min_key_code + 1;
305f7df2e56Smrg    info->length = sizeof(xXIKeyInfo) / 4 + info->num_keycodes;
3066747b715Smrg    info->sourceid = dev->key->sourceid;
3076747b715Smrg
308f7df2e56Smrg    kc = (uint32_t *) &info[1];
3096747b715Smrg    for (i = xkb->min_key_code; i <= xkb->max_key_code; i++, kc++)
3106747b715Smrg        *kc = i;
3116747b715Smrg
3126747b715Smrg    return info->length * 4;
3136747b715Smrg}
3146747b715Smrg
3156747b715Smrgstatic void
316f7df2e56SmrgSwapKeyInfo(DeviceIntPtr dev, xXIKeyInfo * info)
3176747b715Smrg{
3186747b715Smrg    uint32_t *key;
3196747b715Smrg    int i;
3206747b715Smrg
321f7df2e56Smrg    swaps(&info->type);
322f7df2e56Smrg    swaps(&info->length);
323f7df2e56Smrg    swaps(&info->sourceid);
3246747b715Smrg
325f7df2e56Smrg    for (i = 0, key = (uint32_t *) &info[1]; i < info->num_keycodes;
326f7df2e56Smrg         i++, key++)
327f7df2e56Smrg        swapl(key);
328f7df2e56Smrg
329f7df2e56Smrg    swaps(&info->num_keycodes);
3306747b715Smrg}
3316747b715Smrg
3326747b715Smrg/**
3336747b715Smrg * List axis information for the given axis.
3346747b715Smrg *
3356747b715Smrg * @return The number of bytes written into info.
3366747b715Smrg */
3376747b715Smrgint
338f7df2e56SmrgListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo * info, int axisnumber,
339f7df2e56Smrg                 Bool reportState)
3406747b715Smrg{
3416747b715Smrg    ValuatorClassPtr v = dev->valuator;
3426747b715Smrg
3436747b715Smrg    info->type = ValuatorClass;
344f7df2e56Smrg    info->length = sizeof(xXIValuatorInfo) / 4;
3456747b715Smrg    info->label = v->axes[axisnumber].label;
3466747b715Smrg    info->min.integral = v->axes[axisnumber].min_value;
3476747b715Smrg    info->min.frac = 0;
3486747b715Smrg    info->max.integral = v->axes[axisnumber].max_value;
3496747b715Smrg    info->max.frac = 0;
350f7df2e56Smrg    info->value = double_to_fp3232(v->axisVal[axisnumber]);
3516747b715Smrg    info->resolution = v->axes[axisnumber].resolution;
3526747b715Smrg    info->number = axisnumber;
3539ace9065Smrg    info->mode = valuator_get_mode(dev, axisnumber);
3546747b715Smrg    info->sourceid = v->sourceid;
3556747b715Smrg
3566747b715Smrg    if (!reportState)
357f7df2e56Smrg        info->value = info->min;
3586747b715Smrg
3596747b715Smrg    return info->length * 4;
3606747b715Smrg}
3616747b715Smrg
3626747b715Smrgstatic void
363f7df2e56SmrgSwapValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo * info)
364f7df2e56Smrg{
365f7df2e56Smrg    swaps(&info->type);
366f7df2e56Smrg    swaps(&info->length);
367f7df2e56Smrg    swapl(&info->label);
368f7df2e56Smrg    swapl(&info->min.integral);
369f7df2e56Smrg    swapl(&info->min.frac);
370f7df2e56Smrg    swapl(&info->max.integral);
371f7df2e56Smrg    swapl(&info->max.frac);
372f7df2e56Smrg    swaps(&info->number);
373f7df2e56Smrg    swaps(&info->sourceid);
374f7df2e56Smrg}
375f7df2e56Smrg
376f7df2e56Smrgint
377f7df2e56SmrgListScrollInfo(DeviceIntPtr dev, xXIScrollInfo * info, int axisnumber)
3786747b715Smrg{
379f7df2e56Smrg    ValuatorClassPtr v = dev->valuator;
380f7df2e56Smrg    AxisInfoPtr axis = &v->axes[axisnumber];
381f7df2e56Smrg
382f7df2e56Smrg    if (axis->scroll.type == SCROLL_TYPE_NONE)
383f7df2e56Smrg        return 0;
384f7df2e56Smrg
385f7df2e56Smrg    info->type = XIScrollClass;
386f7df2e56Smrg    info->length = sizeof(xXIScrollInfo) / 4;
387f7df2e56Smrg    info->number = axisnumber;
388f7df2e56Smrg    switch (axis->scroll.type) {
389f7df2e56Smrg    case SCROLL_TYPE_VERTICAL:
390f7df2e56Smrg        info->scroll_type = XIScrollTypeVertical;
391f7df2e56Smrg        break;
392f7df2e56Smrg    case SCROLL_TYPE_HORIZONTAL:
393f7df2e56Smrg        info->scroll_type = XIScrollTypeHorizontal;
394f7df2e56Smrg        break;
395f7df2e56Smrg    default:
396f7df2e56Smrg        ErrorF("[Xi] Unknown scroll type %d. This is a bug.\n",
397f7df2e56Smrg               axis->scroll.type);
398f7df2e56Smrg        break;
399f7df2e56Smrg    }
400f7df2e56Smrg    info->increment = double_to_fp3232(axis->scroll.increment);
401f7df2e56Smrg    info->sourceid = v->sourceid;
402f7df2e56Smrg
403f7df2e56Smrg    info->flags = 0;
404f7df2e56Smrg
405f7df2e56Smrg    if (axis->scroll.flags & SCROLL_FLAG_DONT_EMULATE)
406f7df2e56Smrg        info->flags |= XIScrollFlagNoEmulation;
407f7df2e56Smrg    if (axis->scroll.flags & SCROLL_FLAG_PREFERRED)
408f7df2e56Smrg        info->flags |= XIScrollFlagPreferred;
409f7df2e56Smrg
410f7df2e56Smrg    return info->length * 4;
4116747b715Smrg}
4126747b715Smrg
413f7df2e56Smrgstatic void
414f7df2e56SmrgSwapScrollInfo(DeviceIntPtr dev, xXIScrollInfo * info)
4156747b715Smrg{
416f7df2e56Smrg    swaps(&info->type);
417f7df2e56Smrg    swaps(&info->length);
418f7df2e56Smrg    swaps(&info->number);
419f7df2e56Smrg    swaps(&info->sourceid);
420f7df2e56Smrg    swaps(&info->scroll_type);
421f7df2e56Smrg    swapl(&info->increment.integral);
422f7df2e56Smrg    swapl(&info->increment.frac);
423f7df2e56Smrg}
424f7df2e56Smrg
425f7df2e56Smrg/**
426f7df2e56Smrg * List multitouch information
427f7df2e56Smrg *
428f7df2e56Smrg * @return The number of bytes written into info.
429f7df2e56Smrg */
430f7df2e56Smrgint
431f7df2e56SmrgListTouchInfo(DeviceIntPtr dev, xXITouchInfo * touch)
432f7df2e56Smrg{
433f7df2e56Smrg    touch->type = XITouchClass;
434f7df2e56Smrg    touch->length = sizeof(xXITouchInfo) >> 2;
435f7df2e56Smrg    touch->sourceid = dev->touch->sourceid;
436f7df2e56Smrg    touch->mode = dev->touch->mode;
437f7df2e56Smrg    touch->num_touches = dev->touch->num_touches;
438f7df2e56Smrg
439f7df2e56Smrg    return touch->length << 2;
440f7df2e56Smrg}
441f7df2e56Smrg
442f7df2e56Smrgstatic void
443f7df2e56SmrgSwapTouchInfo(DeviceIntPtr dev, xXITouchInfo * touch)
444f7df2e56Smrg{
445f7df2e56Smrg    swaps(&touch->type);
446f7df2e56Smrg    swaps(&touch->length);
447f7df2e56Smrg    swaps(&touch->sourceid);
448f7df2e56Smrg}
449f7df2e56Smrg
450f7df2e56Smrgint
451f7df2e56SmrgGetDeviceUse(DeviceIntPtr dev, uint16_t * attachment)
452f7df2e56Smrg{
453f7df2e56Smrg    DeviceIntPtr master = GetMaster(dev, MASTER_ATTACHED);
4546747b715Smrg    int use;
4556747b715Smrg
456f7df2e56Smrg    if (IsMaster(dev)) {
4576747b715Smrg        DeviceIntPtr paired = GetPairedDevice(dev);
458f7df2e56Smrg
4596747b715Smrg        use = IsPointerDevice(dev) ? XIMasterPointer : XIMasterKeyboard;
4606747b715Smrg        *attachment = (paired ? paired->id : 0);
461f7df2e56Smrg    }
462f7df2e56Smrg    else if (!IsFloating(dev)) {
4636747b715Smrg        use = IsPointerDevice(master) ? XISlavePointer : XISlaveKeyboard;
4646747b715Smrg        *attachment = master->id;
465f7df2e56Smrg    }
466f7df2e56Smrg    else
4676747b715Smrg        use = XIFloatingSlave;
4686747b715Smrg
4696747b715Smrg    return use;
4706747b715Smrg}
4716747b715Smrg
4726747b715Smrg/**
4736747b715Smrg * Write the info for device dev into the buffer pointed to by info.
4746747b715Smrg *
4756747b715Smrg * @return The number of bytes used.
4766747b715Smrg */
4776747b715Smrgstatic int
478f7df2e56SmrgListDeviceInfo(ClientPtr client, DeviceIntPtr dev, xXIDeviceInfo * info)
4796747b715Smrg{
480f7df2e56Smrg    char *any = (char *) &info[1];
4816747b715Smrg    int len = 0, total_len = 0;
4826747b715Smrg
4836747b715Smrg    info->deviceid = dev->id;
4846747b715Smrg    info->use = GetDeviceUse(dev, &info->attachment);
4856747b715Smrg    info->num_classes = 0;
4866747b715Smrg    info->name_len = strlen(dev->name);
4876747b715Smrg    info->enabled = dev->enabled;
4886747b715Smrg    total_len = sizeof(xXIDeviceInfo);
4896747b715Smrg
4906747b715Smrg    len = pad_to_int32(info->name_len);
4916747b715Smrg    memset(any, 0, len);
4926747b715Smrg    strncpy(any, dev->name, info->name_len);
4936747b715Smrg    any += len;
4946747b715Smrg    total_len += len;
4956747b715Smrg
4966747b715Smrg    total_len += ListDeviceClasses(client, dev, any, &info->num_classes);
4976747b715Smrg    return total_len;
4986747b715Smrg}
4996747b715Smrg
5006747b715Smrg/**
5016747b715Smrg * Write the class info of the device into the memory pointed to by any, set
5026747b715Smrg * nclasses to the number of classes in total and return the number of bytes
5036747b715Smrg * written.
5046747b715Smrg */
5056747b715Smrgint
5066747b715SmrgListDeviceClasses(ClientPtr client, DeviceIntPtr dev,
507f7df2e56Smrg                  char *any, uint16_t * nclasses)
5086747b715Smrg{
5096747b715Smrg    int total_len = 0;
5106747b715Smrg    int len;
5116747b715Smrg    int i;
5126747b715Smrg    int rc;
5136747b715Smrg
5146747b715Smrg    /* Check if the current device state should be suppressed */
5156747b715Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess);
5166747b715Smrg
517f7df2e56Smrg    if (dev->button) {
5186747b715Smrg        (*nclasses)++;
519f7df2e56Smrg        len = ListButtonInfo(dev, (xXIButtonInfo *) any, rc == Success);
5206747b715Smrg        any += len;
5216747b715Smrg        total_len += len;
5226747b715Smrg    }
5236747b715Smrg
524f7df2e56Smrg    if (dev->key) {
5256747b715Smrg        (*nclasses)++;
526f7df2e56Smrg        len = ListKeyInfo(dev, (xXIKeyInfo *) any);
5276747b715Smrg        any += len;
5286747b715Smrg        total_len += len;
5296747b715Smrg    }
5306747b715Smrg
531f7df2e56Smrg    for (i = 0; dev->valuator && i < dev->valuator->numAxes; i++) {
5326747b715Smrg        (*nclasses)++;
533f7df2e56Smrg        len = ListValuatorInfo(dev, (xXIValuatorInfo *) any, i, rc == Success);
534f7df2e56Smrg        any += len;
535f7df2e56Smrg        total_len += len;
536f7df2e56Smrg    }
537f7df2e56Smrg
538f7df2e56Smrg    for (i = 0; dev->valuator && i < dev->valuator->numAxes; i++) {
539f7df2e56Smrg        len = ListScrollInfo(dev, (xXIScrollInfo *) any, i);
540f7df2e56Smrg        if (len)
541f7df2e56Smrg            (*nclasses)++;
542f7df2e56Smrg        any += len;
543f7df2e56Smrg        total_len += len;
544f7df2e56Smrg    }
545f7df2e56Smrg
546f7df2e56Smrg    if (dev->touch) {
547f7df2e56Smrg        (*nclasses)++;
548f7df2e56Smrg        len = ListTouchInfo(dev, (xXITouchInfo *) any);
5496747b715Smrg        any += len;
5506747b715Smrg        total_len += len;
5516747b715Smrg    }
5526747b715Smrg
5536747b715Smrg    return total_len;
5546747b715Smrg}
5556747b715Smrg
5566747b715Smrgstatic void
557f7df2e56SmrgSwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo * info)
5586747b715Smrg{
559f7df2e56Smrg    char *any = (char *) &info[1];
5606747b715Smrg    int i;
5616747b715Smrg
5626747b715Smrg    /* Skip over name */
5636747b715Smrg    any += pad_to_int32(info->name_len);
5646747b715Smrg
565f7df2e56Smrg    for (i = 0; i < info->num_classes; i++) {
566f7df2e56Smrg        int len = ((xXIAnyInfo *) any)->length;
567f7df2e56Smrg
568f7df2e56Smrg        switch (((xXIAnyInfo *) any)->type) {
569f7df2e56Smrg        case XIButtonClass:
570f7df2e56Smrg            SwapButtonInfo(dev, (xXIButtonInfo *) any);
571f7df2e56Smrg            break;
572f7df2e56Smrg        case XIKeyClass:
573f7df2e56Smrg            SwapKeyInfo(dev, (xXIKeyInfo *) any);
574f7df2e56Smrg            break;
575f7df2e56Smrg        case XIValuatorClass:
576f7df2e56Smrg            SwapValuatorInfo(dev, (xXIValuatorInfo *) any);
577f7df2e56Smrg            break;
578f7df2e56Smrg        case XIScrollClass:
579f7df2e56Smrg            SwapScrollInfo(dev, (xXIScrollInfo *) any);
580f7df2e56Smrg            break;
581f7df2e56Smrg        case XITouchClass:
582f7df2e56Smrg            SwapTouchInfo(dev, (xXITouchInfo *) any);
583f7df2e56Smrg            break;
584f7df2e56Smrg
5856747b715Smrg        }
5866747b715Smrg
5876747b715Smrg        any += len * 4;
5886747b715Smrg    }
5896747b715Smrg
590f7df2e56Smrg    swaps(&info->deviceid);
591f7df2e56Smrg    swaps(&info->use);
592f7df2e56Smrg    swaps(&info->attachment);
593f7df2e56Smrg    swaps(&info->num_classes);
594f7df2e56Smrg    swaps(&info->name_len);
5956747b715Smrg
5966747b715Smrg}
597