XIDeviceInfo* XIQueryDevice(Display *dpy, int deviceid, int *ndevices_return) { XIDeviceInfo *info = NULL; xXIQueryDeviceReq *req; xXIQueryDeviceReply reply; char *ptr; char *end; int i; char *buf; XExtDisplayInfo *extinfo = XInput_find_display(dpy); LockDisplay(dpy); if (_XiCheckExtInit(dpy, XInput_2_0, extinfo) == -1) goto error_unlocked; GetReq(XIQueryDevice, req); req->reqType = extinfo->codes->major_opcode; req->ReqType = X_XIQueryDevice; req->deviceid = deviceid; if (!_XReply(dpy, (xReply*) &reply, 0, xFalse)) goto error; if (reply.length < INT_MAX / 4) { *ndevices_return = reply.num_devices; info = Xmalloc((reply.num_devices + 1) * sizeof(XIDeviceInfo)); } else { *ndevices_return = 0; info = NULL; } if (!info) goto error; buf = Xmalloc(reply.length * 4); _XRead(dpy, buf, reply.length * 4); ptr = buf; end = buf + reply.length * 4; /* info is a null-terminated array */ info[reply.num_devices].name = NULL; for (i = 0; i < reply.num_devices; i++) { int nclasses; size_t sz; XIDeviceInfo *lib = &info[i]; xXIDeviceInfo *wire = (xXIDeviceInfo*)ptr; if (ptr + sizeof(xXIDeviceInfo) > end) goto error_loop; lib->deviceid = wire->deviceid; lib->use = wire->use; lib->attachment = wire->attachment; lib->enabled = wire->enabled; nclasses = wire->num_classes; ptr += sizeof(xXIDeviceInfo); if (ptr + wire->name_len > end) goto error_loop; lib->name = Xcalloc(wire->name_len + 1, 1); if (lib->name == NULL) goto error_loop; strncpy(lib->name, ptr, wire->name_len); lib->name[wire->name_len] = '\0'; ptr += ((wire->name_len + 3)/4) * 4; sz = size_classes((xXIAnyInfo*)ptr, nclasses); lib->classes = Xmalloc(sz); if (lib->classes == NULL) { Xfree(lib->name); goto error_loop; } ptr += copy_classes(lib, (xXIAnyInfo*)ptr, &nclasses); /* We skip over unused classes */ lib->num_classes = nclasses; } Xfree(buf); UnlockDisplay(dpy); SyncHandle(); return info; error_loop: while (--i >= 0) { Xfree(info[i].name); Xfree(info[i].classes); } error: UnlockDisplay(dpy); error_unlocked: SyncHandle(); *ndevices_return = -1; Xfree(buf); return NULL; }
XIDeviceInfo* XIQueryDevice(Display *dpy, int deviceid, int *ndevices_return) { XIDeviceInfo *info = NULL; xXIQueryDeviceReq *req; xXIQueryDeviceReply reply; char *ptr; int i; char *buf; XExtDisplayInfo *extinfo = XInput_find_display(dpy); LockDisplay(dpy); if (_XiCheckExtInit(dpy, XInput_2_0, extinfo) == -1) goto error; GetReq(XIQueryDevice, req); req->reqType = extinfo->codes->major_opcode; req->ReqType = X_XIQueryDevice; req->deviceid = deviceid; if (!_XReply(dpy, (xReply*) &reply, 0, xFalse)) goto error; *ndevices_return = reply.num_devices; info = Xmalloc((reply.num_devices + 1) * sizeof(XIDeviceInfo)); if (!info) goto error; buf = Xmalloc(reply.length * 4); _XRead(dpy, buf, reply.length * 4); ptr = buf; /* info is a null-terminated array */ info[reply.num_devices].name = NULL; for (i = 0; i < reply.num_devices; i++) { XIDeviceInfo *lib = &info[i]; xXIDeviceInfo *wire = (xXIDeviceInfo*)ptr; lib->deviceid = wire->deviceid; lib->use = wire->use; lib->attachment = wire->attachment; lib->enabled = wire->enabled; lib->num_classes = wire->num_classes; lib->classes = (XIAnyClassInfo**)&lib[1]; ptr += sizeof(xXIDeviceInfo); lib->name = Xcalloc(wire->name_len + 1, 1); strncpy(lib->name, ptr, wire->name_len); ptr += ((wire->name_len + 3)/4) * 4; lib->classes = Xmalloc(size_classes((xXIAnyInfo*)ptr, lib->num_classes)); ptr += copy_classes(lib, (xXIAnyInfo*)ptr, lib->num_classes); } Xfree(buf); UnlockDisplay(dpy); SyncHandle(); return info; error: UnlockDisplay(dpy); SyncHandle(); *ndevices_return = -1; return NULL; }