#define NEED_EVENTS
#define NEED_REPLIES
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <X11/X.h>
#include <X11/Xproto.h>
#include "inputstr.h"
#include <X11/extensions/XI.h>
#include <X11/extensions/XIproto.h>
#include "XIstubs.h"
#include "extnsionst.h"
#include "exglobals.h"
#include "exevents.h"
#include "xace.h"
#include "listdev.h"
int
SProcXListInputDevices(ClientPtr client)
{
char n;
REQUEST(xListInputDevicesReq);
swaps(&stuff->length, n);
return (ProcXListInputDevices(client));
}
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));
}
}
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;
}
}
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 && client->swapped) {
swaps(&b2->num_buttons, n);
}
*buf += sizeof(xButtonInfo);
}
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->isMaster && IsKeyboardDevice(d))
dev->use = IsXKeyboard;
else if (d->isMaster && IsPointerDevice(d))
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);
}
*buf += sizeof(xDeviceInfo);
}
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 && client->swapped) {
swaps(&k2->num_keys, n);
}
*buf += sizeof(xKeyInfo);
}
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 && 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 && client->swapped) {
swapl(&a2->min_value, n);
swapl(&a2->max_value, n);
swapl(&a2->resolution, n);
}
a2++;
a++;
*buf += sizeof(xAxisInfo);
}
}
return (i);
}
static void
ListDeviceInfo(ClientPtr client, DeviceIntPtr d, xDeviceInfoPtr dev,
char **devbuf, char **classbuf, char **namebuf)
{
CopyDeviceName(namebuf, d->name);
CopySwapDevice(client, d, 0, devbuf);
CopySwapClasses(client, d, &dev->num_classes, classbuf);
}
void
CopySwapClasses(ClientPtr client, DeviceIntPtr dev, CARD8 *num_classes,
char** classbuf)
{
if (dev->key != NULL) {
CopySwapKeyClass(client, dev->key, classbuf);
(*num_classes)++;
}
if (dev->button != NULL) {
CopySwapButtonClass(client, dev->button, classbuf);
(*num_classes)++;
}
if (dev->valuator != NULL) {
(*num_classes) +=
CopySwapValuatorClass(client, dev->valuator, classbuf);
}
}
int
ProcXListInputDevices(ClientPtr client)
{
xListInputDevicesReply rep;
XIClientPtr pXIClient;
int numdevs = 0;
int namesize = 1;
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;
pXIClient = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
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)
{
ListDeviceInfo(client, d, dev++, &devbuf, &classbuf, &namebuf);
}
for (d = inputInfo.off_devices; d; d = d->next)
{
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;
}
void
SRepXListInputDevices(ClientPtr client, int size, xListInputDevicesReply * rep)
{
char n;
swaps(&rep->sequenceNumber, n);
swapl(&rep->length, n);
WriteToClient(client, size, (char *)rep);
}