summaryrefslogtreecommitdiff
path: root/Xi/xiquerydevice.c
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2009-06-16 12:13:16 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2009-06-17 09:05:22 +1000
commitd230742ea820a21a3f1ed0c58b5e6d8680b2f2aa (patch)
treec1d736272599c1701aace889c82f0a1f48077b7d /Xi/xiquerydevice.c
parent4ddb002b6847e8a88e6f13ae0453a35ee79946ae (diff)
Xi: namespace XI2 files.
Some files (notably those merged with MPX before XI2 came along) didn't use a 'xi' prefix. This patch changes all of them to meaningful names. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Diffstat (limited to 'Xi/xiquerydevice.c')
-rw-r--r--Xi/xiquerydevice.c451
1 files changed, 451 insertions, 0 deletions
diff --git a/Xi/xiquerydevice.c b/Xi/xiquerydevice.c
new file mode 100644
index 000000000..07ddfa1cf
--- /dev/null
+++ b/Xi/xiquerydevice.c
@@ -0,0 +1,451 @@
+/*
+ * 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/extensions/XI2proto.h>
+#include "xkbstr.h"
+#include "xkbsrv.h"
+#include "xserver-properties.h"
+#include "exevents.h"
+
+#include "xiquerydevice.h"
+
+static int ListDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo* info);
+static int SizeDeviceInfo(DeviceIntPtr dev);
+static void SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo* info);
+int
+SProcXIQueryDevice(ClientPtr client)
+{
+ char n;
+
+ REQUEST(xXIQueryDeviceReq);
+
+ swaps(&stuff->length, n);
+ swaps(&stuff->deviceid, n);
+
+ return ProcXIQueryDevice(client);
+}
+
+int
+ProcXIQueryDevice(ClientPtr client)
+{
+ xXIQueryDeviceReply rep;
+ DeviceIntPtr dev = NULL;
+ int rc = Success;
+ int len = 0;
+ char *info, *ptr;
+
+ REQUEST(xXIQueryDeviceReq);
+ REQUEST_SIZE_MATCH(xXIQueryDeviceReq);
+
+ if (stuff->deviceid > 0xFF) /* FIXME */
+ {
+ client->errorValue = stuff->deviceid;
+ return BadImplementation;
+ }
+
+ if (stuff->deviceid != XIAllDevices && stuff->deviceid != XIAllMasterDevices)
+ {
+ rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess);
+ if (rc != Success)
+ {
+ client->errorValue = stuff->deviceid;
+ return rc;
+ }
+ }
+
+ if (dev)
+ len += SizeDeviceInfo(dev);
+ else
+ {
+ len = 0;
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ {
+ if (stuff->deviceid == XIAllDevices ||
+ (stuff->deviceid == XIAllMasterDevices && IsMaster(dev)))
+ len += SizeDeviceInfo(dev);
+ }
+
+ for (dev = inputInfo.off_devices; dev; dev = dev->next)
+ {
+ if (stuff->deviceid == XIAllDevices ||
+ (stuff->deviceid == XIAllMasterDevices && IsMaster(dev)))
+ len += SizeDeviceInfo(dev);
+ }
+
+ dev = NULL;
+ }
+
+ info = xcalloc(1, len);
+ if (!info)
+ return BadAlloc;
+
+ memset(&rep, 0, sizeof(xXIQueryDeviceReply));
+ rep.repType = X_Reply;
+ rep.RepType = X_XIQueryDevice;
+ rep.sequenceNumber = client->sequence;
+ rep.length = len/4;
+ rep.num_devices = 0;
+
+ ptr = info;
+ if (dev)
+ {
+ len = ListDeviceInfo(dev, (xXIDeviceInfo*)info);
+ if (client->swapped)
+ SwapDeviceInfo(dev, (xXIDeviceInfo*)info);
+ info += len;
+ rep.num_devices = 1;
+ } else
+ {
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ {
+ if (stuff->deviceid == XIAllDevices ||
+ (stuff->deviceid == XIAllMasterDevices && IsMaster(dev)))
+ {
+ len = ListDeviceInfo(dev, (xXIDeviceInfo*)info);
+ if (client->swapped)
+ SwapDeviceInfo(dev, (xXIDeviceInfo*)info);
+ info += len;
+ rep.num_devices++;
+ }
+ }
+
+ for (dev = inputInfo.off_devices; dev; dev = dev->next)
+ {
+ if (stuff->deviceid == XIAllDevices ||
+ (stuff->deviceid == XIAllMasterDevices && IsMaster(dev)))
+ {
+ len = ListDeviceInfo(dev, (xXIDeviceInfo*)info);
+ if (client->swapped)
+ SwapDeviceInfo(dev, (xXIDeviceInfo*)info);
+ info += len;
+ rep.num_devices++;
+ }
+ }
+ }
+
+ WriteReplyToClient(client, sizeof(xXIQueryDeviceReply), &rep);
+ WriteToClient(client, rep.length * 4, ptr);
+ return rc;
+}
+
+void
+SRepXIQueryDevice(ClientPtr client, int size, xXIQueryDeviceReply *rep)
+{
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swaps(&rep->num_devices, n);
+
+ /* Device info is already swapped, see ProcXIQueryDevice */
+
+ WriteToClient(client, size, (char *)rep);
+}
+
+
+
+/**
+ * @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 += (((strlen(dev->name) + 3)/4)*4);
+
+ 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);
+ }
+
+ 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)
+ len += sizeof(xXIValuatorInfo) * dev->valuator->numAxes;
+
+ return len;
+}
+
+
+/**
+ * Write button information into info.
+ * @return Number of bytes written into info.
+ */
+int
+ListButtonInfo(DeviceIntPtr dev, xXIButtonInfo* info)
+{
+ info->type = ButtonClass;
+ info->num_buttons = dev->button->numButtons;
+ info->length = 2 + info->num_buttons;
+
+ /** XXX: button labels */
+
+ return info->length * 4;
+}
+
+static void
+SwapButtonInfo(DeviceIntPtr dev, xXIButtonInfo* info)
+{
+ char n;
+ Atom *btn;
+ int i;
+ swaps(&info->type, n);
+ swaps(&info->length, n);
+
+ for (i = 0, btn = (Atom*)&info[1]; i < info->num_buttons; i++, btn++)
+ swaps(btn, n);
+
+ swaps(&info->num_buttons, n);
+}
+
+/**
+ * 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 = 2 + info->num_keycodes;
+
+ 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)
+{
+ char n;
+ uint32_t *key;
+ int i;
+ swaps(&info->type, n);
+ swaps(&info->length, n);
+
+ for (i = 0, key = (uint32_t*)&info[1]; i < info->num_keycodes; i++, key++)
+ swapl(key, n);
+
+ swaps(&info->num_keycodes, n);
+}
+
+/**
+ * List axis information for the given axis.
+ *
+ * @return The number of bytes written into info.
+ */
+int
+ListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info, int axisnumber)
+{
+ ValuatorClassPtr v = dev->valuator;
+
+ info->type = ValuatorClass;
+ info->length = sizeof(xXIValuatorInfo)/4;
+ info->name = XIGetKnownProperty(AXIS_LABEL_PROP_REL_MISC); /* XXX */
+ 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->resolution = v->axes[axisnumber].resolution;
+ info->number = axisnumber;
+ info->mode = v->mode; /* Server doesn't have per-axis mode yet */
+
+ return info->length * 4;
+}
+
+static void
+SwapValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info)
+{
+ char n;
+ swaps(&info->type, n);
+ swaps(&info->length, n);
+ swapl(&info->name, n);
+ swapl(&info->min.integral, n);
+ swapl(&info->min.frac, n);
+ swapl(&info->max.integral, n);
+ swapl(&info->max.frac, n);
+ swaps(&info->number, n);
+}
+
+int GetDeviceUse(DeviceIntPtr dev, uint16_t *attachment)
+{
+ DeviceIntPtr master = dev->u.master;
+ int use;
+
+ if (IsMaster(dev))
+ {
+ DeviceIntPtr paired = GetPairedDevice(dev);
+ use = IsPointerDevice(dev) ? XIMasterPointer : XIMasterKeyboard;
+ *attachment = (paired ? paired->id : 0);
+ } else if (master)
+ {
+ 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(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 = ((info->name_len + 3)/4) * 4;
+ memset(any, 0, len);
+ strncpy(any, dev->name, info->name_len);
+ any += len;
+ total_len += len;
+
+ return total_len + ListDeviceClasses(dev, any, &info->num_classes);
+}
+
+/**
+ * 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(DeviceIntPtr dev, char *any, uint16_t *nclasses)
+{
+ int total_len = 0;
+ int len;
+ int i;
+
+ if (dev->button)
+ {
+ (*nclasses)++;
+ len = ListButtonInfo(dev, (xXIButtonInfo*)any);
+ 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);
+ any += len;
+ total_len += len;
+ }
+
+ return total_len;
+}
+
+static void
+SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo* info)
+{
+ char n;
+ char *any = (char*)&info[1];
+ int i;
+
+ /* Skip over name */
+ any += (((info->name_len + 3)/4) * 4);
+
+ 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;
+ }
+
+ any += len * 4;
+ }
+
+ swaps(&info->deviceid, n);
+ swaps(&info->use, n);
+ swaps(&info->attachment, n);
+ swaps(&info->num_classes, n);
+ swaps(&info->name_len, n);
+
+}