Skip to content

Instantly share code, notes, and snippets.

@acdimalev
Created January 26, 2012 11:29
Show Gist options
  • Save acdimalev/1682350 to your computer and use it in GitHub Desktop.
Save acdimalev/1682350 to your computer and use it in GitHub Desktop.
WiP -- xpad support for Ecore
// NEEDS WORK!!!
// I have no doubt that there are memory leaks in here
#include <Ecore.h>
#include <fcntl.h>
#include <linux/joystick.h>
#include <libudev.h>
#include "xpad.h"
#define MAX_XPADS 4
#define XPAD_NUM_AXES 8
#define XPAD_NUM_BUTTONS 11
#define XPAD_AXIS_MAX ((1 << 15) - 1)
struct xpad_flat {
int is_alive, is_assigned;
float axes[8];
int buttons[11];
};
struct xpad xpads[MAX_XPADS];
int max_xpads = MAX_XPADS;
Eina_Bool xpad_fd_handler(void *data, Ecore_Fd_Handler *fdh) {
int fd = ecore_main_fd_handler_fd_get(fdh);
struct xpad_flat *xpad = data;
struct js_event e;
ssize_t retval;
retval = read(fd, &e, sizeof(struct js_event));
if (retval == 0) {
// this shouldn't happen
}
if (retval == -1) {
// xpad disconnect
xpad->is_alive = 0;
ecore_main_fd_handler_del(fdh);
close(fd);
return ECORE_CALLBACK_CANCEL;
}
switch(e.type & ~JS_EVENT_INIT) {
case JS_EVENT_BUTTON:
printf("%d->buttons[%d]: %f\n", xpad, e.number, (float) e.value / XPAD_AXIS_MAX);
if (e.number < XPAD_NUM_BUTTONS)
{ xpad->buttons[e.number] = e.value; }
break;
case JS_EVENT_AXIS:
printf("%d->axes[%d]: %f\n", xpad, e.number, (float) e.value / XPAD_AXIS_MAX);
if (e.number < XPAD_NUM_AXES)
{ xpad->axes[e.number] = (float) e.value / XPAD_AXIS_MAX; }
}
return ECORE_CALLBACK_RENEW;
}
Eina_Bool xpad_dev_attach(void *data) {
struct udev_device *device = data;
const char *devnode = udev_device_get_devnode(device);
// BUG! -- what happens if the device is disconnected
// before it is successfully opened?
//printf("%s\n", devnode);
int fd = open(devnode, O_RDONLY);
if (fd == -1)
{ return ECORE_CALLBACK_RENEW; }
udev_device_unref(device);
int i;
struct xpad *xpad;
for (i = 0; i < max_xpads; i++) {
xpad = &xpads[i];
if (! xpad->is_alive) { break; }
}
if (i == max_xpads) {
close(fd);
return ECORE_CALLBACK_CANCEL;
}
ecore_main_fd_handler_add(
fd, ECORE_FD_READ, xpad_fd_handler, xpad, NULL, NULL);
xpad->is_alive = -1;
xpad->is_assigned = 0;
return ECORE_CALLBACK_CANCEL;
}
void xpad_udev_attach(struct udev *udev, struct udev_device *device) {
struct udev_device *usb_device = udev_device_get_parent_with_subsystem_devtype(device, "usb", 0);
const char *sysname = udev_device_get_sysname(device);
const char *usb_driver = udev_device_get_driver(usb_device);
//printf("%s - %s\n", sysname, usb_driver);
if (usb_driver && ! strcmp("xpad", usb_driver))
{ ecore_timer_add(1, xpad_dev_attach, device); }
}
Eina_Bool xpad_udev_fd_handler(void *data, Ecore_Fd_Handler *fdh) {
struct udev_monitor *monitor = data;
struct udev *udev = udev_monitor_get_udev(monitor);
struct udev_device *device = udev_monitor_receive_device(monitor);
const char *sysname = udev_device_get_sysname(device);
if ( ! strncmp("js", sysname, 2) )
{ xpad_udev_attach(udev, device); }
return ECORE_CALLBACK_RENEW;
}
void xpad_init() {
struct udev *udev = udev_new();
// monitor
struct udev_monitor *monitor = udev_monitor_new_from_netlink(udev, "udev");
udev_monitor_filter_add_match_subsystem_devtype(
monitor, "input", 0);
udev_monitor_enable_receiving(monitor);
int fd = udev_monitor_get_fd(monitor);
ecore_main_fd_handler_add(
fd, ECORE_FD_READ, xpad_udev_fd_handler, monitor, NULL, NULL );
// enumerate
struct udev_enumerate *enumerate = udev_enumerate_new(udev);
struct udev_list_entry *devices, *list_entry;
udev_enumerate_add_match_subsystem(enumerate, "input");
udev_enumerate_scan_devices(enumerate);
devices = udev_enumerate_get_list_entry(enumerate);
udev_list_entry_foreach(list_entry, devices) {
const char *path = udev_list_entry_get_name(list_entry);
struct udev_device *device = udev_device_new_from_syspath(udev, path);
const char *sysname = udev_device_get_sysname(device);
if ( ! strncmp("js", sysname, 2) )
{ xpad_udev_attach(udev, device); }
}
udev_enumerate_unref(enumerate);
}
struct xpad {
int is_alive, is_assigned;
float lsx, lsy, lt, rsx, rsy, rt, dx, dy;
int a, b, x, y, lb, rb, back, start, guide, lsb, rsb;
};
extern struct xpad xpads[];
extern int max_xpads;
void xpad_init();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment