xref: /OK3568_Linux_fs/external/xserver/Xi/listdev.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /************************************************************
2*4882a593Smuzhiyun 
3*4882a593Smuzhiyun Copyright 1989, 1998  The Open Group
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun Permission to use, copy, modify, distribute, and sell this software and its
6*4882a593Smuzhiyun documentation for any purpose is hereby granted without fee, provided that
7*4882a593Smuzhiyun the above copyright notice appear in all copies and that both that
8*4882a593Smuzhiyun copyright notice and this permission notice appear in supporting
9*4882a593Smuzhiyun documentation.
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun The above copyright notice and this permission notice shall be included in
12*4882a593Smuzhiyun all copies or substantial portions of the Software.
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*4882a593Smuzhiyun IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*4882a593Smuzhiyun FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17*4882a593Smuzhiyun OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18*4882a593Smuzhiyun AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19*4882a593Smuzhiyun CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun Except as contained in this notice, the name of The Open Group shall not be
22*4882a593Smuzhiyun used in advertising or otherwise to promote the sale, use or other dealings
23*4882a593Smuzhiyun in this Software without prior written authorization from The Open Group.
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun 			All Rights Reserved
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun Permission to use, copy, modify, and distribute this software and its
30*4882a593Smuzhiyun documentation for any purpose and without fee is hereby granted,
31*4882a593Smuzhiyun provided that the above copyright notice appear in all copies and that
32*4882a593Smuzhiyun both that copyright notice and this permission notice appear in
33*4882a593Smuzhiyun supporting documentation, and that the name of Hewlett-Packard not be
34*4882a593Smuzhiyun used in advertising or publicity pertaining to distribution of the
35*4882a593Smuzhiyun software without specific, written prior permission.
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38*4882a593Smuzhiyun ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39*4882a593Smuzhiyun HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40*4882a593Smuzhiyun ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41*4882a593Smuzhiyun WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42*4882a593Smuzhiyun ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43*4882a593Smuzhiyun SOFTWARE.
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun ********************************************************/
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun /***********************************************************************
48*4882a593Smuzhiyun  *
49*4882a593Smuzhiyun  * Extension function to list the available input devices.
50*4882a593Smuzhiyun  *
51*4882a593Smuzhiyun  */
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
54*4882a593Smuzhiyun #include <dix-config.h>
55*4882a593Smuzhiyun #endif
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun #include <X11/X.h>              /* for inputstr.h    */
58*4882a593Smuzhiyun #include <X11/Xproto.h>         /* Request macro     */
59*4882a593Smuzhiyun #include "inputstr.h"           /* DeviceIntPtr      */
60*4882a593Smuzhiyun #include <X11/extensions/XI.h>
61*4882a593Smuzhiyun #include <X11/extensions/XIproto.h>
62*4882a593Smuzhiyun #include "XIstubs.h"
63*4882a593Smuzhiyun #include "extnsionst.h"
64*4882a593Smuzhiyun #include "exevents.h"
65*4882a593Smuzhiyun #include "xace.h"
66*4882a593Smuzhiyun #include "xkbsrv.h"
67*4882a593Smuzhiyun #include "xkbstr.h"
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun #include "listdev.h"
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun /***********************************************************************
72*4882a593Smuzhiyun  *
73*4882a593Smuzhiyun  * This procedure lists the input devices available to the server.
74*4882a593Smuzhiyun  *
75*4882a593Smuzhiyun  */
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun int _X_COLD
SProcXListInputDevices(ClientPtr client)78*4882a593Smuzhiyun SProcXListInputDevices(ClientPtr client)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun     REQUEST(xListInputDevicesReq);
81*4882a593Smuzhiyun     swaps(&stuff->length);
82*4882a593Smuzhiyun     return (ProcXListInputDevices(client));
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun /***********************************************************************
86*4882a593Smuzhiyun  *
87*4882a593Smuzhiyun  * This procedure calculates the size of the information to be returned
88*4882a593Smuzhiyun  * for an input device.
89*4882a593Smuzhiyun  *
90*4882a593Smuzhiyun  */
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun static void
SizeDeviceInfo(DeviceIntPtr d,int * namesize,int * size)93*4882a593Smuzhiyun SizeDeviceInfo(DeviceIntPtr d, int *namesize, int *size)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun     int chunks;
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun     *namesize += 1;
98*4882a593Smuzhiyun     if (d->name)
99*4882a593Smuzhiyun         *namesize += strlen(d->name);
100*4882a593Smuzhiyun     if (d->key != NULL)
101*4882a593Smuzhiyun         *size += sizeof(xKeyInfo);
102*4882a593Smuzhiyun     if (d->button != NULL)
103*4882a593Smuzhiyun         *size += sizeof(xButtonInfo);
104*4882a593Smuzhiyun     if (d->valuator != NULL) {
105*4882a593Smuzhiyun         chunks = ((int) d->valuator->numAxes + 19) / VPC;
106*4882a593Smuzhiyun         *size += (chunks * sizeof(xValuatorInfo) +
107*4882a593Smuzhiyun                   d->valuator->numAxes * sizeof(xAxisInfo));
108*4882a593Smuzhiyun     }
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun /***********************************************************************
112*4882a593Smuzhiyun  *
113*4882a593Smuzhiyun  * This procedure copies data to the DeviceInfo struct, swapping if necessary.
114*4882a593Smuzhiyun  *
115*4882a593Smuzhiyun  * We need the extra byte in the allocated buffer, because the trailing null
116*4882a593Smuzhiyun  * hammers one extra byte, which is overwritten by the next name except for
117*4882a593Smuzhiyun  * the last name copied.
118*4882a593Smuzhiyun  *
119*4882a593Smuzhiyun  */
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun static void
CopyDeviceName(char ** namebuf,const char * name)122*4882a593Smuzhiyun CopyDeviceName(char **namebuf, const char *name)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun     char *nameptr = *namebuf;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun     if (name) {
127*4882a593Smuzhiyun         *nameptr++ = strlen(name);
128*4882a593Smuzhiyun         strcpy(nameptr, name);
129*4882a593Smuzhiyun         *namebuf += (strlen(name) + 1);
130*4882a593Smuzhiyun     }
131*4882a593Smuzhiyun     else {
132*4882a593Smuzhiyun         *nameptr++ = 0;
133*4882a593Smuzhiyun         *namebuf += 1;
134*4882a593Smuzhiyun     }
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun /***********************************************************************
138*4882a593Smuzhiyun  *
139*4882a593Smuzhiyun  * This procedure copies ButtonClass information, swapping if necessary.
140*4882a593Smuzhiyun  *
141*4882a593Smuzhiyun  */
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun static void
CopySwapButtonClass(ClientPtr client,ButtonClassPtr b,char ** buf)144*4882a593Smuzhiyun CopySwapButtonClass(ClientPtr client, ButtonClassPtr b, char **buf)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun     xButtonInfoPtr b2;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun     b2 = (xButtonInfoPtr) * buf;
149*4882a593Smuzhiyun     b2->class = ButtonClass;
150*4882a593Smuzhiyun     b2->length = sizeof(xButtonInfo);
151*4882a593Smuzhiyun     b2->num_buttons = b->numButtons;
152*4882a593Smuzhiyun     if (client && client->swapped) {
153*4882a593Smuzhiyun         swaps(&b2->num_buttons);
154*4882a593Smuzhiyun     }
155*4882a593Smuzhiyun     *buf += sizeof(xButtonInfo);
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun /***********************************************************************
159*4882a593Smuzhiyun  *
160*4882a593Smuzhiyun  * This procedure copies data to the DeviceInfo struct, swapping if necessary.
161*4882a593Smuzhiyun  *
162*4882a593Smuzhiyun  */
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun static void
CopySwapDevice(ClientPtr client,DeviceIntPtr d,int num_classes,char ** buf)165*4882a593Smuzhiyun CopySwapDevice(ClientPtr client, DeviceIntPtr d, int num_classes, char **buf)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun     xDeviceInfoPtr dev;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun     dev = (xDeviceInfoPtr) * buf;
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun     dev->id = d->id;
172*4882a593Smuzhiyun     dev->type = d->xinput_type;
173*4882a593Smuzhiyun     dev->num_classes = num_classes;
174*4882a593Smuzhiyun     if (IsMaster(d) && IsKeyboardDevice(d))
175*4882a593Smuzhiyun         dev->use = IsXKeyboard;
176*4882a593Smuzhiyun     else if (IsMaster(d) && IsPointerDevice(d))
177*4882a593Smuzhiyun         dev->use = IsXPointer;
178*4882a593Smuzhiyun     else if (d->valuator && d->button)
179*4882a593Smuzhiyun         dev->use = IsXExtensionPointer;
180*4882a593Smuzhiyun     else if (d->key && d->kbdfeed)
181*4882a593Smuzhiyun         dev->use = IsXExtensionKeyboard;
182*4882a593Smuzhiyun     else
183*4882a593Smuzhiyun         dev->use = IsXExtensionDevice;
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun     if (client->swapped) {
186*4882a593Smuzhiyun         swapl(&dev->type);
187*4882a593Smuzhiyun     }
188*4882a593Smuzhiyun     *buf += sizeof(xDeviceInfo);
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun /***********************************************************************
192*4882a593Smuzhiyun  *
193*4882a593Smuzhiyun  * This procedure copies KeyClass information, swapping if necessary.
194*4882a593Smuzhiyun  *
195*4882a593Smuzhiyun  */
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun static void
CopySwapKeyClass(ClientPtr client,KeyClassPtr k,char ** buf)198*4882a593Smuzhiyun CopySwapKeyClass(ClientPtr client, KeyClassPtr k, char **buf)
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun     xKeyInfoPtr k2;
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun     k2 = (xKeyInfoPtr) * buf;
203*4882a593Smuzhiyun     k2->class = KeyClass;
204*4882a593Smuzhiyun     k2->length = sizeof(xKeyInfo);
205*4882a593Smuzhiyun     k2->min_keycode = k->xkbInfo->desc->min_key_code;
206*4882a593Smuzhiyun     k2->max_keycode = k->xkbInfo->desc->max_key_code;
207*4882a593Smuzhiyun     k2->num_keys = k2->max_keycode - k2->min_keycode + 1;
208*4882a593Smuzhiyun     if (client && client->swapped) {
209*4882a593Smuzhiyun         swaps(&k2->num_keys);
210*4882a593Smuzhiyun     }
211*4882a593Smuzhiyun     *buf += sizeof(xKeyInfo);
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun /***********************************************************************
215*4882a593Smuzhiyun  *
216*4882a593Smuzhiyun  * This procedure copies ValuatorClass information, swapping if necessary.
217*4882a593Smuzhiyun  *
218*4882a593Smuzhiyun  * Devices may have up to 255 valuators.  The length of a ValuatorClass is
219*4882a593Smuzhiyun  * defined to be sizeof(ValuatorClassInfo) + num_axes * sizeof (xAxisInfo).
220*4882a593Smuzhiyun  * The maximum length is therefore (8 + 255 * 12) = 3068.  However, the
221*4882a593Smuzhiyun  * length field is one byte.  If a device has more than 20 valuators, we
222*4882a593Smuzhiyun  * must therefore return multiple valuator classes to the client.
223*4882a593Smuzhiyun  *
224*4882a593Smuzhiyun  */
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun static int
CopySwapValuatorClass(ClientPtr client,DeviceIntPtr dev,char ** buf)227*4882a593Smuzhiyun CopySwapValuatorClass(ClientPtr client, DeviceIntPtr dev, char **buf)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun     int i, j, axes, t_axes;
230*4882a593Smuzhiyun     ValuatorClassPtr v = dev->valuator;
231*4882a593Smuzhiyun     xValuatorInfoPtr v2;
232*4882a593Smuzhiyun     AxisInfo *a;
233*4882a593Smuzhiyun     xAxisInfoPtr a2;
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun     for (i = 0, axes = v->numAxes; i < ((v->numAxes + 19) / VPC);
236*4882a593Smuzhiyun          i++, axes -= VPC) {
237*4882a593Smuzhiyun         t_axes = axes < VPC ? axes : VPC;
238*4882a593Smuzhiyun         if (t_axes < 0)
239*4882a593Smuzhiyun             t_axes = v->numAxes % VPC;
240*4882a593Smuzhiyun         v2 = (xValuatorInfoPtr) * buf;
241*4882a593Smuzhiyun         v2->class = ValuatorClass;
242*4882a593Smuzhiyun         v2->length = sizeof(xValuatorInfo) + t_axes * sizeof(xAxisInfo);
243*4882a593Smuzhiyun         v2->num_axes = t_axes;
244*4882a593Smuzhiyun         v2->mode = valuator_get_mode(dev, 0);
245*4882a593Smuzhiyun         v2->motion_buffer_size = v->numMotionEvents;
246*4882a593Smuzhiyun         if (client && client->swapped) {
247*4882a593Smuzhiyun             swapl(&v2->motion_buffer_size);
248*4882a593Smuzhiyun         }
249*4882a593Smuzhiyun         *buf += sizeof(xValuatorInfo);
250*4882a593Smuzhiyun         a = v->axes + (VPC * i);
251*4882a593Smuzhiyun         a2 = (xAxisInfoPtr) * buf;
252*4882a593Smuzhiyun         for (j = 0; j < t_axes; j++) {
253*4882a593Smuzhiyun             a2->min_value = a->min_value;
254*4882a593Smuzhiyun             a2->max_value = a->max_value;
255*4882a593Smuzhiyun             a2->resolution = a->resolution;
256*4882a593Smuzhiyun             if (client && client->swapped) {
257*4882a593Smuzhiyun                 swapl(&a2->min_value);
258*4882a593Smuzhiyun                 swapl(&a2->max_value);
259*4882a593Smuzhiyun                 swapl(&a2->resolution);
260*4882a593Smuzhiyun             }
261*4882a593Smuzhiyun             a2++;
262*4882a593Smuzhiyun             a++;
263*4882a593Smuzhiyun             *buf += sizeof(xAxisInfo);
264*4882a593Smuzhiyun         }
265*4882a593Smuzhiyun     }
266*4882a593Smuzhiyun     return i;
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun static void
CopySwapClasses(ClientPtr client,DeviceIntPtr dev,CARD8 * num_classes,char ** classbuf)270*4882a593Smuzhiyun CopySwapClasses(ClientPtr client, DeviceIntPtr dev, CARD8 *num_classes,
271*4882a593Smuzhiyun                 char **classbuf)
272*4882a593Smuzhiyun {
273*4882a593Smuzhiyun     if (dev->key != NULL) {
274*4882a593Smuzhiyun         CopySwapKeyClass(client, dev->key, classbuf);
275*4882a593Smuzhiyun         (*num_classes)++;
276*4882a593Smuzhiyun     }
277*4882a593Smuzhiyun     if (dev->button != NULL) {
278*4882a593Smuzhiyun         CopySwapButtonClass(client, dev->button, classbuf);
279*4882a593Smuzhiyun         (*num_classes)++;
280*4882a593Smuzhiyun     }
281*4882a593Smuzhiyun     if (dev->valuator != NULL) {
282*4882a593Smuzhiyun         (*num_classes) += CopySwapValuatorClass(client, dev, classbuf);
283*4882a593Smuzhiyun     }
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun /***********************************************************************
287*4882a593Smuzhiyun  *
288*4882a593Smuzhiyun  * This procedure lists information to be returned for an input device.
289*4882a593Smuzhiyun  *
290*4882a593Smuzhiyun  */
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun static void
ListDeviceInfo(ClientPtr client,DeviceIntPtr d,xDeviceInfoPtr dev,char ** devbuf,char ** classbuf,char ** namebuf)293*4882a593Smuzhiyun ListDeviceInfo(ClientPtr client, DeviceIntPtr d, xDeviceInfoPtr dev,
294*4882a593Smuzhiyun                char **devbuf, char **classbuf, char **namebuf)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun     CopyDeviceName(namebuf, d->name);
297*4882a593Smuzhiyun     CopySwapDevice(client, d, 0, devbuf);
298*4882a593Smuzhiyun     CopySwapClasses(client, d, &dev->num_classes, classbuf);
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun /***********************************************************************
302*4882a593Smuzhiyun  *
303*4882a593Smuzhiyun  * This procedure checks if a device should be left off the list.
304*4882a593Smuzhiyun  *
305*4882a593Smuzhiyun  */
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun static Bool
ShouldSkipDevice(ClientPtr client,DeviceIntPtr d)308*4882a593Smuzhiyun ShouldSkipDevice(ClientPtr client, DeviceIntPtr d)
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun     /* don't send master devices other than VCP/VCK */
311*4882a593Smuzhiyun     if (!IsMaster(d) || d == inputInfo.pointer ||d == inputInfo.keyboard) {
312*4882a593Smuzhiyun         int rc = XaceHook(XACE_DEVICE_ACCESS, client, d, DixGetAttrAccess);
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun         if (rc == Success)
315*4882a593Smuzhiyun             return FALSE;
316*4882a593Smuzhiyun     }
317*4882a593Smuzhiyun     return TRUE;
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun /***********************************************************************
321*4882a593Smuzhiyun  *
322*4882a593Smuzhiyun  * This procedure lists the input devices available to the server.
323*4882a593Smuzhiyun  *
324*4882a593Smuzhiyun  * If this request is called by a client that has not issued a
325*4882a593Smuzhiyun  * GetExtensionVersion request with major/minor version set, we don't send the
326*4882a593Smuzhiyun  * complete device list. Instead, we only send the VCP, the VCK and floating
327*4882a593Smuzhiyun  * SDs. This resembles the setup found on XI 1.x machines.
328*4882a593Smuzhiyun  */
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun int
ProcXListInputDevices(ClientPtr client)331*4882a593Smuzhiyun ProcXListInputDevices(ClientPtr client)
332*4882a593Smuzhiyun {
333*4882a593Smuzhiyun     xListInputDevicesReply rep;
334*4882a593Smuzhiyun     int numdevs = 0;
335*4882a593Smuzhiyun     int namesize = 1;           /* need 1 extra byte for strcpy */
336*4882a593Smuzhiyun     int i = 0, size = 0;
337*4882a593Smuzhiyun     int total_length;
338*4882a593Smuzhiyun     char *devbuf, *classbuf, *namebuf, *savbuf;
339*4882a593Smuzhiyun     Bool *skip;
340*4882a593Smuzhiyun     xDeviceInfo *dev;
341*4882a593Smuzhiyun     DeviceIntPtr d;
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xListInputDevicesReq);
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun     rep = (xListInputDevicesReply) {
346*4882a593Smuzhiyun         .repType = X_Reply,
347*4882a593Smuzhiyun         .RepType = X_ListInputDevices,
348*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
349*4882a593Smuzhiyun         .length = 0
350*4882a593Smuzhiyun     };
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun     /* allocate space for saving skip value */
353*4882a593Smuzhiyun     skip = calloc(sizeof(Bool), inputInfo.numDevices);
354*4882a593Smuzhiyun     if (!skip)
355*4882a593Smuzhiyun         return BadAlloc;
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun     /* figure out which devices to skip */
358*4882a593Smuzhiyun     numdevs = 0;
359*4882a593Smuzhiyun     for (d = inputInfo.devices; d; d = d->next, i++) {
360*4882a593Smuzhiyun         skip[i] = ShouldSkipDevice(client, d);
361*4882a593Smuzhiyun         if (skip[i])
362*4882a593Smuzhiyun             continue;
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun         SizeDeviceInfo(d, &namesize, &size);
365*4882a593Smuzhiyun         numdevs++;
366*4882a593Smuzhiyun     }
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun     for (d = inputInfo.off_devices; d; d = d->next, i++) {
369*4882a593Smuzhiyun         skip[i] = ShouldSkipDevice(client, d);
370*4882a593Smuzhiyun         if (skip[i])
371*4882a593Smuzhiyun             continue;
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun         SizeDeviceInfo(d, &namesize, &size);
374*4882a593Smuzhiyun         numdevs++;
375*4882a593Smuzhiyun     }
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun     /* allocate space for reply */
378*4882a593Smuzhiyun     total_length = numdevs * sizeof(xDeviceInfo) + size + namesize;
379*4882a593Smuzhiyun     devbuf = (char *) calloc(1, total_length);
380*4882a593Smuzhiyun     classbuf = devbuf + (numdevs * sizeof(xDeviceInfo));
381*4882a593Smuzhiyun     namebuf = classbuf + size;
382*4882a593Smuzhiyun     savbuf = devbuf;
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun     /* fill in and send reply */
385*4882a593Smuzhiyun     i = 0;
386*4882a593Smuzhiyun     dev = (xDeviceInfoPtr) devbuf;
387*4882a593Smuzhiyun     for (d = inputInfo.devices; d; d = d->next, i++) {
388*4882a593Smuzhiyun         if (skip[i])
389*4882a593Smuzhiyun             continue;
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun         ListDeviceInfo(client, d, dev++, &devbuf, &classbuf, &namebuf);
392*4882a593Smuzhiyun     }
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun     for (d = inputInfo.off_devices; d; d = d->next, i++) {
395*4882a593Smuzhiyun         if (skip[i])
396*4882a593Smuzhiyun             continue;
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun         ListDeviceInfo(client, d, dev++, &devbuf, &classbuf, &namebuf);
399*4882a593Smuzhiyun     }
400*4882a593Smuzhiyun     rep.ndevices = numdevs;
401*4882a593Smuzhiyun     rep.length = bytes_to_int32(total_length);
402*4882a593Smuzhiyun     WriteReplyToClient(client, sizeof(xListInputDevicesReply), &rep);
403*4882a593Smuzhiyun     WriteToClient(client, total_length, savbuf);
404*4882a593Smuzhiyun     free(savbuf);
405*4882a593Smuzhiyun     free(skip);
406*4882a593Smuzhiyun     return Success;
407*4882a593Smuzhiyun }
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun /***********************************************************************
410*4882a593Smuzhiyun  *
411*4882a593Smuzhiyun  * This procedure writes the reply for the XListInputDevices function,
412*4882a593Smuzhiyun  * if the client and server have a different byte ordering.
413*4882a593Smuzhiyun  *
414*4882a593Smuzhiyun  */
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun void _X_COLD
SRepXListInputDevices(ClientPtr client,int size,xListInputDevicesReply * rep)417*4882a593Smuzhiyun SRepXListInputDevices(ClientPtr client, int size, xListInputDevicesReply * rep)
418*4882a593Smuzhiyun {
419*4882a593Smuzhiyun     swaps(&rep->sequenceNumber);
420*4882a593Smuzhiyun     swapl(&rep->length);
421*4882a593Smuzhiyun     WriteToClient(client, size, rep);
422*4882a593Smuzhiyun }
423