Created
November 14, 2018 13:24
-
-
Save MCMrARM/9eaaf8a395ed31c59aaafbbe33f2b771 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
#include <cstdlib> | |
#include <cstring> | |
#include <string> | |
#include <sstream> | |
#include <iostream> | |
#include <iomanip> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <libudev.h> | |
#include <libevdev-1.0/libevdev/libevdev.h> | |
#define LBITS (sizeof(long) * 8) | |
#define NLONGS(x) (((x) - 1) / LBITS + 1) | |
#define TEST_BIT(v, i) !!((v)[(i) / LBITS] & (1L << ((i) % LBITS))) | |
static void writeLEShort(std::ostream& s, unsigned short v) { | |
s << std::setw(2) << (v & 0xff) << std::setw(2) << ((v >> 8) & 0xff); | |
} | |
std::string getGUID(struct libevdev* edev) { | |
std::stringstream ss; | |
ss << std::hex << std::setfill('0'); | |
writeLEShort(ss, (unsigned short) libevdev_get_id_bustype(edev)); | |
writeLEShort(ss, 0); | |
writeLEShort(ss, (unsigned short) libevdev_get_id_vendor(edev)); | |
writeLEShort(ss, 0); | |
writeLEShort(ss, (unsigned short) libevdev_get_id_product(edev)); | |
writeLEShort(ss, 0); | |
writeLEShort(ss, (unsigned short) libevdev_get_id_version(edev)); | |
writeLEShort(ss, 0); | |
return ss.str(); | |
} | |
inline bool isHat(int index) { | |
return (index >= ABS_HAT0X && index <= ABS_HAT3Y); | |
} | |
void handleDev(struct udev_device* dev) { | |
const char* val = udev_device_get_property_value(dev, "ID_INPUT_JOYSTICK"); | |
if (val != nullptr && strcmp(val, "1") == 0) { | |
const char* devPath = udev_device_get_devnode(dev); | |
if (devPath == nullptr) | |
return; | |
int fd = open(devPath, O_RDONLY | O_NONBLOCK); | |
struct libevdev* edev = nullptr; | |
int err = libevdev_new_from_fd(fd, &edev); | |
if (err) { | |
printf("libevdev_new_from_fd error %i (%s)\n", err, devPath); | |
close(fd); | |
return; | |
} | |
printf("%s\n", getGUID(edev).c_str()); | |
unsigned long abs[NLONGS(ABS_CNT)]; | |
int len = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs)), abs); | |
if (len < 0) | |
throw std::runtime_error("Failed to get joystick abs"); | |
len *= 8; | |
int nextId = 0; | |
for (size_t i = 0; i < len; i++) { | |
if (!TEST_BIT(abs, i)) { | |
continue; | |
} | |
const input_absinfo* absinfo = libevdev_get_abs_info(edev, i); | |
if (absinfo == nullptr) | |
continue; | |
int id = isHat(i) ? 0 : (nextId++); | |
if (!isHat(i)) | |
printf("id=%i min=%i max=%i flat=%i fuzz=%i\n", id, absinfo->minimum, absinfo->maximum, absinfo->flat, absinfo->fuzz); | |
} | |
libevdev_free(edev); | |
} | |
} | |
int main() { | |
struct udev* udev = udev_new(); | |
struct udev_enumerate* enumerate = udev_enumerate_new(udev); | |
udev_enumerate_add_match_subsystem(enumerate, "input"); | |
udev_enumerate_scan_devices(enumerate); | |
struct udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate); | |
struct udev_list_entry* dev_list_entry; | |
udev_list_entry_foreach(dev_list_entry, devices) { | |
const char* path = udev_list_entry_get_name(dev_list_entry); | |
struct udev_device* dev = udev_device_new_from_syspath(udev, path); | |
if (dev == nullptr) | |
continue; | |
handleDev(dev); | |
udev_device_unref(dev); | |
} | |
udev_enumerate_unref(enumerate); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I don't think the suggested patch matches much sense, albeit this doesn't mean there's no bug in the code -- I'm not confident whether the result of ioctl is even supposed to be used now that I am reviewing the code; maybe it should be replaced with a generic loop to
NLONGS(ABS_CNT) * 8
.