-
-
Save Foxite/0436ccf2be19002651079679e6284dff to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Based on this program for G600: | |
// https://github.com/mafik/logitech-g600-linux | |
// It's 99% the same program except for the fact that it looks for a G502 instead of G600, and some other minor changes I couldn't be bothered to write down. | |
#include <linux/input.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <dirent.h> | |
#include <errno.h> | |
#include <fcntl.h> | |
#include <unistd.h> | |
struct input_event events[256]; | |
const char kDir[] = "/dev/input/by-id/"; | |
const char kPrefix[] = "usb-Logitech_Gaming_Mouse_G502_"; | |
const char kSuffix[] = "-if01-event-kbd"; | |
// ADD KEY->COMMAND MAPPINGS HERE: | |
const char *downCommands[] = { | |
//[scancode] = "command to run", | |
[4] = "xdotool mousedown 8", // G4 (mouse button 4 / backward) | |
[5] = "xdotool mousedown 9", // G5 (mouse button 5 / forward) | |
[6] = "xdotool key ctrl+w", // G7 | |
[7] = "xdotool key ctrl+t", // G8 | |
[8] = "xdotool mousedown 6", // Scroll left (not useful in current state) | |
[9] = "xdotool mousedown 7", // Scroll right (not useful in current state) | |
//[10] = "", // G+G4 (not practical) | |
//[11] = "", // G+G5 (not practical) | |
//[12] = "", // G+G7 | |
[13] = "xdotool key ctrl+shift+t", // G+G8 | |
[14] = "xdotool key ctrl+shift+Tab", // G+Scroll left | |
[15] = "xdotool key ctrl+Tab", // G+Scroll right | |
}; | |
const char *upCommands[] = { | |
//[scancode] = "command to run", | |
[4] = "xdotool mouseup 8", // G4 | |
[5] = "xdotool mouseup 9", // G5 | |
[8] = "xdotool mouseup 6", // Scroll left (not useful in current state) | |
[9] = "xdotool mouseup 7", // Scroll right (not useful in current state) | |
}; | |
int starts_with(const char* haystack, const char* prefix) { | |
size_t prefix_length = strlen(prefix), haystack_length = strlen(haystack); | |
if (haystack_length < prefix_length) return 0; | |
return strncmp(prefix, haystack, prefix_length) == 0; | |
} | |
int ends_with(const char* haystack, const char* suffix) { | |
size_t suffix_length = strlen(suffix), haystack_length = strlen(haystack); | |
if (haystack_length < suffix_length) return 0; | |
size_t haystack_end = haystack + haystack_length - suffix_length; | |
return strncmp(suffix, haystack_end, suffix_length) == 0; | |
} | |
// Returns non-0 on error. | |
int find_g600(char *path) { | |
//*path = kDir; | |
DIR *dir; | |
struct dirent *ent; | |
if (!(dir = opendir(kDir))) { | |
return 1; | |
} | |
while ((ent = readdir(dir))) { | |
if (starts_with(ent->d_name, kPrefix) && ends_with(ent->d_name, kSuffix)) { | |
strcpy(path, kDir); | |
strcat(path, ent->d_name); | |
printf("full path is %s\n", path); | |
//*path += ent->d_name; | |
closedir(dir); | |
return 0; | |
} | |
} | |
closedir(dir); | |
return 2; | |
} | |
int main() { | |
printf("Starting G502 Linux controller.\n\n"); | |
printf("It's a good idea to configure G502 with Logitech Gaming Software before running this program:\n"); | |
printf(" - assign left, right, middle mouse button and vertical mouse wheel to their normal functions\n"); | |
printf(" - assign the G-Shift button to \"G-Shift\"\n"); | |
printf(" - assign all other keys (including horizontal mouse wheel) to arbitrary (unique) keyboard keys\n"); | |
printf("\n"); | |
char path[1024]; | |
int find_error = find_g600(&path); | |
if (find_error) { | |
printf("Error: Couldn't find G502 input device.\n"); | |
switch(find_error) { | |
case 1: | |
printf("Suggestion: Maybe the expected directory (%s) is wrong. Check whether this directory exists and fix it by editing \"g600.c\".\n", kDir); | |
break; | |
case 2: | |
printf("Suggestion: Maybe the expected device prefix (%s) is wrong. Check whether a device with this prefix exists in %s and fix it by editing \"g600.cpp\".\n", kPrefix, kDir); | |
break; | |
} | |
printf("Suggestion: Maybe a permission is missing. Try running this program with with sudo.\n"); | |
return 1; | |
} | |
int fd = open(path, O_RDONLY); | |
if (fd < 0) { | |
printf("Error: Couldn't open \"%s\" for reading.\n", path); | |
printf("Reason: %s.\n", strerror(errno)); | |
printf("Suggestion: Maybe a permission is missing. Try running this program with with sudo.\n"); | |
return 1; | |
} | |
ioctl(fd, EVIOCGRAB, 1); | |
printf("G502 controller started successfully.\n\n"); | |
while (1) { | |
size_t n = read(fd, events, sizeof(events)); | |
if (n <= 0) return 2; | |
if (n < sizeof(struct input_event) % 2) continue; | |
if (events[0].type != 4 || events[0].code != 4 || events[1].type != 1) | |
continue; | |
/* | |
for (int i = 0; i < 2; i++) { | |
printf("type %d, code %d, value %d (%d)\n", events[i].type, events[i].code, events[i].value, events[i].value & ~0x70000); | |
} | |
/*/ | |
int pressed = events[1].value; | |
int scancode = events[0].value & ~0x70000; | |
const char* actionStr = (pressed) ? "+" : "-"; | |
printf("%s %d.\n", actionStr, scancode); | |
const char *downCommand = downCommands[scancode], *upCommand = upCommands[scancode]; | |
const char *cmdToRun = (pressed) ? downCommand : upCommand; | |
if (!cmdToRun || !strlen(cmdToRun)) continue; | |
printf("Executing: \"%s\"\n", cmdToRun); | |
system(cmdToRun); | |
//*/ | |
} | |
close(fd); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment