xref: /OK3568_Linux_fs/external/xserver/test/xi2/protocol-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 
24*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
25*4882a593Smuzhiyun #include <dix-config.h>
26*4882a593Smuzhiyun #endif
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #include <stdint.h>
29*4882a593Smuzhiyun #include <X11/X.h>
30*4882a593Smuzhiyun #include <X11/Xproto.h>
31*4882a593Smuzhiyun #include <X11/extensions/XI2proto.h>
32*4882a593Smuzhiyun #include <X11/Xatom.h>
33*4882a593Smuzhiyun #include "inputstr.h"
34*4882a593Smuzhiyun #include "extinit.h"
35*4882a593Smuzhiyun #include "exglobals.h"
36*4882a593Smuzhiyun #include "scrnintstr.h"
37*4882a593Smuzhiyun #include "xkbsrv.h"
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun #include "xiquerydevice.h"
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun #include "protocol-common.h"
42*4882a593Smuzhiyun /*
43*4882a593Smuzhiyun  * Protocol testing for XIQueryDevice request and reply.
44*4882a593Smuzhiyun  *
45*4882a593Smuzhiyun  * Test approach:
46*4882a593Smuzhiyun  * Wrap WriteToClient to intercept server's reply. ProcXIQueryDevice returns
47*4882a593Smuzhiyun  * data in two batches, once for the request, once for the trailing data
48*4882a593Smuzhiyun  * with the device information.
49*4882a593Smuzhiyun  * Repeatedly test with varying deviceids and check against data in reply.
50*4882a593Smuzhiyun  */
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun struct test_data {
53*4882a593Smuzhiyun     int which_device;
54*4882a593Smuzhiyun     int num_devices_in_reply;
55*4882a593Smuzhiyun };
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun extern ClientRec client_window;
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun static void reply_XIQueryDevice_data(ClientPtr client, int len, char *data,
60*4882a593Smuzhiyun                                      void *closure);
61*4882a593Smuzhiyun static void reply_XIQueryDevice(ClientPtr client, int len, char *data,
62*4882a593Smuzhiyun                                 void *closure);
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun /* reply handling for the first bytes that constitute the reply */
65*4882a593Smuzhiyun static void
reply_XIQueryDevice(ClientPtr client,int len,char * data,void * userdata)66*4882a593Smuzhiyun reply_XIQueryDevice(ClientPtr client, int len, char *data, void *userdata)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun     xXIQueryDeviceReply *rep = (xXIQueryDeviceReply *) data;
69*4882a593Smuzhiyun     struct test_data *querydata = (struct test_data *) userdata;
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun     if (client->swapped) {
72*4882a593Smuzhiyun         swapl(&rep->length);
73*4882a593Smuzhiyun         swaps(&rep->sequenceNumber);
74*4882a593Smuzhiyun         swaps(&rep->num_devices);
75*4882a593Smuzhiyun     }
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun     reply_check_defaults(rep, len, XIQueryDevice);
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun     if (querydata->which_device == XIAllDevices)
80*4882a593Smuzhiyun         assert(rep->num_devices == devices.num_devices);
81*4882a593Smuzhiyun     else if (querydata->which_device == XIAllMasterDevices)
82*4882a593Smuzhiyun         assert(rep->num_devices == devices.num_master_devices);
83*4882a593Smuzhiyun     else
84*4882a593Smuzhiyun         assert(rep->num_devices == 1);
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun     querydata->num_devices_in_reply = rep->num_devices;
87*4882a593Smuzhiyun     reply_handler = reply_XIQueryDevice_data;
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun /* reply handling for the trailing bytes that constitute the device info */
91*4882a593Smuzhiyun static void
reply_XIQueryDevice_data(ClientPtr client,int len,char * data,void * closure)92*4882a593Smuzhiyun reply_XIQueryDevice_data(ClientPtr client, int len, char *data, void *closure)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun     int i, j;
95*4882a593Smuzhiyun     struct test_data *querydata = (struct test_data *) closure;
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun     DeviceIntPtr dev;
98*4882a593Smuzhiyun     xXIDeviceInfo *info = (xXIDeviceInfo *) data;
99*4882a593Smuzhiyun     xXIAnyInfo *any;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun     for (i = 0; i < querydata->num_devices_in_reply; i++) {
102*4882a593Smuzhiyun         if (client->swapped) {
103*4882a593Smuzhiyun             swaps(&info->deviceid);
104*4882a593Smuzhiyun             swaps(&info->attachment);
105*4882a593Smuzhiyun             swaps(&info->use);
106*4882a593Smuzhiyun             swaps(&info->num_classes);
107*4882a593Smuzhiyun             swaps(&info->name_len);
108*4882a593Smuzhiyun         }
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun         if (querydata->which_device > XIAllMasterDevices)
111*4882a593Smuzhiyun             assert(info->deviceid == querydata->which_device);
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun         assert(info->deviceid >= 2);    /* 0 and 1 is reserved */
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun         switch (info->deviceid) {
116*4882a593Smuzhiyun         case 2:                /* VCP */
117*4882a593Smuzhiyun             dev = devices.vcp;
118*4882a593Smuzhiyun             assert(info->use == XIMasterPointer);
119*4882a593Smuzhiyun             assert(info->attachment == devices.vck->id);
120*4882a593Smuzhiyun             assert(info->num_classes == 3);     /* 2 axes + button */
121*4882a593Smuzhiyun             break;
122*4882a593Smuzhiyun         case 3:                /* VCK */
123*4882a593Smuzhiyun             dev = devices.vck;
124*4882a593Smuzhiyun             assert(info->use == XIMasterKeyboard);
125*4882a593Smuzhiyun             assert(info->attachment == devices.vcp->id);
126*4882a593Smuzhiyun             assert(info->num_classes == 1);
127*4882a593Smuzhiyun             break;
128*4882a593Smuzhiyun         case 4:                /* mouse */
129*4882a593Smuzhiyun             dev = devices.mouse;
130*4882a593Smuzhiyun             assert(info->use == XISlavePointer);
131*4882a593Smuzhiyun             assert(info->attachment == devices.vcp->id);
132*4882a593Smuzhiyun             assert(info->num_classes == 7);     /* 4 axes + button + 2 scroll */
133*4882a593Smuzhiyun             break;
134*4882a593Smuzhiyun         case 5:                /* keyboard */
135*4882a593Smuzhiyun             dev = devices.kbd;
136*4882a593Smuzhiyun             assert(info->use == XISlaveKeyboard);
137*4882a593Smuzhiyun             assert(info->attachment == devices.vck->id);
138*4882a593Smuzhiyun             assert(info->num_classes == 1);
139*4882a593Smuzhiyun             break;
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun         default:
142*4882a593Smuzhiyun             /* We shouldn't get here */
143*4882a593Smuzhiyun             assert(0);
144*4882a593Smuzhiyun             break;
145*4882a593Smuzhiyun         }
146*4882a593Smuzhiyun         assert(info->enabled == dev->enabled);
147*4882a593Smuzhiyun         assert(info->name_len == strlen(dev->name));
148*4882a593Smuzhiyun         assert(strncmp((char *) &info[1], dev->name, info->name_len) == 0);
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun         any =
151*4882a593Smuzhiyun             (xXIAnyInfo *) ((char *) &info[1] + ((info->name_len + 3) / 4) * 4);
152*4882a593Smuzhiyun         for (j = 0; j < info->num_classes; j++) {
153*4882a593Smuzhiyun             if (client->swapped) {
154*4882a593Smuzhiyun                 swaps(&any->type);
155*4882a593Smuzhiyun                 swaps(&any->length);
156*4882a593Smuzhiyun                 swaps(&any->sourceid);
157*4882a593Smuzhiyun             }
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun             switch (info->deviceid) {
160*4882a593Smuzhiyun             case 3:            /* VCK and kbd have the same properties */
161*4882a593Smuzhiyun             case 5:
162*4882a593Smuzhiyun             {
163*4882a593Smuzhiyun                 int k;
164*4882a593Smuzhiyun                 xXIKeyInfo *ki = (xXIKeyInfo *) any;
165*4882a593Smuzhiyun                 XkbDescPtr xkb = devices.vck->key->xkbInfo->desc;
166*4882a593Smuzhiyun                 uint32_t *kc;
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun                 if (client->swapped)
169*4882a593Smuzhiyun                     swaps(&ki->num_keycodes);
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun                 assert(any->type == XIKeyClass);
172*4882a593Smuzhiyun                 assert(ki->num_keycodes ==
173*4882a593Smuzhiyun                        (xkb->max_key_code - xkb->min_key_code + 1));
174*4882a593Smuzhiyun                 assert(any->length == (2 + ki->num_keycodes));
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun                 kc = (uint32_t *) &ki[1];
177*4882a593Smuzhiyun                 for (k = 0; k < ki->num_keycodes; k++, kc++) {
178*4882a593Smuzhiyun                     if (client->swapped)
179*4882a593Smuzhiyun                         swapl(kc);
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun                     assert(*kc >= xkb->min_key_code);
182*4882a593Smuzhiyun                     assert(*kc <= xkb->max_key_code);
183*4882a593Smuzhiyun                 }
184*4882a593Smuzhiyun                 break;
185*4882a593Smuzhiyun             }
186*4882a593Smuzhiyun             case 4:
187*4882a593Smuzhiyun             {
188*4882a593Smuzhiyun                 assert(any->type == XIButtonClass ||
189*4882a593Smuzhiyun                        any->type == XIValuatorClass ||
190*4882a593Smuzhiyun                        any->type == XIScrollClass);
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun                 if (any->type == XIScrollClass) {
193*4882a593Smuzhiyun                     xXIScrollInfo *si = (xXIScrollInfo *) any;
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun                     if (client->swapped) {
196*4882a593Smuzhiyun                         swaps(&si->number);
197*4882a593Smuzhiyun                         swaps(&si->scroll_type);
198*4882a593Smuzhiyun                         swapl(&si->increment.integral);
199*4882a593Smuzhiyun                         swapl(&si->increment.frac);
200*4882a593Smuzhiyun                     }
201*4882a593Smuzhiyun                     assert(si->length == 6);
202*4882a593Smuzhiyun                     assert(si->number == 2 || si->number == 3);
203*4882a593Smuzhiyun                     if (si->number == 2) {
204*4882a593Smuzhiyun                         assert(si->scroll_type == XIScrollTypeVertical);
205*4882a593Smuzhiyun                         assert(!si->flags);
206*4882a593Smuzhiyun                     }
207*4882a593Smuzhiyun                     if (si->number == 3) {
208*4882a593Smuzhiyun                         assert(si->scroll_type == XIScrollTypeHorizontal);
209*4882a593Smuzhiyun                         assert(si->flags & XIScrollFlagPreferred);
210*4882a593Smuzhiyun                         assert(!(si->flags & ~XIScrollFlagPreferred));
211*4882a593Smuzhiyun                     }
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun                     assert(si->increment.integral == si->number);
214*4882a593Smuzhiyun                     /* protocol-common.c sets up increments of 2.4 and 3.5 */
215*4882a593Smuzhiyun                     assert(si->increment.frac > 0.3 * (1ULL << 32));
216*4882a593Smuzhiyun                     assert(si->increment.frac < 0.6 * (1ULL << 32));
217*4882a593Smuzhiyun                 }
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun             }
220*4882a593Smuzhiyun                 /* fall through */
221*4882a593Smuzhiyun             case 2:            /* VCP and mouse have the same properties except for scroll */
222*4882a593Smuzhiyun             {
223*4882a593Smuzhiyun                 if (info->deviceid == 2)        /* VCP */
224*4882a593Smuzhiyun                     assert(any->type == XIButtonClass ||
225*4882a593Smuzhiyun                            any->type == XIValuatorClass);
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun                 if (any->type == XIButtonClass) {
228*4882a593Smuzhiyun                     int l;
229*4882a593Smuzhiyun                     xXIButtonInfo *bi = (xXIButtonInfo *) any;
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun                     if (client->swapped)
232*4882a593Smuzhiyun                         swaps(&bi->num_buttons);
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun                     assert(bi->num_buttons == devices.vcp->button->numButtons);
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun                     l = 2 + bi->num_buttons +
237*4882a593Smuzhiyun                         bytes_to_int32(bits_to_bytes(bi->num_buttons));
238*4882a593Smuzhiyun                     assert(bi->length == l);
239*4882a593Smuzhiyun                 }
240*4882a593Smuzhiyun                 else if (any->type == XIValuatorClass) {
241*4882a593Smuzhiyun                     xXIValuatorInfo *vi = (xXIValuatorInfo *) any;
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun                     if (client->swapped) {
244*4882a593Smuzhiyun                         swaps(&vi->number);
245*4882a593Smuzhiyun                         swapl(&vi->label);
246*4882a593Smuzhiyun                         swapl(&vi->min.integral);
247*4882a593Smuzhiyun                         swapl(&vi->min.frac);
248*4882a593Smuzhiyun                         swapl(&vi->max.integral);
249*4882a593Smuzhiyun                         swapl(&vi->max.frac);
250*4882a593Smuzhiyun                         swapl(&vi->resolution);
251*4882a593Smuzhiyun                     }
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun                     assert(vi->length == 11);
254*4882a593Smuzhiyun                     assert(vi->number >= 0 && vi->number < 4);
255*4882a593Smuzhiyun                     if (info->deviceid == 2)    /* VCP */
256*4882a593Smuzhiyun                         assert(vi->number < 2);
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun                     assert(vi->mode == XIModeRelative);
259*4882a593Smuzhiyun                     /* device was set up as relative, so standard
260*4882a593Smuzhiyun                      * values here. */
261*4882a593Smuzhiyun                     assert(vi->min.integral == -1);
262*4882a593Smuzhiyun                     assert(vi->min.frac == 0);
263*4882a593Smuzhiyun                     assert(vi->max.integral == -1);
264*4882a593Smuzhiyun                     assert(vi->max.frac == 0);
265*4882a593Smuzhiyun                     assert(vi->resolution == 0);
266*4882a593Smuzhiyun                 }
267*4882a593Smuzhiyun             }
268*4882a593Smuzhiyun                 break;
269*4882a593Smuzhiyun             }
270*4882a593Smuzhiyun             any = (xXIAnyInfo *) (((char *) any) + any->length * 4);
271*4882a593Smuzhiyun         }
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun         info = (xXIDeviceInfo *) any;
274*4882a593Smuzhiyun     }
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun static void
request_XIQueryDevice(struct test_data * querydata,int deviceid,int error)278*4882a593Smuzhiyun request_XIQueryDevice(struct test_data *querydata, int deviceid, int error)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun     int rc;
281*4882a593Smuzhiyun     ClientRec client;
282*4882a593Smuzhiyun     xXIQueryDeviceReq request;
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun     request_init(&request, XIQueryDevice);
285*4882a593Smuzhiyun     client = init_client(request.length, &request);
286*4882a593Smuzhiyun     reply_handler = reply_XIQueryDevice;
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun     querydata->which_device = deviceid;
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun     request.deviceid = deviceid;
291*4882a593Smuzhiyun     rc = ProcXIQueryDevice(&client);
292*4882a593Smuzhiyun     assert(rc == error);
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun     if (rc != Success)
295*4882a593Smuzhiyun         assert(client.errorValue == deviceid);
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun     reply_handler = reply_XIQueryDevice;
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun     client.swapped = TRUE;
300*4882a593Smuzhiyun     swaps(&request.length);
301*4882a593Smuzhiyun     swaps(&request.deviceid);
302*4882a593Smuzhiyun     rc = SProcXIQueryDevice(&client);
303*4882a593Smuzhiyun     assert(rc == error);
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun     if (rc != Success)
306*4882a593Smuzhiyun         assert(client.errorValue == deviceid);
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun static void
test_XIQueryDevice(void)310*4882a593Smuzhiyun test_XIQueryDevice(void)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun     int i;
313*4882a593Smuzhiyun     xXIQueryDeviceReq request;
314*4882a593Smuzhiyun     struct test_data data;
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun     reply_handler = reply_XIQueryDevice;
317*4882a593Smuzhiyun     global_userdata = &data;
318*4882a593Smuzhiyun     request_init(&request, XIQueryDevice);
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun     printf("Testing XIAllDevices.\n");
321*4882a593Smuzhiyun     request_XIQueryDevice(&data, XIAllDevices, Success);
322*4882a593Smuzhiyun     printf("Testing XIAllMasterDevices.\n");
323*4882a593Smuzhiyun     request_XIQueryDevice(&data, XIAllMasterDevices, Success);
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun     printf("Testing existing device ids.\n");
326*4882a593Smuzhiyun     for (i = 2; i < 6; i++)
327*4882a593Smuzhiyun         request_XIQueryDevice(&data, i, Success);
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun     printf("Testing non-existing device ids.\n");
330*4882a593Smuzhiyun     for (i = 6; i <= 0xFFFF; i++)
331*4882a593Smuzhiyun         request_XIQueryDevice(&data, i, BadDevice);
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun     reply_handler = NULL;
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun int
protocol_xiquerydevice_test(void)338*4882a593Smuzhiyun protocol_xiquerydevice_test(void)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun     init_simple();
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun     test_XIQueryDevice();
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun     return 0;
345*4882a593Smuzhiyun }
346