Hi,
this is another attempt to get the sixaxis plugin merged upstream in
bluez, now cable pairing is done without libusb, which is good because
the hid driver does not need to be detached anymore.
The work is based on patches by Bastian Nocera, so its SOB line comes
first on the third patch, even though many parts have been totally
reimplemented. More comments on the patch itself.
Bastien, I took the liberty to impersonate you in the second patch about
re-adding manager_get_default_adapter(), because the change was taken
out from your bluez rpm package. I hope this is OK.
I was wondering if it was possible to have the equivalent of this plugin
as a separate daemon doing the association part with bluez over dbus,
instead of having it builtin (I do not know the bluez dbus interface at
all), and if there were any major drawbacks with that compared to the
builtin plugin. What are your opinions on that?
Anyhow,
HOWTO test it:
- Get a kernel supporting HIDIOCSFEATURE and HIDIOCGFEATURE: linux-next
should have that, or Jiki Kosina's hidraw-feature branch:
http://git.kernel.org/?p=linux/kernel/git/jikos/hid.git;a=shortlog;h=refs/heads/hidraw-feature
- Build it and install it with its linux-libc-dev package ("make
deb-pkg" on recent kernels builds that already).
- Apply the patches in this series and configure bluez, the ioctl
above should be detected automatically and the plugin enabled.
- If there is any problem, try backing up and cleaning up
/var/lib/bluetooth/
TODO before merging:
- Check the routine about bluetooth association. Also, is it strictly
necessary to grant manually the first connection?
- Add the actual official version of linux-libc-dev in which the
hidraw ioctl will be merged (now it is just 2.6.3x as a
placeholder).
- Check the last comment from Marcel about the timeout in
http://marc.info/?l=linux-bluetooth&m=125525415718147&w=2 Could you
comment on the third patch about that, please?
- When the controller is connected via USB after it is working over BT
it is seen as a second controller and the second LED is turned on,
should we force BT disconnection on USB connection?
- Test with multiple controllers, and/or multiple BT adapters, which I
can't do right now.
- Remove the XXX comment about the lowercase hex bdaddr format.
FUTURE plans:
- Add support for battery status report
- Add support for Playstation Move (I don't have the hardware, tho),
Pascal?
Thanks,
Antonio
Antonio Ospite (2):
Remove input/sixpair.c
Add sixaxis plugin: USB pairing and LEDs settings
Bastien Nocera (1):
Re-add manager_get_default_adapter()
Makefile.am | 9 +-
acinclude.m4 | 39 ++++
configure.ac | 1 +
input/sixpair.c | 299 -------------------------------
plugins/sixaxis.c | 506 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/manager.c | 5 +
src/manager.h | 1 +
7 files changed, 559 insertions(+), 301 deletions(-)
delete mode 100644 input/sixpair.c
create mode 100644 plugins/sixaxis.c
--
Antonio Ospite
http://ao2.it
PGP public key ID: 0x4553B001
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
On Fri, 2011-02-25 at 15:49 +0000, Simon Kenyon wrote:
> On 25/02/2011 10:04, Antonio Ospite wrote:
> > FUTURE plans:
> > - Add support for battery status report
> > - Add support for Playstation Move (I don't have the hardware, tho),
> > Pascal?
>
> any chance of including the PS3 BD remote in your plans?
The PS3 BD remote doesn't use cable pairing, and has been supported in
bluetoothd for a couple of years already.
Cheers
On 25/02/2011 10:04, Antonio Ospite wrote:
> FUTURE plans:
> - Add support for battery status report
> - Add support for Playstation Move (I don't have the hardware, tho),
> Pascal?
any chance of including the PS3 BD remote in your plans?
--
simon
Antonio Ospite writes:
> FUTURE plans:
> - Add support for battery status report
> - Add support for Playstation Move (I don't have the hardware, tho),
As far as I know, if your infrastructure can both pair the
sixaxis over USB and register it in /var/lib/bluetooth, then it
will only take a small patch to add support for the Move later.
There are rumours that Sony will announce PC support the Move
at a conference next week, and the speaker seems to have a
strong Linux background. Maybe that will reveal some useful
information, such as:
- whether it is safe to perform the cable pairing everytime the
device is plugged in (I'd expect the USB socket to die long
before any flash chip wears out, but who knows ?)
- whether it is safe to run the LED bulb at full power
- how to use the built-in sensor calibration data.
Pascal
On Fri, 2011-02-25 at 11:04 +0100, Antonio Ospite wrote:
> Hi,
>
> this is another attempt to get the sixaxis plugin merged upstream in
> bluez, now cable pairing is done without libusb, which is good because
> the hid driver does not need to be detached anymore.
Good stuff.
> The work is based on patches by Bastian Nocera, so its SOB line comes
> first on the third patch, even though many parts have been totally
> reimplemented. More comments on the patch itself.
>
> Bastien, I took the liberty to impersonate you in the second patch about
> re-adding manager_get_default_adapter(), because the change was taken
> out from your bluez rpm package. I hope this is OK.
Both fine by me.
> I was wondering if it was possible to have the equivalent of this plugin
> as a separate daemon doing the association part with bluez over dbus,
> instead of having it builtin (I do not know the bluez dbus interface at
> all), and if there were any major drawbacks with that compared to the
> builtin plugin. What are your opinions on that?
This was already discussed, and I even created a patch to allow outside
pairing. I don't think there's much of a point doing this outside of
bluetoothd though, and Marcel preferred the pairing to be done within
bluetoothd.
> Anyhow,
>
> HOWTO test it:
> - Get a kernel supporting HIDIOCSFEATURE and HIDIOCGFEATURE: linux-next
> should have that, or Jiki Kosina's hidraw-feature branch:
> http://git.kernel.org/?p=linux/kernel/git/jikos/hid.git;a=shortlog;h=refs/heads/hidraw-feature
> - Build it and install it with its linux-libc-dev package ("make
> deb-pkg" on recent kernels builds that already).
> - Apply the patches in this series and configure bluez, the ioctl
> above should be detected automatically and the plugin enabled.
> - If there is any problem, try backing up and cleaning up
> /var/lib/bluetooth/
>
> TODO before merging:
> - Check the routine about bluetooth association. Also, is it strictly
> necessary to grant manually the first connection?
The line setting the device trust should be enough to not have to
manually grant the first connection. You might want to double-check what
changes between the state of /var/lib/bluetooth after cable pairing and
before connecting for the first time.
> - Add the actual official version of linux-libc-dev in which the
> hidraw ioctl will be merged (now it is just 2.6.3x as a
> placeholder).
> - Check the last comment from Marcel about the timeout in
> http://marc.info/?l=linux-bluetooth&m=125525415718147&w=2 Could you
> comment on the third patch about that, please?
The timeout was to avoid reading data while udev was probing the device.
This might not be necessary anymore.
> - When the controller is connected via USB after it is working over BT
> it is seen as a second controller and the second LED is turned on,
> should we force BT disconnection on USB connection?
If we can assert that the device is the same one, yes, I think we
should.
> - Test with multiple controllers, and/or multiple BT adapters, which I
> can't do right now.
> - Remove the XXX comment about the lowercase hex bdaddr format.
>
>
> FUTURE plans:
> - Add support for battery status report
Where is the battery level exported currently?
> - Add support for Playstation Move (I don't have the hardware, tho),
> Pascal?
The PS3 add-on keyboard, and the PS3 headset both use cable pairing. I
have them around, but was unable to get them to pair.
Cheers
Add a plugin which handles the connection of a Sixaxis device, when a
new hidraw device is connected the plugin:
- Filters udev events, and select the Sixaxis device
- Sets LEDs to match the joystick system number (for USB and BT)
- Sets the Master bluetooth address in the Sixaxis (USB pairing)
- Adds the device to the database of the current default
adapter (BT association)
Signed-off-by: Bastien Nocera <[email protected]>
Signed-off-by: Antonio Ospite <[email protected]>
---
Changes since previous version:
- Use 'sixaxis' as plugin name because this is not a generic cable pairing
mechanism.
- Drop dependency on libusb, we can now use hidraw to send feature reports,
since this patch has been accepted:
https://patchwork.kernel.org/patch/485671/
- Other autotools cleanups (use UDEV_LIBS, check for the needed hidraw
ioctls)
- Rebase on latest bluez (s/debug/DBG/, use adapter_get_device(), etc.)
- Misc fixes: change indentation, reorder includes and functions, etc.
- Add support for setting LEDs according to the joystick system number.
- Address some of Marcel's comments from the previous submission:
http://marc.info/?l=linux-bluetooth&m=125525415718147&w=2
+ Use hidraw
+ separate check for UDEV in the autotools changes
A description of the udev part of the plugin can be found here:
http://article.gmane.org/gmane.linux.kernel.input/18435
Makefile.am | 9 +-
acinclude.m4 | 39 ++++
configure.ac | 1 +
plugins/sixaxis.c | 506 +++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 553 insertions(+), 2 deletions(-)
create mode 100644 plugins/sixaxis.c
diff --git a/Makefile.am b/Makefile.am
index adf6c84..f72ca19 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -202,6 +202,11 @@ builtin_sources += health/hdp_main.c health/hdp_types.h \
health/hdp_util.h health/hdp_util.c
endif
+if SIXAXISPLUGIN
+builtin_modules += sixaxis
+builtin_sources += plugins/sixaxis.c
+endif
+
builtin_modules += hciops mgmtops
builtin_sources += plugins/hciops.c plugins/mgmtops.c
@@ -247,7 +252,7 @@ src_bluetoothd_SOURCES = $(gdbus_sources) $(builtin_sources) \
src/dbus-common.c src/dbus-common.h \
src/event.h src/event.c
src_bluetoothd_LDADD = lib/libbluetooth.la @GLIB_LIBS@ @DBUS_LIBS@ \
- @CAPNG_LIBS@ -ldl -lrt
+ @CAPNG_LIBS@ @UDEV_LIBS@ -ldl -lrt
src_bluetoothd_LDFLAGS = -Wl,--export-dynamic \
-Wl,--version-script=$(srcdir)/src/bluetooth.ver
@@ -363,7 +368,7 @@ EXTRA_DIST += doc/manager-api.txt \
AM_YFLAGS = -d
-AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @CAPNG_CFLAGS@ \
+AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @CAPNG_CFLAGS@ @UDEV_CFLAGS@ \
-DBLUETOOTH_PLUGIN_BUILTIN -DPLUGINDIR=\""$(plugindir)"\"
INCLUDES = -I$(builddir)/lib -I$(builddir)/src -I$(srcdir)/src \
diff --git a/acinclude.m4 b/acinclude.m4
index 91e0956..5437816 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -147,6 +147,35 @@ AC_DEFUN([AC_PATH_USB], [
[Define to 1 if you need the usb_interrupt_read() function.]))
])
+AC_DEFUN([AC_PATH_SIXAXIS], [
+ PKG_CHECK_MODULES(UDEV, libudev, udev_found=yes, udev_found=no)
+ AC_SUBST(UDEV_CFLAGS)
+ AC_SUBST(UDEV_LIBS)
+
+ AC_CACHE_CHECK([for HIDIOCSFEATURE and HIDIOCGFEATURE (for Sixaxis plugin)],
+ [ac_cv_have_HIDIOCxFEATURE],
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[
+ #include <sys/ioctl.h>
+ #include <linux/hidraw.h>
+ #if ! (defined(HIDIOCSFEATURE) && defined(HIDIOCGFEATURE))
+ #error "HIDIOCSFEATURE and HIDIOCGFEATURE are required (linux-libc-dev >= 2.6.3x)"
+ #endif
+ ]],
+ []
+ )],[
+ ac_cv_have_HIDIOCxFEATURE=yes
+ ],[
+ ac_cv_have_HIDIOCxFEATURE="no, get linux-libc-dev >= 2.6.3x"
+ ]
+ )]
+ )
+
+ if ( test "${udev_found}" = "yes" && test "${ac_cv_have_HIDIOCxFEATURE}" = "yes" ); then
+ sixaxis_plugin_deps_found=yes
+ fi
+])
+
AC_DEFUN([AC_PATH_SNDFILE], [
PKG_CHECK_MODULES(SNDFILE, sndfile, sndfile_found=yes, sndfile_found=no)
AC_SUBST(SNDFILE_CFLAGS)
@@ -178,6 +207,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
sndfile_enable=${sndfile_found}
hal_enable=no
usb_enable=${usb_found}
+ sixaxis_enable=${sixaxis_plugin_deps_found}
alsa_enable=${alsa_found}
gstreamer_enable=${gstreamer_found}
audio_enable=yes
@@ -260,6 +290,10 @@ AC_DEFUN([AC_ARG_BLUEZ], [
usb_enable=${enableval}
])
+ AC_ARG_ENABLE(sixaxis, AC_HELP_STRING([--enable-sixaxis], [enable Sixaxis plugin]), [
+ sixaxis_enable=${enableval}
+ ])
+
AC_ARG_ENABLE(tracer, AC_HELP_STRING([--enable-tracer], [install Tracing daemon]), [
tracer_enable=${enableval}
])
@@ -351,6 +385,10 @@ AC_DEFUN([AC_ARG_BLUEZ], [
AC_DEFINE(HAVE_LIBUSB, 1, [Define to 1 if you have USB library.])
fi
+ if (test "${sixaxis_enable}" = "yes" && test "${sixaxis_plugin_deps_found}" = "yes"); then
+ AC_DEFINE(HAVE_SIXAXIS_PLUGIN, 1, [Define to 1 if you have sixaxis plugin.])
+ fi
+
AM_CONDITIONAL(SNDFILE, test "${sndfile_enable}" = "yes" && test "${sndfile_found}" = "yes")
AM_CONDITIONAL(USB, test "${usb_enable}" = "yes" && test "${usb_found}" = "yes")
AM_CONDITIONAL(SBC, test "${alsa_enable}" = "yes" || test "${gstreamer_enable}" = "yes" ||
@@ -383,4 +421,5 @@ AC_DEFUN([AC_ARG_BLUEZ], [
AM_CONDITIONAL(UDEVRULES, test "${udevrules_enable}" = "yes")
AM_CONDITIONAL(CONFIGFILES, test "${configfiles_enable}" = "yes")
AM_CONDITIONAL(MAEMO6PLUGIN, test "${maemo6_enable}" = "yes")
+ AM_CONDITIONAL(SIXAXISPLUGIN, test "${sixaxis_enable}" = "yes" && test "${sixaxis_plugin_deps_found}" = "yes")
])
diff --git a/configure.ac b/configure.ac
index 8564e2b..09af33e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -40,6 +40,7 @@ AC_PATH_GLIB
AC_PATH_ALSA
AC_PATH_GSTREAMER
AC_PATH_USB
+AC_PATH_SIXAXIS
AC_PATH_SNDFILE
AC_PATH_OUI
AC_PATH_READLINE
diff --git a/plugins/sixaxis.c b/plugins/sixaxis.c
new file mode 100644
index 0000000..4f7b3c2
--- /dev/null
+++ b/plugins/sixaxis.c
@@ -0,0 +1,506 @@
+/*
+ * sixaxis plugin: do cable association for Sixaxis controller
+ *
+ * Copyright (C) 2009 Bastien Nocera <[email protected]>
+ * Copyright (C) 2010 Antonio Ospite <[email protected]>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/*
+ * In the following this terminology is used:
+ *
+ * - controller: a Sixaxis joypad.
+ * - adapter: the bluetooth dongle on the host system.
+ * - adapter_bdaddr: the bdaddr of the bluetooth adapter.
+ * - device_bdaddr: the bdaddr of the Sixaxis controller.
+ * - master_bdaddr: the bdaddr of the adapter to be configured into the
+ * Sixaxis controller
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <glib.h>
+#include <linux/hidraw.h>
+
+#define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE 1
+#include <libudev.h>
+
+#include "plugin.h"
+#include "log.h"
+#include "adapter.h"
+#include "device.h"
+#include "manager.h"
+#include "storage.h"
+#include "sdp_lib.h"
+
+#define BDADDR_STR_SIZE 18 /* strlen("00:00:00:00:00:00") + 1 */
+
+/* Vendor and product ID for the Sixaxis PS3 controller */
+#define VENDOR 0x054c
+#define PRODUCT 0x0268
+#define SIXAXIS_NAME "PLAYSTATION(R)3 Controller"
+#define SIXAXIS_PNP_RECORD "3601920900000A000100000900013503191124090004350D35061901000900113503190011090006350909656E09006A0901000900093508350619112409010009000D350F350D350619010009001335031900110901002513576972656C65737320436F6E74726F6C6C65720901012513576972656C65737320436F6E74726F6C6C6572090102251B536F6E7920436F6D707574657220456E7465727461696E6D656E740902000901000902010901000902020800090203082109020428010902052801090206359A35980822259405010904A101A102850175089501150026FF00810375019513150025013500450105091901291381027501950D0600FF8103150026FF0005010901A10075089504350046FF0009300931093209358102C0050175089527090181027508953009019102750895300901B102C0A1028502750895300901B102C0A10285EE750895300901B102C0A10285EF750895300901B102C0C0090207350835060904090901000902082800090209280109020A280109020B09010009020C093E8009020D280009020E2800"
+#define HID_UUID "00001124-0000-1000-8000-00805f9b34fb"
+
+static struct btd_device *create_sixaxis_association(struct btd_adapter *adapter,
+ const char *name,
+ const char *address,
+ guint32 vendor_id,
+ guint32 product_id,
+ const char *pnp_record)
+{
+ DBusConnection *conn;
+ sdp_record_t *rec;
+ struct btd_device *device;
+ bdaddr_t src, dst;
+ char srcaddr[18];
+
+ conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+ if (conn == NULL) {
+ DBG("Failed to get on the bus");
+ return NULL;
+ }
+
+ device = adapter_get_device(conn, adapter, address);
+ if (device != NULL) {
+ device_set_temporary(device, FALSE);
+ device_set_name(device, name);
+ }
+
+ str2ba(address, &dst);
+ adapter_get_address(adapter, &src);
+ ba2str(&src, srcaddr);
+
+ write_device_name(&dst, &src, (char *) name);
+
+ /* Store the device's SDP record */
+ rec = record_from_string(pnp_record);
+ store_record(srcaddr, address, rec);
+ sdp_record_free(rec);
+ /* Set the device id */
+ store_device_id(srcaddr, address, 0xffff, vendor_id, product_id, 0);
+ /* Don't write a profile, it will be updated when the device connects */
+
+ write_trust(srcaddr, address, "[all]", TRUE);
+
+ dbus_connection_unref(conn);
+ return device;
+}
+
+
+/* Usb cable pairing section */
+static unsigned char *get_feature_report(int fd, uint8_t report_number, unsigned int len)
+{
+ unsigned char *buf;
+ int ret;
+
+ buf = calloc(len, sizeof(*buf));
+ if (buf == NULL) {
+ error("%s: calloc failed", __func__);
+ return NULL;
+ }
+
+ buf[0] = report_number;
+
+ ret = ioctl(fd, HIDIOCGFEATURE(len), buf);
+ if (ret < 0) {
+ error("%s: HIDIOCGFEATURE ret = %d", __func__, ret);
+ return NULL;
+ }
+
+ return buf;
+}
+
+static int set_feature_report(int fd, uint8_t *report, int len)
+{
+ int ret;
+
+ ret = ioctl(fd, HIDIOCSFEATURE(len), report);
+ if (ret < 0)
+ error("%s: HIDIOCSFEATURE ret = %d", __func__, ret);
+
+ return ret;
+}
+
+static char *get_device_bdaddr(int fd)
+{
+ unsigned char *buf;
+ char *address;
+
+ buf = get_feature_report(fd, 0xf2, 18);
+ if (buf == NULL) {
+ error("%s: cannot get feature report", __func__);
+ return NULL;
+ }
+
+ address = calloc(BDADDR_STR_SIZE, sizeof(*address));
+ if (address == NULL) {
+ error("%s: calloc failed", __func__);
+ free(buf);
+ return NULL;
+ }
+
+ /* XXX: if we put lowercase hex digits here bluez refuses to associate */
+ snprintf(address, BDADDR_STR_SIZE,
+#if 1
+ "%02X:%02X:%02X:%02X:%02X:%02X",
+#else
+ "%02x:%02x:%02x:%02x:%02x:%02x",
+#endif
+ buf[4], buf[5], buf[6], buf[7], buf[8], buf[9]);
+
+ free(buf);
+ return address;
+}
+
+static gboolean set_master_bdaddr(int fd, char *adapter_bdaddr)
+{
+ uint8_t *report;
+ uint8_t addr[6];
+ int ret;
+
+ ret = sscanf(adapter_bdaddr, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
+ &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]);
+ if (ret != 6) {
+
+ error("%s: Parsing the bt address failed", __func__);
+ return FALSE;
+ }
+
+ report = malloc(8);
+ if (report == NULL) {
+ error("%s: malloc failed", __func__);
+ return FALSE;
+ }
+
+ report[0] = 0xf5;
+ report[1] = 0x01;
+
+ report[2] = addr[0];
+ report[3] = addr[1];
+ report[4] = addr[2];
+ report[5] = addr[3];
+ report[6] = addr[4];
+ report[7] = addr[5];
+
+ ret = set_feature_report(fd, report, 8);
+ if (ret < 0)
+ error("%s: cannot set feature report", __func__);
+
+ DBG("New Master Bluetooth address: %s", adapter_bdaddr);
+
+ free(report);
+
+ return (ret >= 0);
+}
+
+static int sixpair(int fd, struct btd_adapter *adapter)
+{
+ char *device_bdaddr;
+ char adapter_bdaddr[18];
+ struct btd_device *device;
+ bdaddr_t dst;
+
+ adapter_get_address(adapter, &dst);
+ ba2str(&dst, adapter_bdaddr);
+ DBG("Adapter bdaddr %s", adapter_bdaddr);
+
+ if (set_master_bdaddr(fd, adapter_bdaddr) == FALSE) {
+ DBG("Failed to set the master Bluetooth address");
+ return -1;
+ }
+
+ device_bdaddr = get_device_bdaddr(fd);
+ if (device_bdaddr == NULL) {
+ DBG("Failed to get the Bluetooth address from the device");
+ return -1;
+ }
+
+ DBG("Device bdaddr %s", device_bdaddr);
+
+ device = create_sixaxis_association(adapter,
+ SIXAXIS_NAME,
+ device_bdaddr,
+ VENDOR, PRODUCT, SIXAXIS_PNP_RECORD);
+ if (device)
+ btd_device_add_uuid(device, HID_UUID);
+
+ free(device_bdaddr);
+ return 0;
+}
+
+
+/* Led setting section */
+#define LED_1 (0x01 << 1)
+#define LED_2 (0x01 << 2)
+#define LED_3 (0x01 << 3)
+#define LED_4 (0x01 << 4)
+
+#define LED_STATUS_OFF 0
+#define LED_STATUS_ON 1
+
+static int set_leds(int fd, unsigned char leds_status[4])
+{
+ int ret;
+
+ /*
+ * the total time the led is active (0xff means forever)
+ * | duty_length: how long a cycle is in deciseconds (0 means "blink really fast")
+ * | | ??? (Some form of phase shift or duty_length multiplier?)
+ * | | | % of duty_length the led is off (0xff means 100%)
+ * | | | | % of duty_length the led is on (0xff mean 100%)
+ * | | | | |
+ * 0xff, 0x27, 0x10, 0x00, 0x32,
+ */
+ unsigned char leds_report[] = {
+ 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, /* rumble values TBD */
+ 0x00, 0x00, 0x00, 0x00, 0x1e, /* 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 leds = 0;
+ if (leds_status[0])
+ leds |= LED_1;
+ if (leds_status[1])
+ leds |= LED_2;
+ if (leds_status[2])
+ leds |= LED_3;
+ if (leds_status[3])
+ leds |= LED_4;
+
+ leds_report[10] = leds;
+
+ ret = write(fd, leds_report, sizeof(leds_report));
+ if (ret < (ssize_t) sizeof(leds_report))
+ perror("Unable to write to hidraw device");
+
+ return ret;
+}
+
+static int set_controller_number(int fd, unsigned int n)
+{
+ unsigned char leds_status[4] = {0, 0, 0, 0};
+
+ switch (n) {
+ case 0:
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ leds_status[n - 1] = LED_STATUS_ON;
+ break;
+ case 5:
+ case 6:
+ case 7:
+ leds_status[4 - 1] = LED_STATUS_ON;
+ leds_status[n - 4 - 1] = LED_STATUS_ON;
+ break;
+ default:
+ error("Only 7 controllers supported for now.");
+ return -1;
+ }
+
+ return set_leds(fd, leds_status);
+}
+
+
+static void handle_device_plug(struct udev_device *udevice)
+{
+ struct udev_device *hid_parent;
+ struct udev_enumerate *enumerate;
+ struct udev_list_entry *devices, *dev_list_entry;
+ const char *hid_phys;
+ const char *hidraw_node;
+ unsigned char is_usb = FALSE;
+ int js_num = 0;
+ int fd;
+
+ hid_parent = udev_device_get_parent_with_subsystem_devtype(udevice, "hid", NULL);
+ if (!hid_parent) {
+ error("cannot get parent hid device.");
+ return;
+ }
+
+ if (g_str_has_suffix(udev_device_get_property_value(hid_parent, "HID_NAME"),
+ "PLAYSTATION(R)3 Controller") == FALSE)
+ return;
+
+ DBG("Found a Sixaxis device");
+
+ hidraw_node = udev_device_get_devnode(udevice);
+
+ hid_phys = udev_device_get_property_value(hid_parent, "HID_PHYS");
+
+ /* looking for joysticks */
+ 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) {
+ const char *devname;
+ struct udev_device *js_dev;
+ struct udev_device *input_parent;
+ const char *input_phys;
+
+ 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) {
+ error("cannot get parent input device.");
+ continue;
+ }
+
+ /* check this is the joystick relative to the hidraw device above */
+ input_phys = udev_device_get_sysattr_value(input_parent, "phys");
+ if (g_strcmp0(input_phys, hid_phys) == 0) {
+ js_num = atoi(udev_device_get_sysnum(js_dev)) + 1;
+ DBG("joypad device_num: %d\n", js_num);
+ DBG("hidraw_node: %s\n", hidraw_node);
+ DBG("driver: %s\n",
+ udev_device_get_property_value(js_dev, "ID_USB_DRIVER"));
+
+ if (g_strcmp0(udev_device_get_property_value(js_dev, "ID_USB_DRIVER"),
+ "usbhid") == 0)
+ is_usb = TRUE;
+ }
+
+ udev_device_unref(js_dev);
+ }
+
+ udev_enumerate_unref(enumerate);
+
+ fd = open(hidraw_node, O_RDWR);
+ if (fd < 0) {
+ error("%s: hidraw open", __func__);
+ return;
+ }
+
+ if (js_num > 0)
+ set_controller_number(fd, js_num);
+ if (is_usb) {
+ struct btd_adapter *adapter;
+
+ /* Look for the default adapter */
+ adapter = manager_get_default_adapter();
+ if (adapter == NULL) {
+ DBG("No adapters, exiting");
+ return;
+ }
+ sixpair(fd, adapter);
+ }
+
+ close(fd);
+}
+
+static gboolean device_event_idle(struct udev_device *udevice)
+{
+ handle_device_plug(udevice);
+ udev_device_unref(udevice);
+ return FALSE;
+}
+
+static struct udev *ctx = NULL;
+static struct udev_monitor *monitor = NULL;
+static guint watch_id = 0;
+
+static gboolean
+monitor_event(GIOChannel *source,
+ GIOCondition condition,
+ gpointer data)
+{
+ struct udev_device *udevice;
+
+ udevice = udev_monitor_receive_device(monitor);
+ if (udevice == NULL)
+ goto out;
+ if (g_strcmp0(udev_device_get_action(udevice), "add") != 0) {
+ udev_device_unref(udevice);
+ goto out;
+ }
+
+ g_timeout_add_seconds(1, (GSourceFunc) device_event_idle, udevice);
+
+out:
+ return TRUE;
+}
+
+
+static int sixaxis_init(void)
+{
+ GIOChannel *channel;
+
+ DBG("Setup Sixaxis cable plugin");
+
+ ctx = udev_new();
+ monitor = udev_monitor_new_from_netlink(ctx, "udev");
+ if (monitor == NULL) {
+ error("Could not get udev monitor");
+ return -1;
+ }
+
+ /* Listen for newly connected hidraw interfaces */
+ udev_monitor_filter_add_match_subsystem_devtype(monitor,
+ "hidraw", NULL);
+ udev_monitor_enable_receiving(monitor);
+
+ channel = g_io_channel_unix_new(udev_monitor_get_fd(monitor));
+ watch_id = g_io_add_watch(channel, G_IO_IN, monitor_event, NULL);
+ g_io_channel_unref(channel);
+
+ return 0;
+}
+
+static void sixaxis_exit(void)
+{
+ DBG("Cleanup Sixaxis cable plugin");
+
+ if (watch_id != 0) {
+ g_source_remove(watch_id);
+ watch_id = 0;
+ }
+ if (monitor != NULL) {
+ udev_monitor_unref(monitor);
+ monitor = NULL;
+ }
+ if (ctx != NULL) {
+ udev_unref(ctx);
+ ctx = NULL;
+ }
+}
+
+BLUETOOTH_PLUGIN_DEFINE(sixaxis, VERSION,
+ BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+ sixaxis_init, sixaxis_exit)
--
1.7.4.1
This is the old way to associate to a Sixaxis controller and it is not
even compiled in, so we can safely get rid of it.
Signed-off-by: Antonio Ospite <[email protected]>
---
input/sixpair.c | 299 -------------------------------------------------------
1 files changed, 0 insertions(+), 299 deletions(-)
delete mode 100644 input/sixpair.c
diff --git a/input/sixpair.c b/input/sixpair.c
deleted file mode 100644
index 5c58b9b..0000000
--- a/input/sixpair.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/* To compile
- * gcc -g -Wall -I../src -I../lib/ -I../include -DSTORAGEDIR=\"/var/lib/bluetooth\" -o sixpair sixpair.c ../src/storage.c ../common/libhelper.a -I../common `pkg-config --libs --cflags glib-2.0 libusb-1.0` -lbluetooth
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <inttypes.h>
-
-#include <sdp.h>
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/sdp_lib.h>
-#include <glib.h>
-#include <libusb.h>
-
-#include "storage.h"
-
-/* Vendor and product ID for the Sixaxis PS3 controller */
-#define VENDOR 0x054c
-#define PRODUCT 0x0268
-
-#define PS3_PNP_RECORD "3601920900000A000100000900013503191124090004350D35061901000900113503190011090006350909656E09006A0901000900093508350619112409010009000D350F350D350619010009001335031900110901002513576972656C65737320436F6E74726F6C6C65720901012513576972656C65737320436F6E74726F6C6C6572090102251B536F6E7920436F6D707574657220456E7465727461696E6D656E740902000901000902010901000902020800090203082109020428010902052801090206359A35980822259405010904A101A102850175089501150026FF00810375019513150025013500450105091901291381027501950D0600FF8103150026FF0005010901A10075089504350046FF0009300931093209358102C0050175089527090181027508953009019102750895300901B102C0A1028502750895300901B102C0A10285EE750895300901B102C0A10285EF750895300901B102C0C0090207350835060904090901000902082800090209280109020A280109020B09010009020C093E8009020D280009020E2800"
-
-gboolean option_get_master = TRUE;
-char *option_master= NULL;
-gboolean option_store_info = TRUE;
-const char *option_device = NULL;
-gboolean option_quiet = FALSE;
-
-const GOptionEntry options[] = {
- { "get-master", '\0', 0, G_OPTION_ARG_NONE, &option_get_master, "Get currently set master address", NULL },
- { "set-master", '\0', 0, G_OPTION_ARG_STRING, &option_master, "Set master address (\"auto\" for automatic)", NULL },
- { "store-info", '\0', 0, G_OPTION_ARG_NONE, &option_store_info, "Store the HID info into the input database", NULL },
- { "device", '\0', 0, G_OPTION_ARG_STRING, &option_device, "Only handle one device (default, all supported", NULL },
- { "quiet", 'q', 0, G_OPTION_ARG_NONE, &option_quiet, "Quieten the output", NULL },
- { NULL }
-};
-
-static gboolean
-show_master (libusb_device_handle *devh, int itfnum)
-{
- unsigned char msg[8];
- int res;
-
- res = libusb_control_transfer (devh,
- LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
- 0x01, 0x03f5, itfnum,
- (void*) msg, sizeof(msg),
- 5000);
-
- if (res < 0) {
- g_warning ("Getting the master Bluetooth address failed");
- return FALSE;
- }
- g_print ("Current Bluetooth master: %02X:%02X:%02X:%02X:%02X:%02X\n",
- msg[2], msg[3], msg[4], msg[5], msg[6], msg[7]);
-
- return TRUE;
-}
-
-static char *
-get_bdaddr (libusb_device_handle *devh, int itfnum)
-{
- unsigned char msg[17];
- char *address;
- int res;
-
- res = libusb_control_transfer (devh,
- LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
- 0x01, 0x03f2, itfnum,
- (void*) msg, sizeof(msg),
- 5000);
-
- if (res < 0) {
- g_warning ("Getting the device Bluetooth address failed");
- return NULL;
- }
-
- address = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
- msg[4], msg[5], msg[6], msg[7], msg[8], msg[9]);
-
- if (option_quiet == FALSE) {
- g_print ("Device Bluetooth address: %s\n", address);
- }
-
- return address;
-}
-
-static gboolean
-set_master_bdaddr (libusb_device_handle *devh, int itfnum, char *host)
-{
- unsigned char msg[8];
- int mac[6];
- int res;
-
- if (sscanf(host, "%X:%X:%X:%X:%X:%X",
- &mac[0],&mac[1],&mac[2],&mac[3],&mac[4],&mac[5]) != 6) {
- return FALSE;
- }
-
- msg[0] = 0x01;
- msg[1] = 0x00;
- msg[2] = mac[0];
- msg[3] = mac[1];
- msg[4] = mac[2];
- msg[5] = mac[3];
- msg[6] = mac[4];
- msg[7] = mac[5];
-
- res = libusb_control_transfer (devh,
- LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
- 0x09, 0x03f5, itfnum,
- (void*) msg, sizeof(msg),
- 5000);
-
- if (res < 0) {
- g_warning ("Setting the master Bluetooth address failed");
- return FALSE;
- }
-
- return TRUE;
-}
-
-static char *
-get_host_bdaddr (void)
-{
- FILE *f;
- int mac[6];
-
- //FIXME use dbus to get the default adapter
-
- f = popen("hcitool dev", "r");
-
- if (f == NULL) {
- //FIXME
- return NULL;
- }
- if (fscanf(f, "%*s\n%*s %X:%X:%X:%X:%X:%X",
- &mac[0],&mac[1],&mac[2],&mac[3],&mac[4],&mac[5]) != 6) {
- //FIXME
- return NULL;
- }
-
- return g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
-}
-
-static int
-handle_device (libusb_device *dev, struct libusb_config_descriptor *cfg, int itfnum, const struct libusb_interface_descriptor *alt)
-{
- libusb_device_handle *devh;
- int res, retval;
-
- retval = -1;
-
- if (libusb_open (dev, &devh) < 0) {
- g_warning ("Can't open device");
- goto bail;
- }
- libusb_detach_kernel_driver (devh, itfnum);
-
- res = libusb_claim_interface (devh, itfnum);
- if (res < 0) {
- g_warning ("Can't claim interface %d", itfnum);
- goto bail;
- }
-
- if (option_get_master != FALSE) {
- if (show_master (devh, itfnum) == FALSE)
- goto bail;
- retval = 0;
- }
-
- if (option_master != NULL) {
- if (strcmp (option_master, "auto") == 0) {
- g_free (option_master);
- option_master = get_host_bdaddr ();
- if (option_master == NULL) {
- g_warning ("Can't get bdaddr from default device");
- retval = -1;
- goto bail;
- }
- }
- } else {
- option_master = get_host_bdaddr ();
- if (option_master == NULL) {
- g_warning ("Can't get bdaddr from default device");
- retval = -1;
- goto bail;
- }
- }
-
- if (option_store_info != FALSE) {
- sdp_record_t *rec;
- char *device;
- bdaddr_t dst, src;
-
- device = get_bdaddr (devh, itfnum);
- if (device == NULL) {
- retval = -1;
- goto bail;
- }
-
- rec = record_from_string (PS3_PNP_RECORD);
- store_record(option_master, device, rec);
- write_trust(option_master, device, "[all]", TRUE);
- store_device_id(option_master, device, 0xffff, 0x054c, 0x0268, 0);
- str2ba(option_master, &src);
- str2ba(device, &dst);
- write_device_profiles(&src, &dst, "");
- write_device_name(&src, &dst, "PLAYSTATION(R)3 Controller");
- sdp_record_free(rec);
-
- if (set_master_bdaddr (devh, itfnum, option_master) == FALSE) {
- retval = -1;
- goto bail;
- }
- }
-
-bail:
- libusb_release_interface (devh, itfnum);
- res = libusb_attach_kernel_driver(devh, itfnum);
- if (res < 0) {
- //FIXME sometimes the kernel tells us ENOENT, but succeeds anyway...
- g_warning ("Reattaching the driver failed: %d", res);
- }
- if (devh != NULL)
- libusb_close (devh);
-
- return retval;
-}
-
-int main (int argc, char **argv)
-{
- GOptionContext *context;
- GError *error = NULL;
- libusb_device **list;
- ssize_t num_devices, i;
-
- context = g_option_context_new ("- Manage Sixaxis PS3 controllers");
- g_option_context_add_main_entries (context, options, NULL);
- if (g_option_context_parse (context, &argc, &argv, &error) == FALSE) {
- g_warning ("Couldn't parse command-line options: %s", error->message);
- return 1;
- }
-
- /* Check that the passed bdaddr is correct */
- if (option_master != NULL && strcmp (option_master, "auto") != 0) {
- //FIXME check bdaddr
- }
-
- libusb_init (NULL);
-
- /* Find device(s) */
- num_devices = libusb_get_device_list (NULL, &list);
- if (num_devices < 0) {
- g_warning ("libusb_get_device_list failed");
- return 1;
- }
-
- for (i = 0; i < num_devices; i++) {
- struct libusb_config_descriptor *cfg;
- libusb_device *dev = list[i];
- struct libusb_device_descriptor desc;
- guint8 j;
-
- if (libusb_get_device_descriptor (dev, &desc) < 0) {
- g_warning ("libusb_get_device_descriptor failed");
- continue;
- }
-
- /* Here we check for the supported devices */
- if (desc.idVendor != VENDOR || desc.idProduct != PRODUCT)
- continue;
-
- /* Look for the interface number that interests us */
- for (j = 0; j < desc.bNumConfigurations; j++) {
- struct libusb_config_descriptor *config;
- guint8 k;
-
- libusb_get_config_descriptor (dev, j, &config);
-
- for (k = 0; k < config->bNumInterfaces; k++) {
- const struct libusb_interface *itf = &config->interface[k];
- int l;
-
- for (l = 0; l < itf->num_altsetting ; l++) {
- struct libusb_interface_descriptor alt;
-
- alt = itf->altsetting[l];
- if (alt.bInterfaceClass == 3) {
- handle_device (dev, cfg, l, &alt);
- }
- }
- }
- }
- }
-
- return 0;
-}
-
--
1.7.4.1
From: Bastien Nocera <[email protected]>
Signed-off-by: Bastien Nocera <[email protected]>
Signed-off-by: Antonio Ospite <[email protected]>
---
src/manager.c | 5 +++++
src/manager.h | 1 +
2 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/src/manager.c b/src/manager.c
index e805e0c..254ace4 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -262,6 +262,11 @@ static void manager_set_default_adapter(int id)
DBUS_TYPE_INVALID);
}
+struct btd_adapter *manager_get_default_adapter(void)
+{
+ return manager_find_adapter_by_id(default_adapter_id);
+}
+
static void manager_remove_adapter(struct btd_adapter *adapter)
{
uint16_t dev_id = adapter_get_dev_id(adapter);
diff --git a/src/manager.h b/src/manager.h
index 05c38b3..4f92d2f 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -35,6 +35,7 @@ void manager_cleanup(DBusConnection *conn, const char *path);
const char *manager_get_base_path(void);
struct btd_adapter *manager_find_adapter(const bdaddr_t *sba);
struct btd_adapter *manager_find_adapter_by_id(int id);
+struct btd_adapter *manager_get_default_adapter(void);
void manager_foreach_adapter(adapter_cb func, gpointer user_data);
GSList *manager_get_adapters(void);
struct btd_adapter *btd_manager_register_adapter(int id);
--
1.7.4.1
On Fri, 25 Mar 2011 11:31:05 -0400
Jim Paris <[email protected]> wrote:
> Antonio Ospite wrote:
> > With regard to that, I'd like to see some USB dumps of a Sixaxis
> > talking with GameOS to check if the PS3 can turn off BT on the
> > controller explicitly, can anyone help here? (Pascal? Do you have
> > access to a USB analyzer?):
> >
> > The scenarios I am interested in are:
> > 1. Connect a non-paired Sixaxis to the PS3 via USB
> > 2. Connect an already paired Sixaxis to the PS3 via USB
> > 3. Connect a Sixaxis already associated via BT to a PS3 via USB
>
> Hi Antonio,
>
> You asked me for this a while ago, sorry it took so long. I ran some
> tests and put the log files here:
> http://ps3.jim.sh/sixaxis/dumps/
>
Thanks a lot Jim, now I know what to do if I got bored this weekend.
[...]
> I also did some quick captures of pairing the keypad (CECHZK1UC) and
> original headset (CECHYA-0075). They are being paired with 00:13:a9:74:fe:57.
> http://ps3.jim.sh/sixaxis/dumps/
>
> -jim
>
If I get to taking a look at those I could ask Bastien to test some
stuff too :)
Thanks,
Antonio
--
Antonio Ospite
http://ao2.it
PGP public key ID: 0x4553B001
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
Antonio Ospite wrote:
> With regard to that, I'd like to see some USB dumps of a Sixaxis
> talking with GameOS to check if the PS3 can turn off BT on the
> controller explicitly, can anyone help here? (Pascal? Do you have
> access to a USB analyzer?):
>
> The scenarios I am interested in are:
> 1. Connect a non-paired Sixaxis to the PS3 via USB
> 2. Connect an already paired Sixaxis to the PS3 via USB
> 3. Connect a Sixaxis already associated via BT to a PS3 via USB
Hi Antonio,
You asked me for this a while ago, sorry it took so long. I ran some
tests and put the log files here:
http://ps3.jim.sh/sixaxis/dumps/
There are comments in the file:
$ grep Comment sixaxis-pairing-tests-abbreviated.csv
0,,2,0:03.145.728,,,,,,Comment,,"1. Controller is a DS3 model CECHZC2U, bdaddr 00:24:33:E6:2C:3C"
0,,3,0:04.893.354,,,,,,Comment,,"2. PS3-1 is on and has bdaddr 00:13:a9:74:fe:57"
0,,4,0:05.592.405,,,,,,Comment,,"3. PS3-2 is on and has bdaddr 00:23:06:52:e4:e3"
0,,5,0:05.941.930,,,,,,Comment,,"4. Controller previously paired with 00:11:22:33:44:55"
0,,6,0:06.640.981,,,,,,Comment,,"5. Controller powered off with rear button"
0,,7,0:08.738.133,,,,,,Comment,,"6. About to plug controller into PS3-1 (off, wrong pairing)"
0,,285,0:16.314.138,,,,,,Comment,,"7. About to press PS button"
0,,914,0:20.841.170,,,,,,Comment,,"8. Unplugged controller"
0,,915,0:34.123.132,,,,,,Comment,,"9. Controller is now associated with PS3-1"
0,,916,0:41.113.639,,,,,,Comment,,"10. Controller powered off with rear button"
0,,917,0:41.113.639,,,,,,Comment,,"11. About to plug controller into PS3-1 (off, correct pairing)"
0,,1193,1:01.075.280,,,,,,Comment,,"12. Unplugged controller"
0,,1194,1:11.211.515,,,,,,Comment,,"13. Pressed PS button"
0,,1195,1:27.639.205,,,,,,Comment,,"14. Controller is now associated with PS3-1"
0,,1196,1:27.639.205,,,,,,Comment,,"15. About to plug controller into PS3-1 (associated with this PS3)"
0,,2311,1:41.665.351,,,,,,Comment,,"16. Unplugged controller"
0,,2312,1:44.112.029,,,,,,Comment,,"17. Paired and associated controller with PS3-2"
0,,2313,1:57.393.991,,,,,,Comment,,"18. About to plug controller into PS3-1 (associated with different PS3)"
0,,4585,2:26.172.515,,,,,,Comment,,"19. Unplugged controller"
> > The PS3 add-on keyboard, and the PS3 headset both use cable pairing. I
> > have them around, but was unable to get them to pair.
>
> I don't have the hardware so I never searched to see what the
> differences with the Sixaxis are.
I also did some quick captures of pairing the keypad (CECHZK1UC) and
original headset (CECHYA-0075). They are being paired with 00:13:a9:74:fe:57.
http://ps3.jim.sh/sixaxis/dumps/
-jim
On Fri, 25 Feb 2011 12:34:02 +0000
Bastien Nocera <[email protected]> wrote:
> On Fri, 2011-02-25 at 11:04 +0100, Antonio Ospite wrote:
[...]
> >
> > TODO before merging:
> > - Check the routine about bluetooth association. Also, is it strictly
> > necessary to grant manually the first connection?
>
> The line setting the device trust should be enough to not have to
> manually grant the first connection. You might want to double-check what
> changes between the state of /var/lib/bluetooth after cable pairing and
> before connecting for the first time.
>
Calling write_trust() before adapter_get_device() fixes the prompt on
the first association, AFAICS adapter_get_device() reads the trust file.
> > - When the controller is connected via USB after it is working over BT
> > it is seen as a second controller and the second LED is turned on,
> > should we force BT disconnection on USB connection?
>
> If we can assert that the device is the same one, yes, I think we
> should.
>
With regard to that, I'd like to see some USB dumps of a Sixaxis
talking with GameOS to check if the PS3 can turn off BT on the
controller explicitly, can anyone help here? (Pascal? Do you have
access to a USB analyzer?):
The scenarios I am interested in are:
1. Connect a non-paired Sixaxis to the PS3 via USB
2. Connect an already paired Sixaxis to the PS3 via USB
3. Connect a Sixaxis already associated via BT to a PS3 via USB
> > - Test with multiple controllers, and/or multiple BT adapters, which I
> > can't do right now.
> > - Remove the XXX comment about the lowercase hex bdaddr format.
> >
Another TODO item: avoid setting the led before the controller sends
input events (this is the GameOS behavior as well): I am planning to add
a blocking read() in order to wait for the user to press the PS button
before setting the led, I'll emphasize that in the next review round.
> >
> > FUTURE plans:
> > - Add support for battery status report
>
> Where is the battery level exported currently?
>
It is exported in the input report.
> > - Add support for Playstation Move (I don't have the hardware, tho),
> > Pascal?
>
> The PS3 add-on keyboard, and the PS3 headset both use cable pairing. I
> have them around, but was unable to get them to pair.
>
I don't have the hardware so I never searched to see what the
differences with the Sixaxis are.
Regards,
Antonio
--
Antonio Ospite
http://ao2.it
PGP public key ID: 0x4553B001
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
On Sat, 2011-05-07 at 01:14 +0200, Antonio Ospite wrote:
> On Fri, 06 May 2011 02:14:38 +0100
> Bastien Nocera <[email protected]> wrote:
>
> > On Fri, 2011-02-25 at 11:04 +0100, Antonio Ospite wrote:
> > > + [AC_LANG_PROGRAM([[
> > > + #include <sys/ioctl.h>
> > > + #include <linux/hidraw.h>
> > > + #if ! (defined(HIDIOCSFEATURE) &&
> > > defined(HIDIOCGFEATURE))
> > > + #error "HIDIOCSFEATURE and
> > > HIDIOCGFEATURE are required (linux-libc-dev >= 2.6.3x)"
> > > + #endif
> > > + ]],
> >
> > The only part of the patch I have a problem with is this one.
> >
> > I'd rather the code had:
> > #ifndef HIDIOCSFEATURE
> > #define HIDIOCSFEATURE bleh
> > #endif
> >
> > And gracefully handled the ioctl not being available on the running
> > kernel (eg. "Not handling plugged in Sixaxis joypad because the kernel
> > lacks HIDIOCSFEATURE support").
> >
>
> Thinking twice about that, maybe I haven't fully understood what you
> mean.
>
> Do you want that the plugin can be enabled and _compiled_ on _older_
> kernels as well?
No, the plugin can be built with older kernel headers. The kernel
headers are shipped as part of the glibc, and should offer a "stable"
interface to the Linux kernel. The Debian way of shipping supposed glibc
kernel headers which actually come from the running kernel is something
that's frowned upon.
> Because about compiling on _supported_ ones and then _running_ it on
> _older_ ones, well, the ioctl return values are already checked and
> they should just (gracefully?) fail on unsupported kernels. But I'll
> double check this scenario.
>
> If you want indeed it to be _compiled_ on older kernels and nonetheless
> still work on supported ones, I think we just have to copy the iotcls
> request defines from hidraw.h if they are not defined but I still don't
> know if I like that.
Again, it's not compiling against older kernels. but compiling against
older kernel headers, which is a wildly different thing.
I'd like the plugin to be enabled, even if building with older kernel
headers, as those have no relation to the capabilities of the running
kernel.
It would also make the whole thing easier to test (just install a newer
kernel with the patches merged in, and voila, working sisaxis pairing).
Cheers
On Fri, 06 May 2011 02:14:38 +0100
Bastien Nocera <[email protected]> wrote:
> On Fri, 2011-02-25 at 11:04 +0100, Antonio Ospite wrote:
> > + [AC_LANG_PROGRAM([[
> > + #include <sys/ioctl.h>
> > + #include <linux/hidraw.h>
> > + #if ! (defined(HIDIOCSFEATURE) &&
> > defined(HIDIOCGFEATURE))
> > + #error "HIDIOCSFEATURE and
> > HIDIOCGFEATURE are required (linux-libc-dev >= 2.6.3x)"
> > + #endif
> > + ]],
>
> The only part of the patch I have a problem with is this one.
>
> I'd rather the code had:
> #ifndef HIDIOCSFEATURE
> #define HIDIOCSFEATURE bleh
> #endif
>
> And gracefully handled the ioctl not being available on the running
> kernel (eg. "Not handling plugged in Sixaxis joypad because the kernel
> lacks HIDIOCSFEATURE support").
>
Thinking twice about that, maybe I haven't fully understood what you
mean.
Do you want that the plugin can be enabled and _compiled_ on _older_
kernels as well?
Because about compiling on _supported_ ones and then _running_ it on
_older_ ones, well, the ioctl return values are already checked and
they should just (gracefully?) fail on unsupported kernels. But I'll
double check this scenario.
If you want indeed it to be _compiled_ on older kernels and nonetheless
still work on supported ones, I think we just have to copy the iotcls
request defines from hidraw.h if they are not defined but I still don't
know if I like that.
Regards,
Antonio
--
Antonio Ospite
http://ao2.it
PGP public key ID: 0x4553B001
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
On Fri, 06 May 2011 02:14:38 +0100
Bastien Nocera <[email protected]> wrote:
> On Fri, 2011-02-25 at 11:04 +0100, Antonio Ospite wrote:
> > + [AC_LANG_PROGRAM([[
> > + #include <sys/ioctl.h>
> > + #include <linux/hidraw.h>
> > + #if ! (defined(HIDIOCSFEATURE) &&
> > defined(HIDIOCGFEATURE))
> > + #error "HIDIOCSFEATURE and
> > HIDIOCGFEATURE are required (linux-libc-dev >= 2.6.3x)"
> > + #endif
> > + ]],
>
> The only part of the patch I have a problem with is this one.
>
> I'd rather the code had:
> #ifndef HIDIOCSFEATURE
> #define HIDIOCSFEATURE bleh
> #endif
>
> And gracefully handled the ioctl not being available on the running
> kernel (eg. "Not handling plugged in Sixaxis joypad because the kernel
> lacks HIDIOCSFEATURE support").
>
I'll give that a try a report back my opinion.
Thanks.
> The rest looks fine, and I'll be testing whether my Fedora 15 kernel has
> the feature merged in yet (which would make testing your code much
> easier).
>
Regards,
Antonio
--
Antonio Ospite
http://ao2.it
PGP public key ID: 0x4553B001
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
On Fri, 2011-02-25 at 11:04 +0100, Antonio Ospite wrote:
> + [AC_LANG_PROGRAM([[
> + #include <sys/ioctl.h>
> + #include <linux/hidraw.h>
> + #if ! (defined(HIDIOCSFEATURE) &&
> defined(HIDIOCGFEATURE))
> + #error "HIDIOCSFEATURE and
> HIDIOCGFEATURE are required (linux-libc-dev >= 2.6.3x)"
> + #endif
> + ]],
The only part of the patch I have a problem with is this one.
I'd rather the code had:
#ifndef HIDIOCSFEATURE
#define HIDIOCSFEATURE bleh
#endif
And gracefully handled the ioctl not being available on the running
kernel (eg. "Not handling plugged in Sixaxis joypad because the kernel
lacks HIDIOCSFEATURE support").
The rest looks fine, and I'll be testing whether my Fedora 15 kernel has
the feature merged in yet (which would make testing your code much
easier).
Cheers
On Fri, 3 Jun 2011 11:56:38 -0400
[email protected] wrote:
> Just generally on this subject, should the code which performs the USB
> 'write' be in 'hid-sony.c' rather than the BT core.
>
> It's possible that the Sixaxis or other compatible controllers will be
> only USB connected and BT might not even exist on the system.
>
> If/When I manage to do some work on rumble support, we will probably need
> to ensure that a 'hid-sonyff.c' is aware of any LED settings otherwise it
> might overwrite them when setting the rumble.
>
About leds: in order to decide which leds to set in a meaningful way we
need to know the X in /dev/input/jsX, and udev is the only way I know
to find that out, so either in a bluez plugin or in a standalone
daemon I think the answer is in userspace.
About knowing the led status, I have to check if we can read the led
settings out of the device after we have set them in the HID Output
Report, that's a good point.
Thanks,
Antonio
--
Antonio Ospite
http://ao2.it
PGP public key ID: 0x4553B001
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
Just generally on this subject, should the code which performs the USB
'write' be in 'hid-sony.c' rather than the BT core.
It's possible that the Sixaxis or other compatible controllers will be
only USB connected and BT might not even exist on the system.
If/When I manage to do some work on rumble support, we will probably need
to ensure that a 'hid-sonyff.c' is aware of any LED settings otherwise it
might overwrite them when setting the rumble.
Simon.
On Fri, 2011-06-03 at 13:59 +0200, Antonio Ospite wrote:
> On Sat, 07 May 2011 17:57:07 +0100
> Bastien Nocera <[email protected]> wrote:
>
> > On Sat, 2011-05-07 at 01:14 +0200, Antonio Ospite wrote:
> > > On Fri, 06 May 2011 02:14:38 +0100
> > > Bastien Nocera <[email protected]> wrote:
> > >
> > > > On Fri, 2011-02-25 at 11:04 +0100, Antonio Ospite wrote:
> > > > > + [AC_LANG_PROGRAM([[
> > > > > + #include <sys/ioctl.h>
> > > > > + #include <linux/hidraw.h>
> > > > > + #if ! (defined(HIDIOCSFEATURE) &&
> > > > > defined(HIDIOCGFEATURE))
> > > > > + #error "HIDIOCSFEATURE and
> > > > > HIDIOCGFEATURE are required (linux-libc-dev >= 2.6.3x)"
> > > > > + #endif
> > > > > + ]],
> > > >
> > > > The only part of the patch I have a problem with is this one.
> > > >
> > > > I'd rather the code had:
> > > > #ifndef HIDIOCSFEATURE
> > > > #define HIDIOCSFEATURE bleh
> > > > #endif
> > > >
> [...]
> > Again, it's not compiling against older kernels. but compiling against
> > older kernel headers, which is a wildly different thing.
> >
> > I'd like the plugin to be enabled, even if building with older kernel
> > headers, as those have no relation to the capabilities of the running
> > kernel.
> >
> > It would also make the whole thing easier to test (just install a newer
> > kernel with the patches merged in, and voila, working sisaxis pairing).
> >
>
> Bastien, I'd fulfill your request on the lines of the following
> WIP patch, the intent is to make the plugin compile unconditionally
> still mentioning the soft dependency on 2.6.39-rc1.
> I could have set HAVE_HIDIOCxFEATURE in acinclude.m4 and checked for
> that in sixaxis.c in place of the explicit ifdefs, what is the common
> practice about that?
>
> I still have to take care of the runtime check when running on older
> kernels.
>
> Regards,
> Antonio
>
> diff --git a/acinclude.m4 b/acinclude.m4
> index 901bb4d..e3e0fdd 100644
> --- a/acinclude.m4
> +++ b/acinclude.m4
> @@ -167,12 +167,12 @@ AC_DEFUN([AC_PATH_SIXAXIS], [
> )],[
> ac_cv_have_HIDIOCxFEATURE=yes
> ],[
> - ac_cv_have_HIDIOCxFEATURE="no, get linux-libc-dev >= 2.6.39-rc1"
> + ac_cv_have_HIDIOCxFEATURE="no, emulating linux-libc-dev >= 2.6.39-rc1"
> ]
> )]
> )
>
> - if ( test "${udev_found}" = "yes" && test "${ac_cv_have_HIDIOCxFEATURE}" = "yes" ); then
> + if ( test "${udev_found}" = "yes" ); then
> sixaxis_plugin_deps_found=yes
> fi
> ])
Just remove the macro check from acinclude.m4 altogether. It's not
needed, you already have the necessary checks in the plugin itself.
> diff --git a/plugins/sixaxis.c b/plugins/sixaxis.c
> index 49aad25..fc12878 100644
> --- a/plugins/sixaxis.c
> +++ b/plugins/sixaxis.c
> @@ -58,6 +58,16 @@
> #include "storage.h"
> #include "sdp_lib.h"
>
> +/* Fallback definitions to compile with older headers */
> +#ifndef HIDIOCGFEATURE
> +#define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len)
> +#endif
> +
> +#ifndef HIDIOCSFEATURE
> +#define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len)
> +#endif
Looks fine to me.
Cheers
On Sat, 07 May 2011 17:57:07 +0100
Bastien Nocera <[email protected]> wrote:
> On Sat, 2011-05-07 at 01:14 +0200, Antonio Ospite wrote:
> > On Fri, 06 May 2011 02:14:38 +0100
> > Bastien Nocera <[email protected]> wrote:
> >
> > > On Fri, 2011-02-25 at 11:04 +0100, Antonio Ospite wrote:
> > > > + [AC_LANG_PROGRAM([[
> > > > + #include <sys/ioctl.h>
> > > > + #include <linux/hidraw.h>
> > > > + #if ! (defined(HIDIOCSFEATURE) &&
> > > > defined(HIDIOCGFEATURE))
> > > > + #error "HIDIOCSFEATURE and
> > > > HIDIOCGFEATURE are required (linux-libc-dev >= 2.6.3x)"
> > > > + #endif
> > > > + ]],
> > >
> > > The only part of the patch I have a problem with is this one.
> > >
> > > I'd rather the code had:
> > > #ifndef HIDIOCSFEATURE
> > > #define HIDIOCSFEATURE bleh
> > > #endif
> > >
[...]
> Again, it's not compiling against older kernels. but compiling against
> older kernel headers, which is a wildly different thing.
>
> I'd like the plugin to be enabled, even if building with older kernel
> headers, as those have no relation to the capabilities of the running
> kernel.
>
> It would also make the whole thing easier to test (just install a newer
> kernel with the patches merged in, and voila, working sisaxis pairing).
>
Bastien, I'd fulfill your request on the lines of the following
WIP patch, the intent is to make the plugin compile unconditionally
still mentioning the soft dependency on 2.6.39-rc1.
I could have set HAVE_HIDIOCxFEATURE in acinclude.m4 and checked for
that in sixaxis.c in place of the explicit ifdefs, what is the common
practice about that?
I still have to take care of the runtime check when running on older
kernels.
Regards,
Antonio
diff --git a/acinclude.m4 b/acinclude.m4
index 901bb4d..e3e0fdd 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -167,12 +167,12 @@ AC_DEFUN([AC_PATH_SIXAXIS], [
)],[
ac_cv_have_HIDIOCxFEATURE=yes
],[
- ac_cv_have_HIDIOCxFEATURE="no, get linux-libc-dev >= 2.6.39-rc1"
+ ac_cv_have_HIDIOCxFEATURE="no, emulating linux-libc-dev >= 2.6.39-rc1"
]
)]
)
- if ( test "${udev_found}" = "yes" && test "${ac_cv_have_HIDIOCxFEATURE}" = "yes" ); then
+ if ( test "${udev_found}" = "yes" ); then
sixaxis_plugin_deps_found=yes
fi
])
diff --git a/plugins/sixaxis.c b/plugins/sixaxis.c
index 49aad25..fc12878 100644
--- a/plugins/sixaxis.c
+++ b/plugins/sixaxis.c
@@ -58,6 +58,16 @@
#include "storage.h"
#include "sdp_lib.h"
+/* Fallback definitions to compile with older headers */
+#ifndef HIDIOCGFEATURE
+#define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len)
+#endif
+
+#ifndef HIDIOCSFEATURE
+#define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len)
+#endif
+
+
#define BDADDR_STR_SIZE 18 /* strlen("00:00:00:00:00:00") + 1 */
/* Vendor and product ID for the Sixaxis PS3 controller */
--
Antonio Ospite
http://ao2.it
PGP public key ID: 0x4553B001
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?