XListDev.c revision f1ee322d
1/************************************************************ 2 3Copyright 1989, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from The Open Group. 24 25Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. 26 27 All Rights Reserved 28 29Permission to use, copy, modify, and distribute this software and its 30documentation for any purpose and without fee is hereby granted, 31provided that the above copyright notice appear in all copies and that 32both that copyright notice and this permission notice appear in 33supporting documentation, and that the name of Hewlett-Packard not be 34used in advertising or publicity pertaining to distribution of the 35software without specific, written prior permission. 36 37HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 38ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 39HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 40ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 41WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 42ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 43SOFTWARE. 44 45********************************************************/ 46 47/*********************************************************************** 48 * 49 * XListInputDevices - Request the server to return a list of 50 * available input devices. 51 * 52 */ 53#ifdef HAVE_CONFIG_H 54#include <config.h> 55#endif 56 57#include <X11/extensions/XI.h> 58#include <X11/extensions/XIproto.h> 59#include <X11/Xlibint.h> 60#include <X11/extensions/XInput.h> 61#include <X11/extensions/extutil.h> 62#include "XIint.h" 63 64/* Calculate length field to a multiples of sizeof(XID). XIDs are typedefs 65 * to ulong and thus may be 8 bytes on some platforms. This can trigger a 66 * SIGBUS if a class ends up not being 8-aligned (e.g. after XAxisInfo). 67 */ 68static int pad_to_xid(int base_size) 69{ 70 int padsize = sizeof(XID); 71 72 return ((base_size + padsize - 1)/padsize) * padsize; 73} 74 75static int 76SizeClassInfo(xAnyClassPtr *any, int num_classes) 77{ 78 int size = 0; 79 int j; 80 for (j = 0; j < num_classes; j++) { 81 switch ((*any)->class) { 82 case KeyClass: 83 size += pad_to_xid(sizeof(XKeyInfo)); 84 break; 85 case ButtonClass: 86 size += pad_to_xid(sizeof(XButtonInfo)); 87 break; 88 case ValuatorClass: 89 { 90 xValuatorInfoPtr v; 91 92 v = (xValuatorInfoPtr) *any; 93 size += pad_to_xid(sizeof(XValuatorInfo) + 94 (v->num_axes * sizeof(XAxisInfo))); 95 break; 96 } 97 default: 98 break; 99 } 100 *any = (xAnyClassPtr) ((char *)(*any) + (*any)->length); 101 } 102 103 return size; 104} 105 106static void 107ParseClassInfo(xAnyClassPtr *any, XAnyClassPtr *Any, int num_classes) 108{ 109 int j; 110 111 for (j = 0; j < num_classes; j++) { 112 switch ((*any)->class) { 113 case KeyClass: 114 { 115 XKeyInfoPtr K = (XKeyInfoPtr) *Any; 116 xKeyInfoPtr k = (xKeyInfoPtr) *any; 117 118 K->class = KeyClass; 119 K->length = pad_to_xid(sizeof(XKeyInfo)); 120 K->min_keycode = k->min_keycode; 121 K->max_keycode = k->max_keycode; 122 K->num_keys = k->num_keys; 123 break; 124 } 125 case ButtonClass: 126 { 127 XButtonInfoPtr B = (XButtonInfoPtr) *Any; 128 xButtonInfoPtr b = (xButtonInfoPtr) *any; 129 130 B->class = ButtonClass; 131 B->length = pad_to_xid(sizeof(XButtonInfo)); 132 B->num_buttons = b->num_buttons; 133 break; 134 } 135 case ValuatorClass: 136 { 137 int k; 138 XValuatorInfoPtr V = (XValuatorInfoPtr) *Any; 139 xValuatorInfoPtr v = (xValuatorInfoPtr) *any; 140 XAxisInfoPtr A; 141 xAxisInfoPtr a; 142 143 V->class = ValuatorClass; 144 V->length = pad_to_xid(sizeof(XValuatorInfo) + 145 (v->num_axes * sizeof(XAxisInfo))); 146 V->num_axes = v->num_axes; 147 V->motion_buffer = v->motion_buffer_size; 148 V->mode = v->mode; 149 A = (XAxisInfoPtr) ((char *)V + sizeof(XValuatorInfo)); 150 V->axes = A; 151 a = (xAxisInfoPtr) ((char *)(*any) + sizeof(xValuatorInfo)); 152 for (k = 0; k < (int)v->num_axes; k++, a++, A++) { 153 A->min_value = a->min_value; 154 A->max_value = a->max_value; 155 A->resolution = a->resolution; 156 } 157 break; 158 } 159 default: 160 break; 161 } 162 *any = (xAnyClassPtr) ((char *)(*any) + (*any)->length); 163 *Any = (XAnyClassPtr) ((char *)(*Any) + (*Any)->length); 164 } 165} 166 167XDeviceInfo * 168XListInputDevices( 169 register Display *dpy, 170 int *ndevices) 171{ 172 int size; 173 xListInputDevicesReq *req; 174 xListInputDevicesReply rep; 175 xDeviceInfo *list, *slist = NULL; 176 XDeviceInfo *sclist = NULL; 177 XDeviceInfo *clist = NULL; 178 xAnyClassPtr any, sav_any; 179 XAnyClassPtr Any; 180 char *nptr, *Nptr; 181 int i; 182 long rlen; 183 XExtDisplayInfo *info = XInput_find_display(dpy); 184 185 LockDisplay(dpy); 186 if (_XiCheckExtInit(dpy, XInput_Initial_Release, info) == -1) 187 return ((XDeviceInfo *) NULL); 188 189 GetReq(ListInputDevices, req); 190 req->reqType = info->codes->major_opcode; 191 req->ReqType = X_ListInputDevices; 192 193 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 194 UnlockDisplay(dpy); 195 SyncHandle(); 196 return (XDeviceInfo *) NULL; 197 } 198 199 if ((*ndevices = rep.ndevices)) { /* at least 1 input device */ 200 size = *ndevices * sizeof(XDeviceInfo); 201 rlen = rep.length << 2; /* multiply length by 4 */ 202 list = (xDeviceInfo *) Xmalloc(rlen); 203 slist = list; 204 if (!slist) { 205 _XEatData(dpy, (unsigned long)rlen); 206 UnlockDisplay(dpy); 207 SyncHandle(); 208 return (XDeviceInfo *) NULL; 209 } 210 _XRead(dpy, (char *)list, rlen); 211 212 any = (xAnyClassPtr) ((char *)list + (*ndevices * sizeof(xDeviceInfo))); 213 sav_any = any; 214 for (i = 0; i < *ndevices; i++, list++) { 215 size += SizeClassInfo(&any, (int)list->num_classes); 216 } 217 218 for (i = 0, nptr = (char *)any; i < *ndevices; i++) { 219 size += *nptr + 1; 220 nptr += (*nptr + 1); 221 } 222 223 clist = (XDeviceInfoPtr) Xmalloc(size); 224 if (!clist) { 225 XFree((char *)slist); 226 UnlockDisplay(dpy); 227 SyncHandle(); 228 return (XDeviceInfo *) NULL; 229 } 230 sclist = clist; 231 Any = (XAnyClassPtr) ((char *)clist + 232 (*ndevices * sizeof(XDeviceInfo))); 233 list = slist; 234 any = sav_any; 235 for (i = 0; i < *ndevices; i++, list++, clist++) { 236 clist->type = list->type; 237 clist->id = list->id; 238 clist->use = list->use; 239 clist->num_classes = list->num_classes; 240 clist->inputclassinfo = Any; 241 242 ParseClassInfo(&any, &Any, (int)list->num_classes); 243 } 244 245 clist = sclist; 246 nptr = (char *)any; 247 Nptr = (char *)Any; 248 for (i = 0; i < *ndevices; i++, clist++) { 249 clist->name = (char *)Nptr; 250 memcpy(Nptr, nptr + 1, *nptr); 251 Nptr += (*nptr); 252 *Nptr++ = '\0'; 253 nptr += (*nptr + 1); 254 } 255 } 256 257 XFree((char *)slist); 258 UnlockDisplay(dpy); 259 SyncHandle(); 260 return (sclist); 261} 262 263/*********************************************************************** 264 * 265 * Free the list of input devices. 266 * 267 */ 268 269void 270XFreeDeviceList(XDeviceInfo *list) 271{ 272 if (list != NULL) { 273 XFree((char *)list); 274 } 275} 276