xref: /OK3568_Linux_fs/external/xserver/Xi/xiquerydevice.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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