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