protocol-xiquerydevice.c 11.4 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
 * Copyright © 2009 Red Hat, Inc.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice (including the next
 *  paragraph) shall be included in all copies or substantial portions of the
 *  Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *  DEALINGS IN THE SOFTWARE.
 */

#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif

#include <stdint.h>
#include <X11/X.h>
#include <X11/Xproto.h>
#include <X11/extensions/XI2proto.h>
#include <X11/Xatom.h>
#include "inputstr.h"
#include "extinit.h"
35
#include "exglobals.h"
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include "scrnintstr.h"
#include "xkbsrv.h"

#include "xiquerydevice.h"

#include "protocol-common.h"
/*
 * Protocol testing for XIQueryDevice request and reply.
 *
 * Test approach:
 * Wrap WriteToClient to intercept server's reply. ProcXIQueryDevice returns
 * data in two batches, once for the request, once for the trailing data
 * with the device information.
 * Repeatedly test with varying deviceids and check against data in reply.
 */

struct test_data {
    int which_device;
    int num_devices_in_reply;
};

57
static void reply_XIQueryDevice_data(ClientPtr client, int len, char *data,
58
                                     void *closure);
59
static void reply_XIQueryDevice(ClientPtr client, int len, char *data,
60
                                void *closure);
61
62

/* reply handling for the first bytes that constitute the reply */
63
64
static void
reply_XIQueryDevice(ClientPtr client, int len, char *data, void *userdata)
65
{
66
67
    xXIQueryDeviceReply *rep = (xXIQueryDeviceReply *) data;
    struct test_data *querydata = (struct test_data *) userdata;
68

69
    if (client->swapped) {
70
71
72
        swapl(&rep->length);
        swaps(&rep->sequenceNumber);
        swaps(&rep->num_devices);
73
74
75
76
77
    }

    reply_check_defaults(rep, len, XIQueryDevice);

    if (querydata->which_device == XIAllDevices)
Peter Hutterer's avatar
Peter Hutterer committed
78
        assert(rep->num_devices == devices.num_devices);
79
    else if (querydata->which_device == XIAllMasterDevices)
Peter Hutterer's avatar
Peter Hutterer committed
80
        assert(rep->num_devices == devices.num_master_devices);
81
    else
Peter Hutterer's avatar
Peter Hutterer committed
82
        assert(rep->num_devices == 1);
83
84
85
86
87
88

    querydata->num_devices_in_reply = rep->num_devices;
    reply_handler = reply_XIQueryDevice_data;
}

/* reply handling for the trailing bytes that constitute the device info */
89
static void
90
reply_XIQueryDevice_data(ClientPtr client, int len, char *data, void *closure)
91
92
{
    int i, j;
93
    struct test_data *querydata = (struct test_data *) closure;
94
95

    DeviceIntPtr dev;
96
    xXIDeviceInfo *info = (xXIDeviceInfo *) data;
97
98
    xXIAnyInfo *any;

99
100
    for (i = 0; i < querydata->num_devices_in_reply; i++) {
        if (client->swapped) {
101
102
103
104
105
            swaps(&info->deviceid);
            swaps(&info->attachment);
            swaps(&info->use);
            swaps(&info->num_classes);
            swaps(&info->name_len);
106
107
108
        }

        if (querydata->which_device > XIAllMasterDevices)
Peter Hutterer's avatar
Peter Hutterer committed
109
            assert(info->deviceid == querydata->which_device);
110

111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
        assert(info->deviceid >= 2);    /* 0 and 1 is reserved */

        switch (info->deviceid) {
        case 2:                /* VCP */
            dev = devices.vcp;
            assert(info->use == XIMasterPointer);
            assert(info->attachment == devices.vck->id);
            assert(info->num_classes == 3);     /* 2 axes + button */
            break;
        case 3:                /* VCK */
            dev = devices.vck;
            assert(info->use == XIMasterKeyboard);
            assert(info->attachment == devices.vcp->id);
            assert(info->num_classes == 1);
            break;
        case 4:                /* mouse */
            dev = devices.mouse;
            assert(info->use == XISlavePointer);
            assert(info->attachment == devices.vcp->id);
            assert(info->num_classes == 7);     /* 4 axes + button + 2 scroll */
            break;
        case 5:                /* keyboard */
            dev = devices.kbd;
            assert(info->use == XISlaveKeyboard);
            assert(info->attachment == devices.vck->id);
            assert(info->num_classes == 1);
            break;

        default:
            /* We shouldn't get here */
            assert(0);
            break;
143
        }
Peter Hutterer's avatar
Peter Hutterer committed
144
145
        assert(info->enabled == dev->enabled);
        assert(info->name_len == strlen(dev->name));
146
        assert(strncmp((char *) &info[1], dev->name, info->name_len) == 0);
147

148
149
150
151
        any =
            (xXIAnyInfo *) ((char *) &info[1] + ((info->name_len + 3) / 4) * 4);
        for (j = 0; j < info->num_classes; j++) {
            if (client->swapped) {
152
153
154
                swaps(&any->type);
                swaps(&any->length);
                swaps(&any->sourceid);
155
156
            }

157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
            switch (info->deviceid) {
            case 3:            /* VCK and kbd have the same properties */
            case 5:
            {
                int k;
                xXIKeyInfo *ki = (xXIKeyInfo *) any;
                XkbDescPtr xkb = devices.vck->key->xkbInfo->desc;
                uint32_t *kc;

                if (client->swapped)
                    swaps(&ki->num_keycodes);

                assert(any->type == XIKeyClass);
                assert(ki->num_keycodes ==
                       (xkb->max_key_code - xkb->min_key_code + 1));
                assert(any->length == (2 + ki->num_keycodes));

                kc = (uint32_t *) & ki[1];
                for (k = 0; k < ki->num_keycodes; k++, kc++) {
                    if (client->swapped)
                        swapl(kc);

                    assert(*kc >= xkb->min_key_code);
                    assert(*kc <= xkb->max_key_code);
                }
                break;
            }
            case 4:
185
            {
186
187
188
189
190
191
192
193
194
195
196
197
                assert(any->type == XIButtonClass ||
                       any->type == XIValuatorClass ||
                       any->type == XIScrollClass);

                if (any->type == XIScrollClass) {
                    xXIScrollInfo *si = (xXIScrollInfo *) any;

                    if (client->swapped) {
                        swaps(&si->number);
                        swaps(&si->scroll_type);
                        swapl(&si->increment.integral);
                        swapl(&si->increment.frac);
198
                    }
199
200
201
202
203
                    assert(si->length == 6);
                    assert(si->number == 2 || si->number == 3);
                    if (si->number == 2) {
                        assert(si->scroll_type == XIScrollTypeVertical);
                        assert(!si->flags);
204
                    }
205
206
207
208
                    if (si->number == 3) {
                        assert(si->scroll_type == XIScrollTypeHorizontal);
                        assert(si->flags & XIScrollFlagPreferred);
                        assert(!(si->flags & ~XIScrollFlagPreferred));
209
                    }
210
211
212
213
214
215
216

                    assert(si->increment.integral == si->number);
                    /* protocol-common.c sets up increments of 2.4 and 3.5 */
                    assert(si->increment.frac > 0.3 * (1ULL << 32));
                    assert(si->increment.frac < 0.6 * (1ULL << 32));
                }

217
            }
218
219
220
221
222
223
224
225
                /* fall through */
            case 2:            /* VCP and mouse have the same properties except for scroll */
            {
                if (info->deviceid == 2)        /* VCP */
                    assert(any->type == XIButtonClass ||
                           any->type == XIValuatorClass);

                if (any->type == XIButtonClass) {
226
                    int l;
227
228
229
230
231
232
233
                    xXIButtonInfo *bi = (xXIButtonInfo *) any;

                    if (client->swapped)
                        swaps(&bi->num_buttons);

                    assert(bi->num_buttons == devices.vcp->button->numButtons);

234
                    l = 2 + bi->num_buttons +
235
                        bytes_to_int32(bits_to_bytes(bi->num_buttons));
236
                    assert(bi->length == l);
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
                }
                else if (any->type == XIValuatorClass) {
                    xXIValuatorInfo *vi = (xXIValuatorInfo *) any;

                    if (client->swapped) {
                        swaps(&vi->number);
                        swapl(&vi->label);
                        swapl(&vi->min.integral);
                        swapl(&vi->min.frac);
                        swapl(&vi->max.integral);
                        swapl(&vi->max.frac);
                        swapl(&vi->resolution);
                    }

                    assert(vi->length == 11);
                    assert(vi->number >= 0 && vi->number < 4);
                    if (info->deviceid == 2)    /* VCP */
                        assert(vi->number < 2);

                    assert(vi->mode == XIModeRelative);
                    /* device was set up as relative, so standard
                     * values here. */
                    assert(vi->min.integral == -1);
                    assert(vi->min.frac == 0);
                    assert(vi->max.integral == -1);
                    assert(vi->max.frac == 0);
                    assert(vi->resolution == 0);
                }
            }
                break;
            }
            any = (xXIAnyInfo *) (((char *) any) + any->length * 4);
269
270
        }

271
        info = (xXIDeviceInfo *) any;
272
273
274
    }
}

275
276
static void
request_XIQueryDevice(struct test_data *querydata, int deviceid, int error)
277
278
279
280
281
282
283
284
285
286
287
288
289
{
    int rc;
    ClientRec client;
    xXIQueryDeviceReq request;

    request_init(&request, XIQueryDevice);
    client = init_client(request.length, &request);
    reply_handler = reply_XIQueryDevice;

    querydata->which_device = deviceid;

    request.deviceid = deviceid;
    rc = ProcXIQueryDevice(&client);
Peter Hutterer's avatar
Peter Hutterer committed
290
    assert(rc == error);
291
292

    if (rc != Success)
Peter Hutterer's avatar
Peter Hutterer committed
293
        assert(client.errorValue == deviceid);
294
295
296
297

    reply_handler = reply_XIQueryDevice;

    client.swapped = TRUE;
298
299
    swaps(&request.length);
    swaps(&request.deviceid);
300
    rc = SProcXIQueryDevice(&client);
Peter Hutterer's avatar
Peter Hutterer committed
301
    assert(rc == error);
302
303

    if (rc != Success)
Peter Hutterer's avatar
Peter Hutterer committed
304
        assert(client.errorValue == deviceid);
305
306
}

307
308
static void
test_XIQueryDevice(void)
309
310
311
312
313
314
315
316
317
{
    int i;
    xXIQueryDeviceReq request;
    struct test_data data;

    reply_handler = reply_XIQueryDevice;
    userdata = &data;
    request_init(&request, XIQueryDevice);

Peter Hutterer's avatar
Peter Hutterer committed
318
    printf("Testing XIAllDevices.\n");
319
    request_XIQueryDevice(&data, XIAllDevices, Success);
Peter Hutterer's avatar
Peter Hutterer committed
320
    printf("Testing XIAllMasterDevices.\n");
321
322
    request_XIQueryDevice(&data, XIAllMasterDevices, Success);

Peter Hutterer's avatar
Peter Hutterer committed
323
    printf("Testing existing device ids.\n");
324
325
326
    for (i = 2; i < 6; i++)
        request_XIQueryDevice(&data, i, Success);

Peter Hutterer's avatar
Peter Hutterer committed
327
    printf("Testing non-existing device ids.\n");
328
329
330
331
332
333
334
    for (i = 6; i <= 0xFFFF; i++)
        request_XIQueryDevice(&data, i, BadDevice);

    reply_handler = NULL;

}

335
336
int
main(int argc, char **argv)
337
338
339
{
    init_simple();

Peter Hutterer's avatar
Peter Hutterer committed
340
    test_XIQueryDevice();
341

Peter Hutterer's avatar
Peter Hutterer committed
342
    return 0;
343
}