diff options
Diffstat (limited to 'xorg-server/Xi/listdev.c')
-rw-r--r-- | xorg-server/Xi/listdev.c | 381 |
1 files changed, 381 insertions, 0 deletions
diff --git a/xorg-server/Xi/listdev.c b/xorg-server/Xi/listdev.c new file mode 100644 index 000000000..041de7635 --- /dev/null +++ b/xorg-server/Xi/listdev.c @@ -0,0 +1,381 @@ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice 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 +OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Hewlett-Packard not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ + +/*********************************************************************** + * + * Extension function to list the available input devices. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> /* for inputstr.h */ +#include <X11/Xproto.h> /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include "XIstubs.h" +#include "extnsionst.h" +#include "exglobals.h" /* FIXME */ +#include "xace.h" + +#include "listdev.h" + +#define VPC 20 /* Max # valuators per chunk */ + +/*********************************************************************** + * + * This procedure lists the input devices available to the server. + * + */ + +int +SProcXListInputDevices(ClientPtr client) +{ + char n; + + REQUEST(xListInputDevicesReq); + swaps(&stuff->length, n); + return (ProcXListInputDevices(client)); +} + +/*********************************************************************** + * + * This procedure calculates the size of the information to be returned + * for an input device. + * + */ + +static void +SizeDeviceInfo(DeviceIntPtr d, int *namesize, int *size) +{ + int chunks; + + *namesize += 1; + if (d->name) + *namesize += strlen(d->name); + if (d->key != NULL) + *size += sizeof(xKeyInfo); + if (d->button != NULL) + *size += sizeof(xButtonInfo); + if (d->valuator != NULL) { + chunks = ((int)d->valuator->numAxes + 19) / VPC; + *size += (chunks * sizeof(xValuatorInfo) + + d->valuator->numAxes * sizeof(xAxisInfo)); + } +} + +/*********************************************************************** + * + * This procedure copies data to the DeviceInfo struct, swapping if necessary. + * + * We need the extra byte in the allocated buffer, because the trailing null + * hammers one extra byte, which is overwritten by the next name except for + * the last name copied. + * + */ + +static void +CopyDeviceName(char **namebuf, char *name) +{ + char *nameptr = (char *)*namebuf; + + if (name) { + *nameptr++ = strlen(name); + strcpy(nameptr, name); + *namebuf += (strlen(name) + 1); + } else { + *nameptr++ = 0; + *namebuf += 1; + } +} + +/*********************************************************************** + * + * This procedure copies ButtonClass information, swapping if necessary. + * + */ + +static void +CopySwapButtonClass(ClientPtr client, ButtonClassPtr b, char **buf) +{ + char n; + xButtonInfoPtr b2; + + b2 = (xButtonInfoPtr) * buf; + b2->class = ButtonClass; + b2->length = sizeof(xButtonInfo); + b2->num_buttons = b->numButtons; + if (client->swapped) { + swaps(&b2->num_buttons, n); /* macro - braces are required */ + } + *buf += sizeof(xButtonInfo); +} + +/*********************************************************************** + * + * This procedure copies data to the DeviceInfo struct, swapping if necessary. + * + */ + +static void +CopySwapDevice(ClientPtr client, DeviceIntPtr d, int num_classes, + char **buf) +{ + char n; + xDeviceInfoPtr dev; + + dev = (xDeviceInfoPtr) * buf; + + dev->id = d->id; + dev->type = d->type; + dev->num_classes = num_classes; + if (d == inputInfo.keyboard) + dev->use = IsXKeyboard; + else if (d == inputInfo.pointer) + dev->use = IsXPointer; + else if (d->key && d->kbdfeed) + dev->use = IsXExtensionKeyboard; + else if (d->valuator && d->button) + dev->use = IsXExtensionPointer; + else + dev->use = IsXExtensionDevice; + if (client->swapped) { + swapl(&dev->type, n); /* macro - braces are required */ + } + *buf += sizeof(xDeviceInfo); +} + +/*********************************************************************** + * + * This procedure copies KeyClass information, swapping if necessary. + * + */ + +static void +CopySwapKeyClass(ClientPtr client, KeyClassPtr k, char **buf) +{ + char n; + xKeyInfoPtr k2; + + k2 = (xKeyInfoPtr) * buf; + k2->class = KeyClass; + k2->length = sizeof(xKeyInfo); + k2->min_keycode = k->curKeySyms.minKeyCode; + k2->max_keycode = k->curKeySyms.maxKeyCode; + k2->num_keys = k2->max_keycode - k2->min_keycode + 1; + if (client->swapped) { + swaps(&k2->num_keys, n); + } + *buf += sizeof(xKeyInfo); +} + +/*********************************************************************** + * + * This procedure copies ValuatorClass information, swapping if necessary. + * + * Devices may have up to 255 valuators. The length of a ValuatorClass is + * defined to be sizeof(ValuatorClassInfo) + num_axes * sizeof (xAxisInfo). + * The maximum length is therefore (8 + 255 * 12) = 3068. However, the + * length field is one byte. If a device has more than 20 valuators, we + * must therefore return multiple valuator classes to the client. + * + */ + +static int +CopySwapValuatorClass(ClientPtr client, ValuatorClassPtr v, char **buf) +{ + int i, j, axes, t_axes; + char n; + xValuatorInfoPtr v2; + AxisInfo *a; + xAxisInfoPtr a2; + + for (i = 0, axes = v->numAxes; i < ((v->numAxes + 19) / VPC); + i++, axes -= VPC) { + t_axes = axes < VPC ? axes : VPC; + if (t_axes < 0) + t_axes = v->numAxes % VPC; + v2 = (xValuatorInfoPtr) * buf; + v2->class = ValuatorClass; + v2->length = sizeof(xValuatorInfo) + t_axes * sizeof(xAxisInfo); + v2->num_axes = t_axes; + v2->mode = v->mode & DeviceMode; + v2->motion_buffer_size = v->numMotionEvents; + if (client->swapped) { + swapl(&v2->motion_buffer_size, n); + } + *buf += sizeof(xValuatorInfo); + a = v->axes + (VPC * i); + a2 = (xAxisInfoPtr) * buf; + for (j = 0; j < t_axes; j++) { + a2->min_value = a->min_value; + a2->max_value = a->max_value; + a2->resolution = a->resolution; + if (client->swapped) { + swapl(&a2->min_value, n); + swapl(&a2->max_value, n); + swapl(&a2->resolution, n); + } + a2++; + a++; + *buf += sizeof(xAxisInfo); + } + } + return (i); +} + +/*********************************************************************** + * + * This procedure lists information to be returned for an input device. + * + */ + +static void +ListDeviceInfo(ClientPtr client, DeviceIntPtr d, xDeviceInfoPtr dev, + char **devbuf, char **classbuf, char **namebuf) +{ + CopyDeviceName(namebuf, d->name); + CopySwapDevice(client, d, 0, devbuf); + if (d->key != NULL) { + CopySwapKeyClass(client, d->key, classbuf); + dev->num_classes++; + } + if (d->button != NULL) { + CopySwapButtonClass(client, d->button, classbuf); + dev->num_classes++; + } + if (d->valuator != NULL) { + dev->num_classes += + CopySwapValuatorClass(client, d->valuator, classbuf); + } +} + +/*********************************************************************** + * + * This procedure lists the input devices available to the server. + * + */ + +int +ProcXListInputDevices(ClientPtr client) +{ + xListInputDevicesReply rep; + int numdevs = 0; + int namesize = 1; /* need 1 extra byte for strcpy */ + int rc, size = 0; + int total_length; + char *devbuf; + char *classbuf; + char *namebuf; + char *savbuf; + xDeviceInfo *dev; + DeviceIntPtr d; + + REQUEST_SIZE_MATCH(xListInputDevicesReq); + + rep.repType = X_Reply; + rep.RepType = X_ListInputDevices; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + AddOtherInputDevices(); + + for (d = inputInfo.devices; d; d = d->next) { + rc = XaceHook(XACE_DEVICE_ACCESS, client, d, DixGetAttrAccess); + if (rc != Success) + return rc; + SizeDeviceInfo(d, &namesize, &size); + numdevs++; + } + for (d = inputInfo.off_devices; d; d = d->next) { + rc = XaceHook(XACE_DEVICE_ACCESS, client, d, DixGetAttrAccess); + if (rc != Success) + return rc; + SizeDeviceInfo(d, &namesize, &size); + numdevs++; + } + + total_length = numdevs * sizeof(xDeviceInfo) + size + namesize; + devbuf = (char *)xalloc(total_length); + classbuf = devbuf + (numdevs * sizeof(xDeviceInfo)); + namebuf = classbuf + size; + savbuf = devbuf; + + dev = (xDeviceInfoPtr) devbuf; + for (d = inputInfo.devices; d; d = d->next, dev++) + ListDeviceInfo(client, d, dev, &devbuf, &classbuf, &namebuf); + for (d = inputInfo.off_devices; d; d = d->next, dev++) + ListDeviceInfo(client, d, dev, &devbuf, &classbuf, &namebuf); + + rep.ndevices = numdevs; + rep.length = (total_length + 3) >> 2; + WriteReplyToClient(client, sizeof(xListInputDevicesReply), &rep); + WriteToClient(client, total_length, savbuf); + xfree(savbuf); + return Success; +} + +/*********************************************************************** + * + * This procedure writes the reply for the XListInputDevices function, + * if the client and server have a different byte ordering. + * + */ + +void +SRepXListInputDevices(ClientPtr client, int size, xListInputDevicesReply * rep) +{ + char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + WriteToClient(client, size, (char *)rep); +} |