Merge branch 'master' of ssh://tz.otcshare.org/profile/base/libXi
[platform/upstream/libXi.git] / src / XIQueryDevice.c
1 /*
2  * Copyright © 2009 Red Hat, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  */
24
25 #if HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <stdint.h>
30 #include <X11/Xlibint.h>
31 #include <X11/extensions/XI2proto.h>
32 #include <X11/extensions/XInput2.h>
33 #include <X11/extensions/extutil.h>
34 #include "XIint.h"
35
36 extern int copy_classes(XIDeviceInfo* to, xXIAnyInfo* from, int *nclasses);
37 extern int size_classes(xXIAnyInfo* from, int nclasses);
38
39 XIDeviceInfo*
40 XIQueryDevice(Display *dpy, int deviceid, int *ndevices_return)
41 {
42     XIDeviceInfo        *info = NULL;
43     xXIQueryDeviceReq   *req;
44     xXIQueryDeviceReply reply;
45     char                *ptr;
46     int                 i;
47     char                *buf;
48
49     XExtDisplayInfo *extinfo = XInput_find_display(dpy);
50
51     LockDisplay(dpy);
52     if (_XiCheckExtInit(dpy, XInput_2_0, extinfo) == -1)
53         goto error;
54
55     GetReq(XIQueryDevice, req);
56     req->reqType  = extinfo->codes->major_opcode;
57     req->ReqType  = X_XIQueryDevice;
58     req->deviceid = deviceid;
59
60     if (!_XReply(dpy, (xReply*) &reply, 0, xFalse))
61         goto error;
62
63     *ndevices_return = reply.num_devices;
64     info = Xmalloc((reply.num_devices + 1) * sizeof(XIDeviceInfo));
65     if (!info)
66         goto error;
67
68     buf = Xmalloc(reply.length * 4);
69     _XRead(dpy, buf, reply.length * 4);
70     ptr = buf;
71
72     /* info is a null-terminated array */
73     info[reply.num_devices].name = NULL;
74
75     for (i = 0; i < reply.num_devices; i++)
76     {
77         int             nclasses;
78         size_t          sz;
79         XIDeviceInfo    *lib = &info[i];
80         xXIDeviceInfo   *wire = (xXIDeviceInfo*)ptr;
81
82         lib->deviceid    = wire->deviceid;
83         lib->use         = wire->use;
84         lib->attachment  = wire->attachment;
85         lib->enabled     = wire->enabled;
86         nclasses         = wire->num_classes;
87
88         ptr += sizeof(xXIDeviceInfo);
89
90         lib->name = Xcalloc(wire->name_len + 1, 1);
91         strncpy(lib->name, ptr, wire->name_len);
92         ptr += ((wire->name_len + 3)/4) * 4;
93
94         sz = size_classes((xXIAnyInfo*)ptr, nclasses);
95         lib->classes = Xmalloc(sz);
96         ptr += copy_classes(lib, (xXIAnyInfo*)ptr, &nclasses);
97         /* We skip over unused classes */
98         lib->num_classes = nclasses;
99     }
100
101     Xfree(buf);
102     UnlockDisplay(dpy);
103     SyncHandle();
104     return info;
105
106 error:
107     UnlockDisplay(dpy);
108     SyncHandle();
109     *ndevices_return = -1;
110     return NULL;
111 }
112
113 void
114 XIFreeDeviceInfo(XIDeviceInfo* info)
115 {
116     XIDeviceInfo *ptr = info;
117     while(ptr->name)
118     {
119         Xfree(ptr->classes);
120         Xfree(ptr->name);
121         ptr++;
122     }
123     Xfree(info);
124 }