Skip to content

Instantly share code, notes, and snippets.

@fungiboletus
Created September 30, 2012 10:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fungiboletus/3806423 to your computer and use it in GitHub Desktop.
Save fungiboletus/3806423 to your computer and use it in GitHub Desktop.
Corsair K60 keyboard 51 opcode bug
gcc -I/usr/X11R6/include -L/usr/X11R6/lib -o hack_keyboard hack_keyboard.c -lX11 -lXtst -lXi -lrt
#include <string.h>
#include <ctype.h>
#include <X11/Xlib.h>
#include <X11/extensions/XInput.h>
#include <X11/Xutil.h>
#include <X11/extensions/XTest.h>
#include <X11/keysym.h>
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
static int key_press_type = -1;
XDeviceInfo * find_device_info(
Display * display,
char const * name,
Bool only_extended)
{
XDeviceInfo *devices;
XDeviceInfo *found = NULL;
int loop;
int num_devices;
int len = strlen(name);
Bool is_id = True;
XID id = (XID)-1;
for(loop=0; loop<len; loop++) {
if (!isdigit(name[loop])) {
is_id = False;
break;
}
}
if (is_id) {
id = atoi(name);
}
devices = XListInputDevices(display, &num_devices);
for(loop=0; loop<num_devices; loop++) {
if ((!only_extended || (devices[loop].use >= IsXExtensionDevice)) &&
((!is_id && strcmp(devices[loop].name, name) == 0) ||
(is_id && devices[loop].id == id)))
{
if (found) {
fprintf(stderr,
"Warning: There are multiple devices named '%s'.\n"
"To ensure the correct one is selected, please use "
"the device ID instead.\n\n", name);
return NULL;
} else {
found = &devices[loop];
}
}
}
return found;
}
static int register_events(
Display *display,
XDeviceInfo *info,
char const *dev_name,
Bool handle_proximity)
{
int number = 0; /* number of events registered */
XEventClass event_list[7];
int i;
XDevice *device;
Window root_win;
unsigned long screen;
XInputClassInfo *ip;
screen = DefaultScreen(display);
root_win = RootWindow(display, screen);
device = XOpenDevice(display, info->id);
if (!device) {
fprintf(stderr, "unable to open device '%s'\n", dev_name);
return 0;
}
if (device->num_classes > 0) {
for (ip = device->classes, i=0; i<info->num_classes; ip++, i++) {
if (ip->input_class == KeyClass)
{
DeviceKeyPress(device, key_press_type, event_list[number]); number++;
// DeviceKeyRelease(device, key_release_type, event_list[number]); number++;
}
}
if (XSelectExtensionEvent(display, root_win, event_list, number)) {
fprintf(stderr, "error selecting extended events\n");
return 0;
}
}
return number;
}
static void manage_events(
Display * display)
{
XEvent Event;
struct timespec time;
double old_time = 0.0;
while(1) {
XNextEvent(display, &Event);
if (Event.type == key_press_type)
{
XDeviceKeyEvent * key = (XDeviceKeyEvent *) & Event;
if (key->keycode == 51)
{
clock_gettime( CLOCK_MONOTONIC, &time );
double new_time = time.tv_sec + time.tv_nsec/1000000000.0;
if (new_time - old_time < 0.5)
{
printf("correction: %f\n", new_time - old_time);
XTestFakeKeyEvent(display, 22, True, CurrentTime);
XTestFakeKeyEvent(display, 22, False, CurrentTime);
XFlush(display);
}
old_time = new_time;
}
}
}
}
int main(int argc, char const *argv[])
{
if (argc < 2)
{
fprintf(stderr, "Usage %s device.\nUse xinput --list to identify the device.\n",
argv[0]);
return EXIT_FAILURE;
}
// Open the display
Display * display = XOpenDisplay(NULL);
if (!display) {
return EXIT_FAILURE;
fprintf(stderr, "Couln'd open display.\n");
}
// Check if the xinput extension is present
int xi_opcode, event, error;
if (!XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error)) {
fprintf(stderr, "X Input extension not available.\n");
XCloseDisplay(display);
return EXIT_FAILURE;
}
// Get the device info
XDeviceInfo * info = find_device_info(display, argv[1], True);
if (!info) {
fprintf(stderr, "Unable te fond device '%s'\n", argv[1]);
XCloseDisplay(display);
return EXIT_FAILURE;
}
if (register_events(display, info, argv[1], False))
manage_events(display);
fprintf(stderr, "Unable to register events\n");
XCloseDisplay(display);
return EXIT_FAILURE;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment