1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright © 2009 Red Hat, Inc.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person obtaining a
5*4882a593Smuzhiyun * copy of this software and associated documentation files (the "Software"),
6*4882a593Smuzhiyun * to deal in the Software without restriction, including without limitation
7*4882a593Smuzhiyun * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*4882a593Smuzhiyun * and/or sell copies of the Software, and to permit persons to whom the
9*4882a593Smuzhiyun * Software is furnished to do so, subject to the following conditions:
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * The above copyright notice and this permission notice (including the next
12*4882a593Smuzhiyun * paragraph) shall be included in all copies or substantial portions of the
13*4882a593Smuzhiyun * Software.
14*4882a593Smuzhiyun *
15*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*4882a593Smuzhiyun * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*4882a593Smuzhiyun * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*4882a593Smuzhiyun * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*4882a593Smuzhiyun * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*4882a593Smuzhiyun * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21*4882a593Smuzhiyun * DEALINGS IN THE SOFTWARE.
22*4882a593Smuzhiyun *
23*4882a593Smuzhiyun * Authors: Peter Hutterer
24*4882a593Smuzhiyun *
25*4882a593Smuzhiyun */
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun /**
28*4882a593Smuzhiyun * @file Protocol handling for the XIQueryDevice request/reply.
29*4882a593Smuzhiyun */
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
32*4882a593Smuzhiyun #include <dix-config.h>
33*4882a593Smuzhiyun #endif
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #include "inputstr.h"
36*4882a593Smuzhiyun #include <X11/X.h>
37*4882a593Smuzhiyun #include <X11/Xatom.h>
38*4882a593Smuzhiyun #include <X11/extensions/XI2proto.h>
39*4882a593Smuzhiyun #include "xkbstr.h"
40*4882a593Smuzhiyun #include "xkbsrv.h"
41*4882a593Smuzhiyun #include "xserver-properties.h"
42*4882a593Smuzhiyun #include "exevents.h"
43*4882a593Smuzhiyun #include "xace.h"
44*4882a593Smuzhiyun #include "inpututils.h"
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun #include "xiquerydevice.h"
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun static Bool ShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr d);
49*4882a593Smuzhiyun static int
50*4882a593Smuzhiyun ListDeviceInfo(ClientPtr client, DeviceIntPtr dev, xXIDeviceInfo * info);
51*4882a593Smuzhiyun static int SizeDeviceInfo(DeviceIntPtr dev);
52*4882a593Smuzhiyun static void SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo * info);
53*4882a593Smuzhiyun int _X_COLD
SProcXIQueryDevice(ClientPtr client)54*4882a593Smuzhiyun SProcXIQueryDevice(ClientPtr client)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun REQUEST(xXIQueryDeviceReq);
57*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xXIQueryDeviceReq);
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun swaps(&stuff->length);
60*4882a593Smuzhiyun swaps(&stuff->deviceid);
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun return ProcXIQueryDevice(client);
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun int
ProcXIQueryDevice(ClientPtr client)66*4882a593Smuzhiyun ProcXIQueryDevice(ClientPtr client)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun xXIQueryDeviceReply rep;
69*4882a593Smuzhiyun DeviceIntPtr dev = NULL;
70*4882a593Smuzhiyun int rc = Success;
71*4882a593Smuzhiyun int i = 0, len = 0;
72*4882a593Smuzhiyun char *info, *ptr;
73*4882a593Smuzhiyun Bool *skip = NULL;
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun REQUEST(xXIQueryDeviceReq);
76*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xXIQueryDeviceReq);
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun if (stuff->deviceid != XIAllDevices &&
79*4882a593Smuzhiyun stuff->deviceid != XIAllMasterDevices) {
80*4882a593Smuzhiyun rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess);
81*4882a593Smuzhiyun if (rc != Success) {
82*4882a593Smuzhiyun client->errorValue = stuff->deviceid;
83*4882a593Smuzhiyun return rc;
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun len += SizeDeviceInfo(dev);
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun else {
88*4882a593Smuzhiyun skip = calloc(sizeof(Bool), inputInfo.numDevices);
89*4882a593Smuzhiyun if (!skip)
90*4882a593Smuzhiyun return BadAlloc;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun for (dev = inputInfo.devices; dev; dev = dev->next, i++) {
93*4882a593Smuzhiyun skip[i] = ShouldSkipDevice(client, stuff->deviceid, dev);
94*4882a593Smuzhiyun if (!skip[i])
95*4882a593Smuzhiyun len += SizeDeviceInfo(dev);
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun for (dev = inputInfo.off_devices; dev; dev = dev->next, i++) {
99*4882a593Smuzhiyun skip[i] = ShouldSkipDevice(client, stuff->deviceid, dev);
100*4882a593Smuzhiyun if (!skip[i])
101*4882a593Smuzhiyun len += SizeDeviceInfo(dev);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun info = calloc(1, len);
106*4882a593Smuzhiyun if (!info) {
107*4882a593Smuzhiyun free(skip);
108*4882a593Smuzhiyun return BadAlloc;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun rep = (xXIQueryDeviceReply) {
112*4882a593Smuzhiyun .repType = X_Reply,
113*4882a593Smuzhiyun .RepType = X_XIQueryDevice,
114*4882a593Smuzhiyun .sequenceNumber = client->sequence,
115*4882a593Smuzhiyun .length = len / 4,
116*4882a593Smuzhiyun .num_devices = 0
117*4882a593Smuzhiyun };
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun ptr = info;
120*4882a593Smuzhiyun if (dev) {
121*4882a593Smuzhiyun len = ListDeviceInfo(client, dev, (xXIDeviceInfo *) info);
122*4882a593Smuzhiyun if (client->swapped)
123*4882a593Smuzhiyun SwapDeviceInfo(dev, (xXIDeviceInfo *) info);
124*4882a593Smuzhiyun info += len;
125*4882a593Smuzhiyun rep.num_devices = 1;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun else {
128*4882a593Smuzhiyun i = 0;
129*4882a593Smuzhiyun for (dev = inputInfo.devices; dev; dev = dev->next, i++) {
130*4882a593Smuzhiyun if (!skip[i]) {
131*4882a593Smuzhiyun len = ListDeviceInfo(client, dev, (xXIDeviceInfo *) info);
132*4882a593Smuzhiyun if (client->swapped)
133*4882a593Smuzhiyun SwapDeviceInfo(dev, (xXIDeviceInfo *) info);
134*4882a593Smuzhiyun info += len;
135*4882a593Smuzhiyun rep.num_devices++;
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun for (dev = inputInfo.off_devices; dev; dev = dev->next, i++) {
140*4882a593Smuzhiyun if (!skip[i]) {
141*4882a593Smuzhiyun len = ListDeviceInfo(client, dev, (xXIDeviceInfo *) info);
142*4882a593Smuzhiyun if (client->swapped)
143*4882a593Smuzhiyun SwapDeviceInfo(dev, (xXIDeviceInfo *) info);
144*4882a593Smuzhiyun info += len;
145*4882a593Smuzhiyun rep.num_devices++;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun len = rep.length * 4;
151*4882a593Smuzhiyun WriteReplyToClient(client, sizeof(xXIQueryDeviceReply), &rep);
152*4882a593Smuzhiyun WriteToClient(client, len, ptr);
153*4882a593Smuzhiyun free(ptr);
154*4882a593Smuzhiyun free(skip);
155*4882a593Smuzhiyun return rc;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun void
SRepXIQueryDevice(ClientPtr client,int size,xXIQueryDeviceReply * rep)159*4882a593Smuzhiyun SRepXIQueryDevice(ClientPtr client, int size, xXIQueryDeviceReply * rep)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun swaps(&rep->sequenceNumber);
162*4882a593Smuzhiyun swapl(&rep->length);
163*4882a593Smuzhiyun swaps(&rep->num_devices);
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun /* Device info is already swapped, see ProcXIQueryDevice */
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun WriteToClient(client, size, rep);
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun /**
171*4882a593Smuzhiyun * @return Whether the device should be included in the returned list.
172*4882a593Smuzhiyun */
173*4882a593Smuzhiyun static Bool
ShouldSkipDevice(ClientPtr client,int deviceid,DeviceIntPtr dev)174*4882a593Smuzhiyun ShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr dev)
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun /* if all devices are not being queried, only master devices are */
177*4882a593Smuzhiyun if (deviceid == XIAllDevices || IsMaster(dev)) {
178*4882a593Smuzhiyun int rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess);
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun if (rc == Success)
181*4882a593Smuzhiyun return FALSE;
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun return TRUE;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun /**
187*4882a593Smuzhiyun * @return The number of bytes needed to store this device's xXIDeviceInfo
188*4882a593Smuzhiyun * (and its classes).
189*4882a593Smuzhiyun */
190*4882a593Smuzhiyun static int
SizeDeviceInfo(DeviceIntPtr dev)191*4882a593Smuzhiyun SizeDeviceInfo(DeviceIntPtr dev)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun int len = sizeof(xXIDeviceInfo);
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun /* 4-padded name */
196*4882a593Smuzhiyun len += pad_to_int32(strlen(dev->name));
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun return len + SizeDeviceClasses(dev);
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun /*
203*4882a593Smuzhiyun * @return The number of bytes needed to store this device's classes.
204*4882a593Smuzhiyun */
205*4882a593Smuzhiyun int
SizeDeviceClasses(DeviceIntPtr dev)206*4882a593Smuzhiyun SizeDeviceClasses(DeviceIntPtr dev)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun int len = 0;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun if (dev->button) {
211*4882a593Smuzhiyun len += sizeof(xXIButtonInfo);
212*4882a593Smuzhiyun len += dev->button->numButtons * sizeof(Atom);
213*4882a593Smuzhiyun len += pad_to_int32(bits_to_bytes(dev->button->numButtons));
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun if (dev->key) {
217*4882a593Smuzhiyun XkbDescPtr xkb = dev->key->xkbInfo->desc;
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun len += sizeof(xXIKeyInfo);
220*4882a593Smuzhiyun len += (xkb->max_key_code - xkb->min_key_code + 1) * sizeof(uint32_t);
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun if (dev->valuator) {
224*4882a593Smuzhiyun int i;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun len += (sizeof(xXIValuatorInfo)) * dev->valuator->numAxes;
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun for (i = 0; i < dev->valuator->numAxes; i++) {
229*4882a593Smuzhiyun if (dev->valuator->axes[i].scroll.type != SCROLL_TYPE_NONE)
230*4882a593Smuzhiyun len += sizeof(xXIScrollInfo);
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun if (dev->touch)
235*4882a593Smuzhiyun len += sizeof(xXITouchInfo);
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun return len;
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun /**
241*4882a593Smuzhiyun * Get pointers to button information areas holding button mask and labels.
242*4882a593Smuzhiyun */
243*4882a593Smuzhiyun static void
ButtonInfoData(xXIButtonInfo * info,int * mask_words,unsigned char ** mask,Atom ** atoms)244*4882a593Smuzhiyun ButtonInfoData(xXIButtonInfo *info, int *mask_words, unsigned char **mask,
245*4882a593Smuzhiyun Atom **atoms)
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun *mask_words = bytes_to_int32(bits_to_bytes(info->num_buttons));
248*4882a593Smuzhiyun *mask = (unsigned char*) &info[1];
249*4882a593Smuzhiyun *atoms = (Atom*) ((*mask) + (*mask_words) * 4);
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun /**
253*4882a593Smuzhiyun * Write button information into info.
254*4882a593Smuzhiyun * @return Number of bytes written into info.
255*4882a593Smuzhiyun */
256*4882a593Smuzhiyun int
ListButtonInfo(DeviceIntPtr dev,xXIButtonInfo * info,Bool reportState)257*4882a593Smuzhiyun ListButtonInfo(DeviceIntPtr dev, xXIButtonInfo * info, Bool reportState)
258*4882a593Smuzhiyun {
259*4882a593Smuzhiyun unsigned char *bits;
260*4882a593Smuzhiyun Atom *labels;
261*4882a593Smuzhiyun int mask_len;
262*4882a593Smuzhiyun int i;
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun if (!dev || !dev->button)
265*4882a593Smuzhiyun return 0;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun info->type = ButtonClass;
268*4882a593Smuzhiyun info->num_buttons = dev->button->numButtons;
269*4882a593Smuzhiyun ButtonInfoData(info, &mask_len, &bits, &labels);
270*4882a593Smuzhiyun info->length = bytes_to_int32(sizeof(xXIButtonInfo)) +
271*4882a593Smuzhiyun info->num_buttons + mask_len;
272*4882a593Smuzhiyun info->sourceid = dev->button->sourceid;
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun memset(bits, 0, mask_len * 4);
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun if (reportState)
277*4882a593Smuzhiyun for (i = 0; i < dev->button->numButtons; i++)
278*4882a593Smuzhiyun if (BitIsOn(dev->button->down, i))
279*4882a593Smuzhiyun SetBit(bits, i);
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun memcpy(labels, dev->button->labels, dev->button->numButtons * sizeof(Atom));
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun return info->length * 4;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun static void
SwapButtonInfo(DeviceIntPtr dev,xXIButtonInfo * info)287*4882a593Smuzhiyun SwapButtonInfo(DeviceIntPtr dev, xXIButtonInfo * info)
288*4882a593Smuzhiyun {
289*4882a593Smuzhiyun Atom *btn;
290*4882a593Smuzhiyun int mask_len;
291*4882a593Smuzhiyun unsigned char *mask;
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun int i;
294*4882a593Smuzhiyun ButtonInfoData(info, &mask_len, &mask, &btn);
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun swaps(&info->type);
297*4882a593Smuzhiyun swaps(&info->length);
298*4882a593Smuzhiyun swaps(&info->sourceid);
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun for (i = 0 ; i < info->num_buttons; i++, btn++)
301*4882a593Smuzhiyun swapl(btn);
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun swaps(&info->num_buttons);
304*4882a593Smuzhiyun }
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun /**
307*4882a593Smuzhiyun * Write key information into info.
308*4882a593Smuzhiyun * @return Number of bytes written into info.
309*4882a593Smuzhiyun */
310*4882a593Smuzhiyun int
ListKeyInfo(DeviceIntPtr dev,xXIKeyInfo * info)311*4882a593Smuzhiyun ListKeyInfo(DeviceIntPtr dev, xXIKeyInfo * info)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun int i;
314*4882a593Smuzhiyun XkbDescPtr xkb = dev->key->xkbInfo->desc;
315*4882a593Smuzhiyun uint32_t *kc;
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun info->type = KeyClass;
318*4882a593Smuzhiyun info->num_keycodes = xkb->max_key_code - xkb->min_key_code + 1;
319*4882a593Smuzhiyun info->length = sizeof(xXIKeyInfo) / 4 + info->num_keycodes;
320*4882a593Smuzhiyun info->sourceid = dev->key->sourceid;
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun kc = (uint32_t *) &info[1];
323*4882a593Smuzhiyun for (i = xkb->min_key_code; i <= xkb->max_key_code; i++, kc++)
324*4882a593Smuzhiyun *kc = i;
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun return info->length * 4;
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun static void
SwapKeyInfo(DeviceIntPtr dev,xXIKeyInfo * info)330*4882a593Smuzhiyun SwapKeyInfo(DeviceIntPtr dev, xXIKeyInfo * info)
331*4882a593Smuzhiyun {
332*4882a593Smuzhiyun uint32_t *key;
333*4882a593Smuzhiyun int i;
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun swaps(&info->type);
336*4882a593Smuzhiyun swaps(&info->length);
337*4882a593Smuzhiyun swaps(&info->sourceid);
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun for (i = 0, key = (uint32_t *) &info[1]; i < info->num_keycodes;
340*4882a593Smuzhiyun i++, key++)
341*4882a593Smuzhiyun swapl(key);
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun swaps(&info->num_keycodes);
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun /**
347*4882a593Smuzhiyun * List axis information for the given axis.
348*4882a593Smuzhiyun *
349*4882a593Smuzhiyun * @return The number of bytes written into info.
350*4882a593Smuzhiyun */
351*4882a593Smuzhiyun int
ListValuatorInfo(DeviceIntPtr dev,xXIValuatorInfo * info,int axisnumber,Bool reportState)352*4882a593Smuzhiyun ListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo * info, int axisnumber,
353*4882a593Smuzhiyun Bool reportState)
354*4882a593Smuzhiyun {
355*4882a593Smuzhiyun ValuatorClassPtr v = dev->valuator;
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun info->type = ValuatorClass;
358*4882a593Smuzhiyun info->length = sizeof(xXIValuatorInfo) / 4;
359*4882a593Smuzhiyun info->label = v->axes[axisnumber].label;
360*4882a593Smuzhiyun info->min.integral = v->axes[axisnumber].min_value;
361*4882a593Smuzhiyun info->min.frac = 0;
362*4882a593Smuzhiyun info->max.integral = v->axes[axisnumber].max_value;
363*4882a593Smuzhiyun info->max.frac = 0;
364*4882a593Smuzhiyun info->value = double_to_fp3232(v->axisVal[axisnumber]);
365*4882a593Smuzhiyun info->resolution = v->axes[axisnumber].resolution;
366*4882a593Smuzhiyun info->number = axisnumber;
367*4882a593Smuzhiyun info->mode = valuator_get_mode(dev, axisnumber);
368*4882a593Smuzhiyun info->sourceid = v->sourceid;
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun if (!reportState)
371*4882a593Smuzhiyun info->value = info->min;
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun return info->length * 4;
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun static void
SwapValuatorInfo(DeviceIntPtr dev,xXIValuatorInfo * info)377*4882a593Smuzhiyun SwapValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo * info)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun swaps(&info->type);
380*4882a593Smuzhiyun swaps(&info->length);
381*4882a593Smuzhiyun swapl(&info->label);
382*4882a593Smuzhiyun swapl(&info->min.integral);
383*4882a593Smuzhiyun swapl(&info->min.frac);
384*4882a593Smuzhiyun swapl(&info->max.integral);
385*4882a593Smuzhiyun swapl(&info->max.frac);
386*4882a593Smuzhiyun swapl(&info->value.integral);
387*4882a593Smuzhiyun swapl(&info->value.frac);
388*4882a593Smuzhiyun swapl(&info->resolution);
389*4882a593Smuzhiyun swaps(&info->number);
390*4882a593Smuzhiyun swaps(&info->sourceid);
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun int
ListScrollInfo(DeviceIntPtr dev,xXIScrollInfo * info,int axisnumber)394*4882a593Smuzhiyun ListScrollInfo(DeviceIntPtr dev, xXIScrollInfo * info, int axisnumber)
395*4882a593Smuzhiyun {
396*4882a593Smuzhiyun ValuatorClassPtr v = dev->valuator;
397*4882a593Smuzhiyun AxisInfoPtr axis = &v->axes[axisnumber];
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun if (axis->scroll.type == SCROLL_TYPE_NONE)
400*4882a593Smuzhiyun return 0;
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun info->type = XIScrollClass;
403*4882a593Smuzhiyun info->length = sizeof(xXIScrollInfo) / 4;
404*4882a593Smuzhiyun info->number = axisnumber;
405*4882a593Smuzhiyun switch (axis->scroll.type) {
406*4882a593Smuzhiyun case SCROLL_TYPE_VERTICAL:
407*4882a593Smuzhiyun info->scroll_type = XIScrollTypeVertical;
408*4882a593Smuzhiyun break;
409*4882a593Smuzhiyun case SCROLL_TYPE_HORIZONTAL:
410*4882a593Smuzhiyun info->scroll_type = XIScrollTypeHorizontal;
411*4882a593Smuzhiyun break;
412*4882a593Smuzhiyun default:
413*4882a593Smuzhiyun ErrorF("[Xi] Unknown scroll type %d. This is a bug.\n",
414*4882a593Smuzhiyun axis->scroll.type);
415*4882a593Smuzhiyun break;
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun info->increment = double_to_fp3232(axis->scroll.increment);
418*4882a593Smuzhiyun info->sourceid = v->sourceid;
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun info->flags = 0;
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun if (axis->scroll.flags & SCROLL_FLAG_DONT_EMULATE)
423*4882a593Smuzhiyun info->flags |= XIScrollFlagNoEmulation;
424*4882a593Smuzhiyun if (axis->scroll.flags & SCROLL_FLAG_PREFERRED)
425*4882a593Smuzhiyun info->flags |= XIScrollFlagPreferred;
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun return info->length * 4;
428*4882a593Smuzhiyun }
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun static void
SwapScrollInfo(DeviceIntPtr dev,xXIScrollInfo * info)431*4882a593Smuzhiyun SwapScrollInfo(DeviceIntPtr dev, xXIScrollInfo * info)
432*4882a593Smuzhiyun {
433*4882a593Smuzhiyun swaps(&info->type);
434*4882a593Smuzhiyun swaps(&info->length);
435*4882a593Smuzhiyun swaps(&info->number);
436*4882a593Smuzhiyun swaps(&info->sourceid);
437*4882a593Smuzhiyun swaps(&info->scroll_type);
438*4882a593Smuzhiyun swapl(&info->increment.integral);
439*4882a593Smuzhiyun swapl(&info->increment.frac);
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun /**
443*4882a593Smuzhiyun * List multitouch information
444*4882a593Smuzhiyun *
445*4882a593Smuzhiyun * @return The number of bytes written into info.
446*4882a593Smuzhiyun */
447*4882a593Smuzhiyun int
ListTouchInfo(DeviceIntPtr dev,xXITouchInfo * touch)448*4882a593Smuzhiyun ListTouchInfo(DeviceIntPtr dev, xXITouchInfo * touch)
449*4882a593Smuzhiyun {
450*4882a593Smuzhiyun touch->type = XITouchClass;
451*4882a593Smuzhiyun touch->length = sizeof(xXITouchInfo) >> 2;
452*4882a593Smuzhiyun touch->sourceid = dev->touch->sourceid;
453*4882a593Smuzhiyun touch->mode = dev->touch->mode;
454*4882a593Smuzhiyun touch->num_touches = dev->touch->num_touches;
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun return touch->length << 2;
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun static void
SwapTouchInfo(DeviceIntPtr dev,xXITouchInfo * touch)460*4882a593Smuzhiyun SwapTouchInfo(DeviceIntPtr dev, xXITouchInfo * touch)
461*4882a593Smuzhiyun {
462*4882a593Smuzhiyun swaps(&touch->type);
463*4882a593Smuzhiyun swaps(&touch->length);
464*4882a593Smuzhiyun swaps(&touch->sourceid);
465*4882a593Smuzhiyun }
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun int
GetDeviceUse(DeviceIntPtr dev,uint16_t * attachment)468*4882a593Smuzhiyun GetDeviceUse(DeviceIntPtr dev, uint16_t * attachment)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun DeviceIntPtr master = GetMaster(dev, MASTER_ATTACHED);
471*4882a593Smuzhiyun int use;
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun if (IsMaster(dev)) {
474*4882a593Smuzhiyun DeviceIntPtr paired = GetPairedDevice(dev);
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun use = IsPointerDevice(dev) ? XIMasterPointer : XIMasterKeyboard;
477*4882a593Smuzhiyun *attachment = (paired ? paired->id : 0);
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun else if (!IsFloating(dev)) {
480*4882a593Smuzhiyun use = IsPointerDevice(master) ? XISlavePointer : XISlaveKeyboard;
481*4882a593Smuzhiyun *attachment = master->id;
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun else
484*4882a593Smuzhiyun use = XIFloatingSlave;
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun return use;
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun /**
490*4882a593Smuzhiyun * Write the info for device dev into the buffer pointed to by info.
491*4882a593Smuzhiyun *
492*4882a593Smuzhiyun * @return The number of bytes used.
493*4882a593Smuzhiyun */
494*4882a593Smuzhiyun static int
ListDeviceInfo(ClientPtr client,DeviceIntPtr dev,xXIDeviceInfo * info)495*4882a593Smuzhiyun ListDeviceInfo(ClientPtr client, DeviceIntPtr dev, xXIDeviceInfo * info)
496*4882a593Smuzhiyun {
497*4882a593Smuzhiyun char *any = (char *) &info[1];
498*4882a593Smuzhiyun int len = 0, total_len = 0;
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun info->deviceid = dev->id;
501*4882a593Smuzhiyun info->use = GetDeviceUse(dev, &info->attachment);
502*4882a593Smuzhiyun info->num_classes = 0;
503*4882a593Smuzhiyun info->name_len = strlen(dev->name);
504*4882a593Smuzhiyun info->enabled = dev->enabled;
505*4882a593Smuzhiyun total_len = sizeof(xXIDeviceInfo);
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun len = pad_to_int32(info->name_len);
508*4882a593Smuzhiyun memset(any, 0, len);
509*4882a593Smuzhiyun strncpy(any, dev->name, info->name_len);
510*4882a593Smuzhiyun any += len;
511*4882a593Smuzhiyun total_len += len;
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun total_len += ListDeviceClasses(client, dev, any, &info->num_classes);
514*4882a593Smuzhiyun return total_len;
515*4882a593Smuzhiyun }
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun /**
518*4882a593Smuzhiyun * Write the class info of the device into the memory pointed to by any, set
519*4882a593Smuzhiyun * nclasses to the number of classes in total and return the number of bytes
520*4882a593Smuzhiyun * written.
521*4882a593Smuzhiyun */
522*4882a593Smuzhiyun int
ListDeviceClasses(ClientPtr client,DeviceIntPtr dev,char * any,uint16_t * nclasses)523*4882a593Smuzhiyun ListDeviceClasses(ClientPtr client, DeviceIntPtr dev,
524*4882a593Smuzhiyun char *any, uint16_t * nclasses)
525*4882a593Smuzhiyun {
526*4882a593Smuzhiyun int total_len = 0;
527*4882a593Smuzhiyun int len;
528*4882a593Smuzhiyun int i;
529*4882a593Smuzhiyun int rc;
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun /* Check if the current device state should be suppressed */
532*4882a593Smuzhiyun rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess);
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun if (dev->button) {
535*4882a593Smuzhiyun (*nclasses)++;
536*4882a593Smuzhiyun len = ListButtonInfo(dev, (xXIButtonInfo *) any, rc == Success);
537*4882a593Smuzhiyun any += len;
538*4882a593Smuzhiyun total_len += len;
539*4882a593Smuzhiyun }
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun if (dev->key) {
542*4882a593Smuzhiyun (*nclasses)++;
543*4882a593Smuzhiyun len = ListKeyInfo(dev, (xXIKeyInfo *) any);
544*4882a593Smuzhiyun any += len;
545*4882a593Smuzhiyun total_len += len;
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun for (i = 0; dev->valuator && i < dev->valuator->numAxes; i++) {
549*4882a593Smuzhiyun (*nclasses)++;
550*4882a593Smuzhiyun len = ListValuatorInfo(dev, (xXIValuatorInfo *) any, i, rc == Success);
551*4882a593Smuzhiyun any += len;
552*4882a593Smuzhiyun total_len += len;
553*4882a593Smuzhiyun }
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun for (i = 0; dev->valuator && i < dev->valuator->numAxes; i++) {
556*4882a593Smuzhiyun len = ListScrollInfo(dev, (xXIScrollInfo *) any, i);
557*4882a593Smuzhiyun if (len)
558*4882a593Smuzhiyun (*nclasses)++;
559*4882a593Smuzhiyun any += len;
560*4882a593Smuzhiyun total_len += len;
561*4882a593Smuzhiyun }
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun if (dev->touch) {
564*4882a593Smuzhiyun (*nclasses)++;
565*4882a593Smuzhiyun len = ListTouchInfo(dev, (xXITouchInfo *) any);
566*4882a593Smuzhiyun any += len;
567*4882a593Smuzhiyun total_len += len;
568*4882a593Smuzhiyun }
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun return total_len;
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun static void
SwapDeviceInfo(DeviceIntPtr dev,xXIDeviceInfo * info)574*4882a593Smuzhiyun SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo * info)
575*4882a593Smuzhiyun {
576*4882a593Smuzhiyun char *any = (char *) &info[1];
577*4882a593Smuzhiyun int i;
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun /* Skip over name */
580*4882a593Smuzhiyun any += pad_to_int32(info->name_len);
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun for (i = 0; i < info->num_classes; i++) {
583*4882a593Smuzhiyun int len = ((xXIAnyInfo *) any)->length;
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun switch (((xXIAnyInfo *) any)->type) {
586*4882a593Smuzhiyun case XIButtonClass:
587*4882a593Smuzhiyun SwapButtonInfo(dev, (xXIButtonInfo *) any);
588*4882a593Smuzhiyun break;
589*4882a593Smuzhiyun case XIKeyClass:
590*4882a593Smuzhiyun SwapKeyInfo(dev, (xXIKeyInfo *) any);
591*4882a593Smuzhiyun break;
592*4882a593Smuzhiyun case XIValuatorClass:
593*4882a593Smuzhiyun SwapValuatorInfo(dev, (xXIValuatorInfo *) any);
594*4882a593Smuzhiyun break;
595*4882a593Smuzhiyun case XIScrollClass:
596*4882a593Smuzhiyun SwapScrollInfo(dev, (xXIScrollInfo *) any);
597*4882a593Smuzhiyun break;
598*4882a593Smuzhiyun case XITouchClass:
599*4882a593Smuzhiyun SwapTouchInfo(dev, (xXITouchInfo *) any);
600*4882a593Smuzhiyun break;
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun }
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun any += len * 4;
605*4882a593Smuzhiyun }
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun swaps(&info->deviceid);
608*4882a593Smuzhiyun swaps(&info->use);
609*4882a593Smuzhiyun swaps(&info->attachment);
610*4882a593Smuzhiyun swaps(&info->num_classes);
611*4882a593Smuzhiyun swaps(&info->name_len);
612*4882a593Smuzhiyun
613*4882a593Smuzhiyun }
614