Add some hacky PoC XLib/XInput C code to fetch slave device nodes
This commit is contained in:
parent
771ddc8ce3
commit
8ae7f2cf5b
5
xdg/get-x-slave-devnodes/Makefile
Normal file
5
xdg/get-x-slave-devnodes/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
get-x-slave-devnodes: get-x-slave-devnodes.c
|
||||
$(CC) -O2 --std=c99 -pedantic -Wall get-x-slave-devnodes.c -o get-x-slave-devnodes -lX11 -lXi
|
||||
clean:
|
||||
rm -f get-x-slave-devnodes
|
||||
|
160
xdg/get-x-slave-devnodes/get-x-slave-devnodes.c
Normal file
160
xdg/get-x-slave-devnodes/get-x-slave-devnodes.c
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Loosely based on a mix of:
|
||||
* - xorg-xinput
|
||||
* https://github.com/freedesktop/xorg-xinput/blob/master/src/property.c::print_property_xi2
|
||||
* - xkbcat
|
||||
* https://github.com/anko/xkbcat
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <X11/extensions/XInput2.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
|
||||
char* get_property_xi2(Display* dpy, int deviceid, Atom property, const char* property_name)
|
||||
{
|
||||
Atom act_type;
|
||||
char* name;
|
||||
int act_format;
|
||||
unsigned long nitems, bytes_after;
|
||||
unsigned char* data;
|
||||
unsigned char* ptr;
|
||||
int j, done = False;
|
||||
char* ret = NULL;
|
||||
|
||||
name = XGetAtomName(dpy, property);
|
||||
int interested_in_property = (strcmp(name, property_name) == 0);
|
||||
XFree(name);
|
||||
if (!interested_in_property)
|
||||
return ret;
|
||||
|
||||
if (XIGetProperty(dpy, deviceid, property, 0, 1000, False,
|
||||
AnyPropertyType, &act_type, &act_format,
|
||||
&nitems, &bytes_after, &data) == Success)
|
||||
{
|
||||
ptr = data;
|
||||
for (j = 0; j < nitems; j++)
|
||||
{
|
||||
switch(act_type)
|
||||
{
|
||||
case XA_STRING:
|
||||
if (act_format != 8)
|
||||
{
|
||||
//Unknown string format
|
||||
done = True;
|
||||
break;
|
||||
}
|
||||
|
||||
int len = strlen((char*)ptr);
|
||||
ret = (char*)malloc(len+1);
|
||||
strcpy(ret, (const char*)ptr);
|
||||
|
||||
j += len; /* The loop's j++ jumps over the
|
||||
terminating 0 */
|
||||
ptr += len; /* ptr += size below jumps over
|
||||
the terminating 0 */
|
||||
break;
|
||||
default:
|
||||
// Unknown type
|
||||
done = True;
|
||||
break;
|
||||
}
|
||||
|
||||
ptr += act_format/8;
|
||||
|
||||
if (done == True)
|
||||
break;
|
||||
}
|
||||
XFree(data);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void assert_xinput2(Display* disp)
|
||||
{
|
||||
int xiOpcode;
|
||||
{ // Test for XInput 2 extension
|
||||
int queryEvent, queryError;
|
||||
if (! XQueryExtension(disp, "XInputExtension", &xiOpcode, &queryEvent, &queryError))
|
||||
{
|
||||
fprintf(stderr, "X Input extension not available\n");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
{ // Request XInput 2.0, to guard against changes in future versions
|
||||
int major = 2, minor = 0;
|
||||
int queryResult = XIQueryVersion(disp, &major, &minor);
|
||||
if (queryResult == BadRequest)
|
||||
{
|
||||
fprintf(stderr, "Need XI 2.0 support (got %d.%d)\n", major, minor);
|
||||
exit(3);
|
||||
}
|
||||
else if (queryResult != Success)
|
||||
{
|
||||
fprintf(stderr, "XIQueryVersion failed!\n");
|
||||
exit(4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void print_device_nodes(Display* disp)
|
||||
{
|
||||
XIDeviceInfo* all_slaves;
|
||||
XIDeviceInfo* current_slave;
|
||||
int num_slaves;
|
||||
|
||||
all_slaves = XIQueryDevice(disp, XIAllDevices, &num_slaves);
|
||||
for (int i = 0; i < num_slaves; i++)
|
||||
{
|
||||
current_slave = &all_slaves[i];
|
||||
|
||||
int nprops;
|
||||
Atom* props;
|
||||
props = XIListProperties(disp, current_slave->deviceid, &nprops);
|
||||
if (!nprops)
|
||||
printf("Device '%s' does not report any properties.\n", current_slave->name);
|
||||
|
||||
while(nprops--)
|
||||
{
|
||||
char* property = get_property_xi2(disp, current_slave->deviceid, props[nprops], "Device Node");
|
||||
if (property != NULL)
|
||||
{
|
||||
printf("%s=%s\n", current_slave->name, property);
|
||||
free(property);
|
||||
}
|
||||
}
|
||||
XFree(props);
|
||||
}
|
||||
|
||||
XIFreeDeviceInfo(all_slaves);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
char* xDisplayName = getenv("DISPLAY");
|
||||
if (xDisplayName == NULL)
|
||||
{
|
||||
printf("DISPLAY environment variable not found\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Connect to X display
|
||||
Display* disp = XOpenDisplay(xDisplayName);
|
||||
if (NULL == disp)
|
||||
{
|
||||
fprintf(stderr, "Cannot open X display '%s'\n", xDisplayName);
|
||||
exit(1);
|
||||
}
|
||||
assert_xinput2(disp);
|
||||
|
||||
print_device_nodes(disp);
|
||||
exit(0);
|
||||
}
|
Loading…
Reference in New Issue
Block a user