88e5001cf2
Patches cleanup Add DualShock4 cable pairing support BIND_NOW support for RELRO iCade autopairing support
363 lines
9.3 KiB
Diff
363 lines
9.3 KiB
Diff
From 94149e19844c3344d1cdd57c24676a0c96b9c8a1 Mon Sep 17 00:00:00 2001
|
|
From: Bastien Nocera <hadess@hadess.net>
|
|
Date: Fri, 25 Aug 2017 19:59:20 +0200
|
|
Subject: [PATCH 1/9] plugins/sixaxis: Remove LEDs handling
|
|
|
|
It's done in the kernel since 2014 in linux kernel commit
|
|
8025087acf9d2b941bae93b3e0967560e7e03e87
|
|
---
|
|
plugins/sixaxis.c | 295 +-----------------------------------------------------
|
|
1 file changed, 5 insertions(+), 290 deletions(-)
|
|
|
|
diff --git a/plugins/sixaxis.c b/plugins/sixaxis.c
|
|
index 7e3c950b4..7d3a8f3ac 100644
|
|
--- a/plugins/sixaxis.c
|
|
+++ b/plugins/sixaxis.c
|
|
@@ -71,17 +71,6 @@ static const struct {
|
|
},
|
|
};
|
|
|
|
-struct leds_data {
|
|
- char *syspath_prefix;
|
|
- uint8_t bitmap;
|
|
-};
|
|
-
|
|
-static void leds_data_destroy(struct leds_data *data)
|
|
-{
|
|
- free(data->syspath_prefix);
|
|
- free(data);
|
|
-}
|
|
-
|
|
static struct udev *ctx = NULL;
|
|
static struct udev_monitor *monitor = NULL;
|
|
static guint watch_id = 0;
|
|
@@ -146,115 +135,6 @@ static int set_master_bdaddr(int fd, const bdaddr_t *bdaddr)
|
|
return ret;
|
|
}
|
|
|
|
-static uint8_t calc_leds_bitmap(int number)
|
|
-{
|
|
- uint8_t bitmap = 0;
|
|
-
|
|
- /* TODO we could support up to 10 (1 + 2 + 3 + 4) */
|
|
- if (number > 7)
|
|
- return bitmap;
|
|
-
|
|
- if (number > 4) {
|
|
- bitmap |= 0x10;
|
|
- number -= 4;
|
|
- }
|
|
-
|
|
- bitmap |= 0x01 << number;
|
|
-
|
|
- return bitmap;
|
|
-}
|
|
-
|
|
-static void set_leds_hidraw(int fd, uint8_t leds_bitmap)
|
|
-{
|
|
- /*
|
|
- * the total time the led is active (0xff means forever)
|
|
- * | duty_length: cycle time in deciseconds (0 - "blink very fast")
|
|
- * | | ??? (Maybe a phase shift or duty_length multiplier?)
|
|
- * | | | % of duty_length led is off (0xff means 100%)
|
|
- * | | | | % of duty_length led is on (0xff means 100%)
|
|
- * | | | | |
|
|
- * 0xff, 0x27, 0x10, 0x00, 0x32,
|
|
- */
|
|
- uint8_t leds_report[] = {
|
|
- 0x01,
|
|
- 0x00, 0x00, 0x00, 0x00, 0x00, /* rumble values TBD */
|
|
- 0x00, 0x00, 0x00, 0x00, 0x00, /* LED_1=0x02, LED_2=0x04 ... */
|
|
- 0xff, 0x27, 0x10, 0x00, 0x32, /* LED_4 */
|
|
- 0xff, 0x27, 0x10, 0x00, 0x32, /* LED_3 */
|
|
- 0xff, 0x27, 0x10, 0x00, 0x32, /* LED_2 */
|
|
- 0xff, 0x27, 0x10, 0x00, 0x32, /* LED_1 */
|
|
- 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
- };
|
|
- int ret;
|
|
-
|
|
- leds_report[10] = leds_bitmap;
|
|
-
|
|
- ret = write(fd, leds_report, sizeof(leds_report));
|
|
- if (ret == sizeof(leds_report))
|
|
- return;
|
|
-
|
|
- if (ret < 0)
|
|
- error("sixaxis: failed to set LEDS (%s)", strerror(errno));
|
|
- else
|
|
- error("sixaxis: failed to set LEDS (%d bytes written)", ret);
|
|
-}
|
|
-
|
|
-static bool set_leds_sysfs(struct leds_data *data)
|
|
-{
|
|
- int i;
|
|
-
|
|
- if (!data->syspath_prefix)
|
|
- return false;
|
|
-
|
|
- /* start from 1, LED0 is never used */
|
|
- for (i = 1; i <= 4; i++) {
|
|
- char path[PATH_MAX] = { 0 };
|
|
- char buf[2] = { 0 };
|
|
- int fd;
|
|
- int ret;
|
|
-
|
|
- snprintf(path, PATH_MAX, "%s%d/brightness",
|
|
- data->syspath_prefix, i);
|
|
-
|
|
- fd = open(path, O_WRONLY);
|
|
- if (fd < 0) {
|
|
- error("sixaxis: cannot open %s (%s)", path,
|
|
- strerror(errno));
|
|
- return false;
|
|
- }
|
|
-
|
|
- buf[0] = '0' + !!(data->bitmap & (1 << i));
|
|
- ret = write(fd, buf, sizeof(buf));
|
|
- close(fd);
|
|
- if (ret != sizeof(buf))
|
|
- return false;
|
|
- }
|
|
-
|
|
- return true;
|
|
-}
|
|
-
|
|
-static gboolean setup_leds(GIOChannel *channel, GIOCondition cond,
|
|
- gpointer user_data)
|
|
-{
|
|
- struct leds_data *data = user_data;
|
|
-
|
|
- if (!data)
|
|
- return FALSE;
|
|
-
|
|
- if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL))
|
|
- goto out;
|
|
-
|
|
- if(!set_leds_sysfs(data)) {
|
|
- int fd = g_io_channel_unix_get_fd(channel);
|
|
- set_leds_hidraw(fd, data->bitmap);
|
|
- }
|
|
-
|
|
-out:
|
|
- leds_data_destroy(data);
|
|
-
|
|
- return FALSE;
|
|
-}
|
|
-
|
|
static bool setup_device(int fd, int index, struct btd_adapter *adapter)
|
|
{
|
|
char device_addr[18], master_addr[18], adapter_addr[18];
|
|
@@ -269,8 +149,7 @@ static bool setup_device(int fd, int index, struct btd_adapter *adapter)
|
|
return false;
|
|
|
|
/* This can happen if controller was plugged while already connected
|
|
- * eg. to charge up battery.
|
|
- * Don't set LEDs in that case, hence return false */
|
|
+ * eg. to charge up battery. */
|
|
device = btd_adapter_find_device(adapter, &device_bdaddr,
|
|
BDADDR_BREDR);
|
|
if (device && btd_device_is_connected(device))
|
|
@@ -307,152 +186,6 @@ static bool setup_device(int fd, int index, struct btd_adapter *adapter)
|
|
return true;
|
|
}
|
|
|
|
-static int get_js_number(struct udev_device *udevice)
|
|
-{
|
|
- struct udev_list_entry *devices, *dev_list_entry;
|
|
- struct udev_enumerate *enumerate;
|
|
- struct udev_device *hid_parent;
|
|
- const char *hidraw_node;
|
|
- const char *hid_id;
|
|
- int number = 0;
|
|
-
|
|
- hid_parent = udev_device_get_parent_with_subsystem_devtype(udevice,
|
|
- "hid", NULL);
|
|
-
|
|
- /*
|
|
- * Look for HID_UNIQ first for the correct behavior via BT, if
|
|
- * HID_UNIQ is not available it means the USB bus is being used and we
|
|
- * can rely on HID_PHYS.
|
|
- */
|
|
- hid_id = udev_device_get_property_value(hid_parent, "HID_UNIQ");
|
|
- if (!hid_id)
|
|
- hid_id = udev_device_get_property_value(hid_parent,
|
|
- "HID_PHYS");
|
|
-
|
|
- hidraw_node = udev_device_get_devnode(udevice);
|
|
- if (!hid_id || !hidraw_node)
|
|
- return 0;
|
|
-
|
|
- enumerate = udev_enumerate_new(udev_device_get_udev(udevice));
|
|
- udev_enumerate_add_match_sysname(enumerate, "js*");
|
|
- udev_enumerate_scan_devices(enumerate);
|
|
- devices = udev_enumerate_get_list_entry(enumerate);
|
|
-
|
|
- udev_list_entry_foreach(dev_list_entry, devices) {
|
|
- struct udev_device *input_parent;
|
|
- struct udev_device *js_dev;
|
|
- const char *input_id;
|
|
- const char *devname;
|
|
-
|
|
- devname = udev_list_entry_get_name(dev_list_entry);
|
|
- js_dev = udev_device_new_from_syspath(
|
|
- udev_device_get_udev(udevice),
|
|
- devname);
|
|
-
|
|
- input_parent = udev_device_get_parent_with_subsystem_devtype(
|
|
- js_dev, "input", NULL);
|
|
- if (!input_parent)
|
|
- goto next;
|
|
-
|
|
- /* check if this is the joystick relative to the hidraw device
|
|
- * above */
|
|
- input_id = udev_device_get_sysattr_value(input_parent, "uniq");
|
|
-
|
|
- /*
|
|
- * A strlen() check is needed because input device over USB
|
|
- * have the UNIQ attribute defined but with an empty value.
|
|
- */
|
|
- if (!input_id || strlen(input_id) == 0)
|
|
- input_id = udev_device_get_sysattr_value(input_parent,
|
|
- "phys");
|
|
-
|
|
- if (!input_id)
|
|
- goto next;
|
|
-
|
|
- if (!strcmp(input_id, hid_id)) {
|
|
- number = atoi(udev_device_get_sysnum(js_dev));
|
|
-
|
|
- /* joystick numbers start from 0, leds from 1 */
|
|
- number++;
|
|
-
|
|
- udev_device_unref(js_dev);
|
|
- break;
|
|
- }
|
|
-next:
|
|
- udev_device_unref(js_dev);
|
|
- }
|
|
-
|
|
- udev_enumerate_unref(enumerate);
|
|
-
|
|
- return number;
|
|
-}
|
|
-
|
|
-static char *get_leds_syspath_prefix(struct udev_device *udevice)
|
|
-{
|
|
- struct udev_list_entry *dev_list_entry;
|
|
- struct udev_enumerate *enumerate;
|
|
- struct udev_device *hid_parent;
|
|
- const char *syspath;
|
|
- char *syspath_prefix;
|
|
-
|
|
- hid_parent = udev_device_get_parent_with_subsystem_devtype(udevice,
|
|
- "hid", NULL);
|
|
-
|
|
- enumerate = udev_enumerate_new(udev_device_get_udev(udevice));
|
|
- udev_enumerate_add_match_parent(enumerate, hid_parent);
|
|
- udev_enumerate_add_match_subsystem(enumerate, "leds");
|
|
- udev_enumerate_scan_devices(enumerate);
|
|
-
|
|
- dev_list_entry = udev_enumerate_get_list_entry(enumerate);
|
|
- if (!dev_list_entry) {
|
|
- syspath_prefix = NULL;
|
|
- goto out;
|
|
- }
|
|
-
|
|
- syspath = udev_list_entry_get_name(dev_list_entry);
|
|
-
|
|
- /*
|
|
- * All the sysfs paths of the LEDs have the same structure, just the
|
|
- * number changes, so strip it and store only the common prefix.
|
|
- *
|
|
- * Subtracting 1 here means assuming that the LED number is a single
|
|
- * digit, this is safe as the kernel driver only exposes 4 LEDs.
|
|
- */
|
|
- syspath_prefix = strndup(syspath, strlen(syspath) - 1);
|
|
-
|
|
-out:
|
|
- udev_enumerate_unref(enumerate);
|
|
-
|
|
- return syspath_prefix;
|
|
-}
|
|
-
|
|
-static struct leds_data *get_leds_data(struct udev_device *udevice)
|
|
-{
|
|
- struct leds_data *data;
|
|
- int number;
|
|
-
|
|
- number = get_js_number(udevice);
|
|
- DBG("number %d", number);
|
|
-
|
|
- data = malloc0(sizeof(*data));
|
|
- if (!data)
|
|
- return NULL;
|
|
-
|
|
- data->bitmap = calc_leds_bitmap(number);
|
|
- if (data->bitmap == 0) {
|
|
- leds_data_destroy(data);
|
|
- return NULL;
|
|
- }
|
|
-
|
|
- /*
|
|
- * It's OK if this fails, set_leds_hidraw() will be used in
|
|
- * case data->syspath_prefix is NULL.
|
|
- */
|
|
- data->syspath_prefix = get_leds_syspath_prefix(udevice);
|
|
-
|
|
- return data;
|
|
-}
|
|
-
|
|
static int get_supported_device(struct udev_device *udevice, uint16_t *bus)
|
|
{
|
|
struct udev_device *hid_parent;
|
|
@@ -481,7 +214,6 @@ static int get_supported_device(struct udev_device *udevice, uint16_t *bus)
|
|
static void device_added(struct udev_device *udevice)
|
|
{
|
|
struct btd_adapter *adapter;
|
|
- GIOChannel *io;
|
|
uint16_t bus;
|
|
int index;
|
|
int fd;
|
|
@@ -493,6 +225,8 @@ static void device_added(struct udev_device *udevice)
|
|
index = get_supported_device(udevice, &bus);
|
|
if (index < 0)
|
|
return;
|
|
+ if (bus != BUS_USB)
|
|
+ return;
|
|
|
|
info("sixaxis: compatible device connected: %s (%04X:%04X)",
|
|
devices[index].name, devices[index].vid,
|
|
@@ -502,27 +236,8 @@ static void device_added(struct udev_device *udevice)
|
|
if (fd < 0)
|
|
return;
|
|
|
|
- io = g_io_channel_unix_new(fd);
|
|
-
|
|
- switch (bus) {
|
|
- case BUS_USB:
|
|
- if (!setup_device(fd, index, adapter))
|
|
- break;
|
|
-
|
|
- /* fall through */
|
|
- case BUS_BLUETOOTH:
|
|
- /* wait for events before setting leds */
|
|
- g_io_add_watch(io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
|
|
- setup_leds, get_leds_data(udevice));
|
|
-
|
|
- break;
|
|
- default:
|
|
- DBG("uknown bus type (%u)", bus);
|
|
- break;
|
|
- }
|
|
-
|
|
- g_io_channel_set_close_on_unref(io, TRUE);
|
|
- g_io_channel_unref(io);
|
|
+ setup_device(fd, index, adapter);
|
|
+ close(fd);
|
|
}
|
|
|
|
static gboolean monitor_watch(GIOChannel *source, GIOCondition condition,
|
|
--
|
|
2.14.1
|
|
|