596 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			596 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * Copyright © 2009 Red Hat, Inc.
 | 
						|
 *
 | 
						|
 * Permission is hereby granted, free of charge, to any person obtaining a
 | 
						|
 * copy of this software and associated documentation files (the "Software"),
 | 
						|
 * to deal in the Software without restriction, including without limitation
 | 
						|
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | 
						|
 * and/or sell copies of the Software, and to permit persons to whom the
 | 
						|
 * Software is furnished to do so, subject to the following conditions:
 | 
						|
 *
 | 
						|
 * The above copyright notice and this permission notice (including the next
 | 
						|
 * paragraph) shall be included in all copies or substantial portions of the
 | 
						|
 * Software.
 | 
						|
 *
 | 
						|
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 | 
						|
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
						|
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
						|
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 | 
						|
 * DEALINGS IN THE SOFTWARE.
 | 
						|
 *
 | 
						|
 * Authors: Peter Hutterer
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
/**
 | 
						|
 * @file Protocol handling for the XIQueryDevice request/reply.
 | 
						|
 */
 | 
						|
 | 
						|
#ifdef HAVE_DIX_CONFIG_H
 | 
						|
#include <dix-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include "inputstr.h"
 | 
						|
#include <X11/X.h>
 | 
						|
#include <X11/Xatom.h>
 | 
						|
#include <X11/extensions/XI2proto.h>
 | 
						|
#include "xkbstr.h"
 | 
						|
#include "xkbsrv.h"
 | 
						|
#include "xserver-properties.h"
 | 
						|
#include "exevents.h"
 | 
						|
#include "xace.h"
 | 
						|
#include "inpututils.h"
 | 
						|
 | 
						|
#include "xiquerydevice.h"
 | 
						|
 | 
						|
static Bool ShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr d);
 | 
						|
static int
 | 
						|
 ListDeviceInfo(ClientPtr client, DeviceIntPtr dev, xXIDeviceInfo * info);
 | 
						|
static int SizeDeviceInfo(DeviceIntPtr dev);
 | 
						|
static void SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo * info);
 | 
						|
int
 | 
						|
SProcXIQueryDevice(ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST(xXIQueryDeviceReq);
 | 
						|
 | 
						|
    swaps(&stuff->length);
 | 
						|
    swaps(&stuff->deviceid);
 | 
						|
 | 
						|
    return ProcXIQueryDevice(client);
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
ProcXIQueryDevice(ClientPtr client)
 | 
						|
{
 | 
						|
    xXIQueryDeviceReply rep;
 | 
						|
    DeviceIntPtr dev = NULL;
 | 
						|
    int rc = Success;
 | 
						|
    int i = 0, len = 0;
 | 
						|
    char *info, *ptr;
 | 
						|
    Bool *skip = NULL;
 | 
						|
 | 
						|
    REQUEST(xXIQueryDeviceReq);
 | 
						|
    REQUEST_SIZE_MATCH(xXIQueryDeviceReq);
 | 
						|
 | 
						|
    if (stuff->deviceid != XIAllDevices &&
 | 
						|
        stuff->deviceid != XIAllMasterDevices) {
 | 
						|
        rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess);
 | 
						|
        if (rc != Success) {
 | 
						|
            client->errorValue = stuff->deviceid;
 | 
						|
            return rc;
 | 
						|
        }
 | 
						|
        len += SizeDeviceInfo(dev);
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        skip = calloc(sizeof(Bool), inputInfo.numDevices);
 | 
						|
        if (!skip)
 | 
						|
            return BadAlloc;
 | 
						|
 | 
						|
        for (dev = inputInfo.devices; dev; dev = dev->next, i++) {
 | 
						|
            skip[i] = ShouldSkipDevice(client, stuff->deviceid, dev);
 | 
						|
            if (!skip[i])
 | 
						|
                len += SizeDeviceInfo(dev);
 | 
						|
        }
 | 
						|
 | 
						|
        for (dev = inputInfo.off_devices; dev; dev = dev->next, i++) {
 | 
						|
            skip[i] = ShouldSkipDevice(client, stuff->deviceid, dev);
 | 
						|
            if (!skip[i])
 | 
						|
                len += SizeDeviceInfo(dev);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    info = calloc(1, len);
 | 
						|
    if (!info) {
 | 
						|
        free(skip);
 | 
						|
        return BadAlloc;
 | 
						|
    }
 | 
						|
 | 
						|
    rep = (xXIQueryDeviceReply) {
 | 
						|
        .repType = X_Reply,
 | 
						|
        .RepType = X_XIQueryDevice,
 | 
						|
        .sequenceNumber = client->sequence,
 | 
						|
        .length = len / 4,
 | 
						|
        .num_devices = 0
 | 
						|
    };
 | 
						|
 | 
						|
    ptr = info;
 | 
						|
    if (dev) {
 | 
						|
        len = ListDeviceInfo(client, dev, (xXIDeviceInfo *) info);
 | 
						|
        if (client->swapped)
 | 
						|
            SwapDeviceInfo(dev, (xXIDeviceInfo *) info);
 | 
						|
        info += len;
 | 
						|
        rep.num_devices = 1;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        i = 0;
 | 
						|
        for (dev = inputInfo.devices; dev; dev = dev->next, i++) {
 | 
						|
            if (!skip[i]) {
 | 
						|
                len = ListDeviceInfo(client, dev, (xXIDeviceInfo *) info);
 | 
						|
                if (client->swapped)
 | 
						|
                    SwapDeviceInfo(dev, (xXIDeviceInfo *) info);
 | 
						|
                info += len;
 | 
						|
                rep.num_devices++;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        for (dev = inputInfo.off_devices; dev; dev = dev->next, i++) {
 | 
						|
            if (!skip[i]) {
 | 
						|
                len = ListDeviceInfo(client, dev, (xXIDeviceInfo *) info);
 | 
						|
                if (client->swapped)
 | 
						|
                    SwapDeviceInfo(dev, (xXIDeviceInfo *) info);
 | 
						|
                info += len;
 | 
						|
                rep.num_devices++;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    len = rep.length * 4;
 | 
						|
    WriteReplyToClient(client, sizeof(xXIQueryDeviceReply), &rep);
 | 
						|
    WriteToClient(client, len, ptr);
 | 
						|
    free(ptr);
 | 
						|
    free(skip);
 | 
						|
    return rc;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
SRepXIQueryDevice(ClientPtr client, int size, xXIQueryDeviceReply * rep)
 | 
						|
{
 | 
						|
    swaps(&rep->sequenceNumber);
 | 
						|
    swapl(&rep->length);
 | 
						|
    swaps(&rep->num_devices);
 | 
						|
 | 
						|
    /* Device info is already swapped, see ProcXIQueryDevice */
 | 
						|
 | 
						|
    WriteToClient(client, size, rep);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @return Whether the device should be included in the returned list.
 | 
						|
 */
 | 
						|
static Bool
 | 
						|
ShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr dev)
 | 
						|
{
 | 
						|
    /* if all devices are not being queried, only master devices are */
 | 
						|
    if (deviceid == XIAllDevices || IsMaster(dev)) {
 | 
						|
        int rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess);
 | 
						|
 | 
						|
        if (rc == Success)
 | 
						|
            return FALSE;
 | 
						|
    }
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @return The number of bytes needed to store this device's xXIDeviceInfo
 | 
						|
 * (and its classes).
 | 
						|
 */
 | 
						|
static int
 | 
						|
SizeDeviceInfo(DeviceIntPtr dev)
 | 
						|
{
 | 
						|
    int len = sizeof(xXIDeviceInfo);
 | 
						|
 | 
						|
    /* 4-padded name */
 | 
						|
    len += pad_to_int32(strlen(dev->name));
 | 
						|
 | 
						|
    return len + SizeDeviceClasses(dev);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * @return The number of bytes needed to store this device's classes.
 | 
						|
 */
 | 
						|
int
 | 
						|
SizeDeviceClasses(DeviceIntPtr dev)
 | 
						|
{
 | 
						|
    int len = 0;
 | 
						|
 | 
						|
    if (dev->button) {
 | 
						|
        len += sizeof(xXIButtonInfo);
 | 
						|
        len += dev->button->numButtons * sizeof(Atom);
 | 
						|
        len += pad_to_int32(bits_to_bytes(dev->button->numButtons));
 | 
						|
    }
 | 
						|
 | 
						|
    if (dev->key) {
 | 
						|
        XkbDescPtr xkb = dev->key->xkbInfo->desc;
 | 
						|
 | 
						|
        len += sizeof(xXIKeyInfo);
 | 
						|
        len += (xkb->max_key_code - xkb->min_key_code + 1) * sizeof(uint32_t);
 | 
						|
    }
 | 
						|
 | 
						|
    if (dev->valuator) {
 | 
						|
        int i;
 | 
						|
 | 
						|
        len += (sizeof(xXIValuatorInfo)) * dev->valuator->numAxes;
 | 
						|
 | 
						|
        for (i = 0; i < dev->valuator->numAxes; i++) {
 | 
						|
            if (dev->valuator->axes[i].scroll.type != SCROLL_TYPE_NONE)
 | 
						|
                len += sizeof(xXIScrollInfo);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (dev->touch)
 | 
						|
        len += sizeof(xXITouchInfo);
 | 
						|
 | 
						|
    return len;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Write button information into info.
 | 
						|
 * @return Number of bytes written into info.
 | 
						|
 */
 | 
						|
int
 | 
						|
ListButtonInfo(DeviceIntPtr dev, xXIButtonInfo * info, Bool reportState)
 | 
						|
{
 | 
						|
    unsigned char *bits;
 | 
						|
    int mask_len;
 | 
						|
    int i;
 | 
						|
 | 
						|
    if (!dev || !dev->button)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    mask_len = bytes_to_int32(bits_to_bytes(dev->button->numButtons));
 | 
						|
 | 
						|
    info->type = ButtonClass;
 | 
						|
    info->num_buttons = dev->button->numButtons;
 | 
						|
    info->length = bytes_to_int32(sizeof(xXIButtonInfo)) +
 | 
						|
        info->num_buttons + mask_len;
 | 
						|
    info->sourceid = dev->button->sourceid;
 | 
						|
 | 
						|
    bits = (unsigned char *) &info[1];
 | 
						|
    memset(bits, 0, mask_len * 4);
 | 
						|
 | 
						|
    if (reportState)
 | 
						|
        for (i = 0; i < dev->button->numButtons; i++)
 | 
						|
            if (BitIsOn(dev->button->down, i))
 | 
						|
                SetBit(bits, i);
 | 
						|
 | 
						|
    bits += mask_len * 4;
 | 
						|
    memcpy(bits, dev->button->labels, dev->button->numButtons * sizeof(Atom));
 | 
						|
 | 
						|
    return info->length * 4;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
SwapButtonInfo(DeviceIntPtr dev, xXIButtonInfo * info)
 | 
						|
{
 | 
						|
    Atom *btn;
 | 
						|
    int i;
 | 
						|
 | 
						|
    swaps(&info->type);
 | 
						|
    swaps(&info->length);
 | 
						|
    swaps(&info->sourceid);
 | 
						|
 | 
						|
    for (i = 0, btn = (Atom *) &info[1]; i < info->num_buttons; i++, btn++)
 | 
						|
        swapl(btn);
 | 
						|
 | 
						|
    swaps(&info->num_buttons);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Write key information into info.
 | 
						|
 * @return Number of bytes written into info.
 | 
						|
 */
 | 
						|
int
 | 
						|
ListKeyInfo(DeviceIntPtr dev, xXIKeyInfo * info)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    XkbDescPtr xkb = dev->key->xkbInfo->desc;
 | 
						|
    uint32_t *kc;
 | 
						|
 | 
						|
    info->type = KeyClass;
 | 
						|
    info->num_keycodes = xkb->max_key_code - xkb->min_key_code + 1;
 | 
						|
    info->length = sizeof(xXIKeyInfo) / 4 + info->num_keycodes;
 | 
						|
    info->sourceid = dev->key->sourceid;
 | 
						|
 | 
						|
    kc = (uint32_t *) &info[1];
 | 
						|
    for (i = xkb->min_key_code; i <= xkb->max_key_code; i++, kc++)
 | 
						|
        *kc = i;
 | 
						|
 | 
						|
    return info->length * 4;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
SwapKeyInfo(DeviceIntPtr dev, xXIKeyInfo * info)
 | 
						|
{
 | 
						|
    uint32_t *key;
 | 
						|
    int i;
 | 
						|
 | 
						|
    swaps(&info->type);
 | 
						|
    swaps(&info->length);
 | 
						|
    swaps(&info->sourceid);
 | 
						|
 | 
						|
    for (i = 0, key = (uint32_t *) &info[1]; i < info->num_keycodes;
 | 
						|
         i++, key++)
 | 
						|
        swapl(key);
 | 
						|
 | 
						|
    swaps(&info->num_keycodes);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * List axis information for the given axis.
 | 
						|
 *
 | 
						|
 * @return The number of bytes written into info.
 | 
						|
 */
 | 
						|
int
 | 
						|
ListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo * info, int axisnumber,
 | 
						|
                 Bool reportState)
 | 
						|
{
 | 
						|
    ValuatorClassPtr v = dev->valuator;
 | 
						|
 | 
						|
    info->type = ValuatorClass;
 | 
						|
    info->length = sizeof(xXIValuatorInfo) / 4;
 | 
						|
    info->label = v->axes[axisnumber].label;
 | 
						|
    info->min.integral = v->axes[axisnumber].min_value;
 | 
						|
    info->min.frac = 0;
 | 
						|
    info->max.integral = v->axes[axisnumber].max_value;
 | 
						|
    info->max.frac = 0;
 | 
						|
    info->value = double_to_fp3232(v->axisVal[axisnumber]);
 | 
						|
    info->resolution = v->axes[axisnumber].resolution;
 | 
						|
    info->number = axisnumber;
 | 
						|
    info->mode = valuator_get_mode(dev, axisnumber);
 | 
						|
    info->sourceid = v->sourceid;
 | 
						|
 | 
						|
    if (!reportState)
 | 
						|
        info->value = info->min;
 | 
						|
 | 
						|
    return info->length * 4;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
SwapValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo * info)
 | 
						|
{
 | 
						|
    swaps(&info->type);
 | 
						|
    swaps(&info->length);
 | 
						|
    swapl(&info->label);
 | 
						|
    swapl(&info->min.integral);
 | 
						|
    swapl(&info->min.frac);
 | 
						|
    swapl(&info->max.integral);
 | 
						|
    swapl(&info->max.frac);
 | 
						|
    swaps(&info->number);
 | 
						|
    swaps(&info->sourceid);
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
ListScrollInfo(DeviceIntPtr dev, xXIScrollInfo * info, int axisnumber)
 | 
						|
{
 | 
						|
    ValuatorClassPtr v = dev->valuator;
 | 
						|
    AxisInfoPtr axis = &v->axes[axisnumber];
 | 
						|
 | 
						|
    if (axis->scroll.type == SCROLL_TYPE_NONE)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    info->type = XIScrollClass;
 | 
						|
    info->length = sizeof(xXIScrollInfo) / 4;
 | 
						|
    info->number = axisnumber;
 | 
						|
    switch (axis->scroll.type) {
 | 
						|
    case SCROLL_TYPE_VERTICAL:
 | 
						|
        info->scroll_type = XIScrollTypeVertical;
 | 
						|
        break;
 | 
						|
    case SCROLL_TYPE_HORIZONTAL:
 | 
						|
        info->scroll_type = XIScrollTypeHorizontal;
 | 
						|
        break;
 | 
						|
    default:
 | 
						|
        ErrorF("[Xi] Unknown scroll type %d. This is a bug.\n",
 | 
						|
               axis->scroll.type);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    info->increment = double_to_fp3232(axis->scroll.increment);
 | 
						|
    info->sourceid = v->sourceid;
 | 
						|
 | 
						|
    info->flags = 0;
 | 
						|
 | 
						|
    if (axis->scroll.flags & SCROLL_FLAG_DONT_EMULATE)
 | 
						|
        info->flags |= XIScrollFlagNoEmulation;
 | 
						|
    if (axis->scroll.flags & SCROLL_FLAG_PREFERRED)
 | 
						|
        info->flags |= XIScrollFlagPreferred;
 | 
						|
 | 
						|
    return info->length * 4;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
SwapScrollInfo(DeviceIntPtr dev, xXIScrollInfo * info)
 | 
						|
{
 | 
						|
    swaps(&info->type);
 | 
						|
    swaps(&info->length);
 | 
						|
    swaps(&info->number);
 | 
						|
    swaps(&info->sourceid);
 | 
						|
    swaps(&info->scroll_type);
 | 
						|
    swapl(&info->increment.integral);
 | 
						|
    swapl(&info->increment.frac);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * List multitouch information
 | 
						|
 *
 | 
						|
 * @return The number of bytes written into info.
 | 
						|
 */
 | 
						|
int
 | 
						|
ListTouchInfo(DeviceIntPtr dev, xXITouchInfo * touch)
 | 
						|
{
 | 
						|
    touch->type = XITouchClass;
 | 
						|
    touch->length = sizeof(xXITouchInfo) >> 2;
 | 
						|
    touch->sourceid = dev->touch->sourceid;
 | 
						|
    touch->mode = dev->touch->mode;
 | 
						|
    touch->num_touches = dev->touch->num_touches;
 | 
						|
 | 
						|
    return touch->length << 2;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
SwapTouchInfo(DeviceIntPtr dev, xXITouchInfo * touch)
 | 
						|
{
 | 
						|
    swaps(&touch->type);
 | 
						|
    swaps(&touch->length);
 | 
						|
    swaps(&touch->sourceid);
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
GetDeviceUse(DeviceIntPtr dev, uint16_t * attachment)
 | 
						|
{
 | 
						|
    DeviceIntPtr master = GetMaster(dev, MASTER_ATTACHED);
 | 
						|
    int use;
 | 
						|
 | 
						|
    if (IsMaster(dev)) {
 | 
						|
        DeviceIntPtr paired = GetPairedDevice(dev);
 | 
						|
 | 
						|
        use = IsPointerDevice(dev) ? XIMasterPointer : XIMasterKeyboard;
 | 
						|
        *attachment = (paired ? paired->id : 0);
 | 
						|
    }
 | 
						|
    else if (!IsFloating(dev)) {
 | 
						|
        use = IsPointerDevice(master) ? XISlavePointer : XISlaveKeyboard;
 | 
						|
        *attachment = master->id;
 | 
						|
    }
 | 
						|
    else
 | 
						|
        use = XIFloatingSlave;
 | 
						|
 | 
						|
    return use;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Write the info for device dev into the buffer pointed to by info.
 | 
						|
 *
 | 
						|
 * @return The number of bytes used.
 | 
						|
 */
 | 
						|
static int
 | 
						|
ListDeviceInfo(ClientPtr client, DeviceIntPtr dev, xXIDeviceInfo * info)
 | 
						|
{
 | 
						|
    char *any = (char *) &info[1];
 | 
						|
    int len = 0, total_len = 0;
 | 
						|
 | 
						|
    info->deviceid = dev->id;
 | 
						|
    info->use = GetDeviceUse(dev, &info->attachment);
 | 
						|
    info->num_classes = 0;
 | 
						|
    info->name_len = strlen(dev->name);
 | 
						|
    info->enabled = dev->enabled;
 | 
						|
    total_len = sizeof(xXIDeviceInfo);
 | 
						|
 | 
						|
    len = pad_to_int32(info->name_len);
 | 
						|
    memset(any, 0, len);
 | 
						|
    strncpy(any, dev->name, info->name_len);
 | 
						|
    any += len;
 | 
						|
    total_len += len;
 | 
						|
 | 
						|
    total_len += ListDeviceClasses(client, dev, any, &info->num_classes);
 | 
						|
    return total_len;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Write the class info of the device into the memory pointed to by any, set
 | 
						|
 * nclasses to the number of classes in total and return the number of bytes
 | 
						|
 * written.
 | 
						|
 */
 | 
						|
int
 | 
						|
ListDeviceClasses(ClientPtr client, DeviceIntPtr dev,
 | 
						|
                  char *any, uint16_t * nclasses)
 | 
						|
{
 | 
						|
    int total_len = 0;
 | 
						|
    int len;
 | 
						|
    int i;
 | 
						|
    int rc;
 | 
						|
 | 
						|
    /* Check if the current device state should be suppressed */
 | 
						|
    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess);
 | 
						|
 | 
						|
    if (dev->button) {
 | 
						|
        (*nclasses)++;
 | 
						|
        len = ListButtonInfo(dev, (xXIButtonInfo *) any, rc == Success);
 | 
						|
        any += len;
 | 
						|
        total_len += len;
 | 
						|
    }
 | 
						|
 | 
						|
    if (dev->key) {
 | 
						|
        (*nclasses)++;
 | 
						|
        len = ListKeyInfo(dev, (xXIKeyInfo *) any);
 | 
						|
        any += len;
 | 
						|
        total_len += len;
 | 
						|
    }
 | 
						|
 | 
						|
    for (i = 0; dev->valuator && i < dev->valuator->numAxes; i++) {
 | 
						|
        (*nclasses)++;
 | 
						|
        len = ListValuatorInfo(dev, (xXIValuatorInfo *) any, i, rc == Success);
 | 
						|
        any += len;
 | 
						|
        total_len += len;
 | 
						|
    }
 | 
						|
 | 
						|
    for (i = 0; dev->valuator && i < dev->valuator->numAxes; i++) {
 | 
						|
        len = ListScrollInfo(dev, (xXIScrollInfo *) any, i);
 | 
						|
        if (len)
 | 
						|
            (*nclasses)++;
 | 
						|
        any += len;
 | 
						|
        total_len += len;
 | 
						|
    }
 | 
						|
 | 
						|
    if (dev->touch) {
 | 
						|
        (*nclasses)++;
 | 
						|
        len = ListTouchInfo(dev, (xXITouchInfo *) any);
 | 
						|
        any += len;
 | 
						|
        total_len += len;
 | 
						|
    }
 | 
						|
 | 
						|
    return total_len;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo * info)
 | 
						|
{
 | 
						|
    char *any = (char *) &info[1];
 | 
						|
    int i;
 | 
						|
 | 
						|
    /* Skip over name */
 | 
						|
    any += pad_to_int32(info->name_len);
 | 
						|
 | 
						|
    for (i = 0; i < info->num_classes; i++) {
 | 
						|
        int len = ((xXIAnyInfo *) any)->length;
 | 
						|
 | 
						|
        switch (((xXIAnyInfo *) any)->type) {
 | 
						|
        case XIButtonClass:
 | 
						|
            SwapButtonInfo(dev, (xXIButtonInfo *) any);
 | 
						|
            break;
 | 
						|
        case XIKeyClass:
 | 
						|
            SwapKeyInfo(dev, (xXIKeyInfo *) any);
 | 
						|
            break;
 | 
						|
        case XIValuatorClass:
 | 
						|
            SwapValuatorInfo(dev, (xXIValuatorInfo *) any);
 | 
						|
            break;
 | 
						|
        case XIScrollClass:
 | 
						|
            SwapScrollInfo(dev, (xXIScrollInfo *) any);
 | 
						|
            break;
 | 
						|
        case XITouchClass:
 | 
						|
            SwapTouchInfo(dev, (xXITouchInfo *) any);
 | 
						|
            break;
 | 
						|
 | 
						|
        }
 | 
						|
 | 
						|
        any += len * 4;
 | 
						|
    }
 | 
						|
 | 
						|
    swaps(&info->deviceid);
 | 
						|
    swaps(&info->use);
 | 
						|
    swaps(&info->attachment);
 | 
						|
    swaps(&info->num_classes);
 | 
						|
    swaps(&info->name_len);
 | 
						|
 | 
						|
}
 |