update to 5 version

This commit is contained in:
Alex Burmashev 2014-06-16 11:23:03 +04:00
parent ea51733c47
commit 20a03fb97e
17 changed files with 1158 additions and 1070 deletions

View file

@ -1,2 +1,2 @@
sources:
"bluez-4.101.tar.xz": 5e6d94686b1a0492c4aed59ba16601f4903c15e8
bluez-5.18.tar.xz: 5d5121b7c4afba5b4b55c1e1db2ef5d77a362a43

View file

@ -1,554 +0,0 @@
From 64f9449656dbbb718d53a54ed8e7904e289280ec Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Fri, 30 Dec 2011 12:34:29 +0100
Subject: [PATCH] Add sixaxis cable-pairing plugin
Implement the old "sixpair" using libudev and libusb-1.0.
When a Sixaxis device is plugged in, events are filtered, and
the device is selected, poked around to set the default Bluetooth
address, and added to the database of the current default adapter.
---
Makefile.am | 9 +-
acinclude.m4 | 16 +++
configure.ac | 1 +
plugins/cable.c | 382 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/adapter.c | 19 +++
src/adapter.h | 3 +
6 files changed, 428 insertions(+), 2 deletions(-)
create mode 100644 plugins/cable.c
diff --git a/Makefile.am b/Makefile.am
index 53fcbe9..f831a72 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -238,6 +238,11 @@ builtin_sources += thermometer/main.c \
endif
+if CABLE
+builtin_modules += cable
+builtin_sources += plugins/cable.c
+endif
+
builtin_modules += hciops mgmtops
builtin_sources += plugins/hciops.c plugins/mgmtops.c
@@ -306,7 +311,7 @@ src_bluetoothd_SOURCES = $(gdbus_sources) $(builtin_sources) \
src/event.h src/event.c \
src/oob.h src/oob.c src/eir.h src/eir.c
src_bluetoothd_LDADD = lib/libbluetooth-private.la @GLIB_LIBS@ @DBUS_LIBS@ \
- -ldl -lrt
+ @CABLE_LIBS@ -ldl -lrt
src_bluetoothd_LDFLAGS = $(AM_LDFLAGS) -Wl,--export-dynamic \
-Wl,--version-script=$(srcdir)/src/bluetooth.ver
@@ -428,7 +433,7 @@ EXTRA_DIST += doc/manager-api.txt \
AM_YFLAGS = -d
-AM_CFLAGS += @DBUS_CFLAGS@ @GLIB_CFLAGS@
+AM_CFLAGS += @DBUS_CFLAGS@ @GLIB_CFLAGS@ @CABLE_CFLAGS@
INCLUDES = -I$(builddir)/lib -I$(builddir)/src -I$(srcdir)/src \
-I$(srcdir)/audio -I$(srcdir)/sbc -I$(srcdir)/gdbus \
diff --git a/acinclude.m4 b/acinclude.m4
index 6505ad3..3f59989 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -139,6 +139,12 @@ AC_DEFUN([AC_PATH_UDEV], [
AC_SUBST(UDEV_LIBS)
])
+AC_DEFUN([AC_PATH_CABLE], [
+ PKG_CHECK_MODULES(CABLE, libudev libusb-1.0, cable_found=yes, cable_found=no)
+ AC_SUBST(CABLE_CFLAGS)
+ AC_SUBST(CABLE_LIBS)
+])
+
AC_DEFUN([AC_PATH_SNDFILE], [
PKG_CHECK_MODULES(SNDFILE, sndfile, sndfile_found=yes, sndfile_found=no)
AC_SUBST(SNDFILE_CFLAGS)
@@ -176,6 +182,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
sndfile_enable=${sndfile_found}
hal_enable=no
usb_enable=${usb_found}
+ cable_enable=${cable_found}
alsa_enable=${alsa_found}
gstreamer_enable=${gstreamer_found}
audio_enable=yes
@@ -265,6 +272,10 @@ AC_DEFUN([AC_ARG_BLUEZ], [
usb_enable=${enableval}
])
+ AC_ARG_ENABLE(cable, AC_HELP_STRING([--enable-cable], [enable DeviceKit support]), [
+ cable_enable=${enableval}
+ ])
+
AC_ARG_ENABLE(tools, AC_HELP_STRING([--enable-tools], [install Bluetooth utilities]), [
tools_enable=${enableval}
])
@@ -366,6 +377,10 @@ AC_DEFUN([AC_ARG_BLUEZ], [
AC_DEFINE(HAVE_LIBUSB, 1, [Define to 1 if you have USB library.])
fi
+ if (test "${cable_enable}" = "yes" && test "${cable_found}" = "yes"); then
+ AC_DEFINE(HAVE_CABLE, 1, [Define to 1 if you have libcable.])
+ 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" ||
@@ -398,4 +413,5 @@ AC_DEFUN([AC_ARG_BLUEZ], [
AM_CONDITIONAL(DBUSOOBPLUGIN, test "${dbusoob_enable}" = "yes")
AM_CONDITIONAL(WIIMOTEPLUGIN, test "${wiimote_enable}" = "yes")
AM_CONDITIONAL(GATTMODULES, test "${gatt_enable}" = "yes")
+ AM_CONDITIONAL(CABLE, test "${cable_enable}" = "yes" && test "${cable_found}" = "yes")
])
diff --git a/configure.ac b/configure.ac
index 48b181e..45a4b15 100644
--- a/configure.ac
+++ b/configure.ac
@@ -46,6 +46,7 @@ AC_PATH_GSTREAMER
AC_PATH_USB
AC_PATH_UDEV
AC_PATH_SNDFILE
+AC_PATH_CABLE
AC_PATH_OUI
AC_PATH_READLINE
AC_PATH_CHECK
diff --git a/plugins/cable.c b/plugins/cable.c
new file mode 100644
index 0000000..fe758db
--- /dev/null
+++ b/plugins/cable.c
@@ -0,0 +1,382 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2009 Bastien Nocera <hadess@hadess.net>
+ *
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE 1
+#include <libudev.h>
+#include <dbus/dbus.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/sdp.h>
+#include <libusb.h>
+
+#include "plugin.h"
+#include "log.h"
+
+#include "adapter.h"
+#include "manager.h"
+#include "device.h"
+
+#include "storage.h"
+#include "sdp_lib.h"
+
+/* Vendor and product ID for the Sixaxis PS3 controller */
+#define VENDOR 0x054c
+#define PRODUCT 0x0268
+#define SIXAXIS_PNP_RECORD "3601920900000A000100000900013503191124090004350D35061901000900113503190011090006350909656E09006A0901000900093508350619112409010009000D350F350D350619010009001335031900110901002513576972656C65737320436F6E74726F6C6C65720901012513576972656C65737320436F6E74726F6C6C6572090102251B536F6E7920436F6D707574657220456E7465727461696E6D656E740902000901000902010901000902020800090203082109020428010902052801090206359A35980822259405010904A101A102850175089501150026FF00810375019513150025013500450105091901291381027501950D0600FF8103150026FF0005010901A10075089504350046FF0009300931093209358102C0050175089527090181027508953009019102750895300901B102C0A1028502750895300901B102C0A10285EE750895300901B102C0A10285EF750895300901B102C0C0090207350835060904090901000902082800090209280109020A280109020B09010009020C093E8009020D280009020E2800"
+#define HID_UUID "00001124-0000-1000-8000-00805f9b34fb"
+
+static struct btd_device *create_cable_association(DBusConnection *conn,
+ struct btd_adapter *adapter,
+ const char *name,
+ const char *address,
+ guint32 vendor_id,
+ guint32 product_id,
+ const char *pnp_record)
+{
+ sdp_record_t *rec;
+ struct btd_device *device;
+ bdaddr_t src, dst;
+ char srcaddr[18];
+
+ device = adapter_find_device(adapter, address);
+ if (device == NULL) {
+ device = device_create(conn, adapter, address, BDADDR_BREDR);
+ if (device != NULL)
+ adapter_create_device_for_device(conn, adapter, device);
+ }
+ 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);
+
+ return device;
+}
+
+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) {
+ DBG("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]);
+
+ DBG("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) {
+ DBG("Setting the master Bluetooth address failed");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+static void handle_usb_device(struct btd_adapter *adapter,
+ libusb_device *dev,
+ struct libusb_config_descriptor *cfg,
+ int itfnum,
+ const struct libusb_interface_descriptor *alt)
+{
+ DBusConnection *conn;
+ libusb_device_handle *devh;
+ char *device_bdaddr;
+ char adapter_bdaddr[18];
+ struct btd_device *device;
+ bdaddr_t dst;
+
+ device_bdaddr = NULL;
+ conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+ if (conn == NULL) {
+ DBG("Failed to get on the bus");
+ return;
+ }
+
+ if (libusb_open(dev, &devh) < 0) {
+ DBG("Can't open device");
+ goto bail;
+ }
+ libusb_detach_kernel_driver(devh, itfnum);
+
+ if (libusb_claim_interface(devh, itfnum) < 0) {
+ DBG("Can't claim interface %d", itfnum);
+ goto bail;
+ }
+
+ device_bdaddr = get_bdaddr(devh, itfnum);
+ if (device_bdaddr == NULL) {
+ DBG("Failed to get the Bluetooth address from the device");
+ goto bail;
+ }
+
+ device = create_cable_association(conn,
+ adapter,
+ "PLAYSTATION(R)3 Controller",
+ device_bdaddr,
+ VENDOR, PRODUCT, SIXAXIS_PNP_RECORD);
+ btd_device_add_uuid(device, HID_UUID);
+
+ adapter_get_address(adapter, &dst);
+ ba2str(&dst, adapter_bdaddr);
+ DBG("Adapter bdaddr %s", adapter_bdaddr);
+
+ if (set_master_bdaddr(devh, itfnum, adapter_bdaddr) == FALSE) {
+ DBG("Failed to set the master Bluetooth address");
+ goto bail;
+ }
+
+bail:
+ dbus_connection_unref(conn);
+ g_free(device_bdaddr);
+ libusb_release_interface(devh, itfnum);
+ /* We ignore errors from the reattach, as there's nothing we
+ * can do about it */
+ libusb_attach_kernel_driver(devh, itfnum);
+ if (devh != NULL)
+ libusb_close(devh);
+}
+
+static void handle_device_plug(struct udev_device *udevice)
+{
+ struct btd_adapter *adapter;
+ guint i;
+
+ libusb_device **list, *usbdev;
+ ssize_t num_devices;
+ struct libusb_device_descriptor desc;
+ guint8 j;
+
+ if (g_strcmp0(udev_device_get_property_value(udevice, "ID_SERIAL"),
+ "Sony_PLAYSTATION_R_3_Controller") != 0)
+ return;
+ /* Don't look at events with an associated driver */
+ if (udev_device_get_property_value(udevice, "ID_USB_DRIVER") != NULL)
+ return;
+
+ DBG("Found Sixaxis device");
+
+ /* Look for the default adapter */
+ adapter = manager_get_default_adapter();
+ if (adapter == NULL)
+ return;
+
+ /* Look for the USB device */
+ libusb_init(NULL);
+
+ num_devices = libusb_get_device_list(NULL, &list);
+ if (num_devices < 0) {
+ DBG("libusb_get_device_list failed");
+ return;
+ }
+
+ usbdev = NULL;
+ for (i = 0; i < num_devices; i++) {
+ char *path;
+
+ path = g_strdup_printf("%s/%03d/%03d", "/dev/bus/usb",
+ libusb_get_bus_number(list[i]),
+ libusb_get_device_address(list[i]));
+ if (g_strcmp0(path, udev_device_get_devnode(udevice)) == 0) {
+ g_free(path);
+ usbdev = libusb_ref_device(list[i]);
+ break;
+ }
+ g_free(path);
+ }
+
+ libusb_free_device_list(list, TRUE);
+ if (usbdev == NULL) {
+ DBG("Found a Sixaxis, but couldn't find it via libusb");
+ goto out;
+ }
+
+ if (libusb_get_device_descriptor(usbdev, &desc) < 0) {
+ DBG("libusb_get_device_descriptor() failed");
+ goto out;
+ }
+
+ /* Look for the interface number that interests us */
+ for (j = 0; j < desc.bNumConfigurations; j++) {
+ struct libusb_config_descriptor *config;
+ guint8 k;
+
+ if (libusb_get_config_descriptor(usbdev, j, &config) < 0) {
+ DBG("Failed to get config descriptor %d", j);
+ continue;
+ }
+
+ 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_usb_device(adapter, usbdev, config, l, &alt);
+ }
+ }
+ }
+ }
+
+out:
+ if (usbdev != NULL)
+ libusb_unref_device(usbdev);
+ libusb_exit(NULL);
+}
+
+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)
+ goto out;
+
+ g_timeout_add_seconds(1, (GSourceFunc) device_event_idle, udevice);
+
+out:
+ return TRUE;
+}
+
+
+static int cable_init(void)
+{
+ GIOChannel *channel;
+
+ DBG("Setup 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 usb device */
+ udev_monitor_filter_add_match_subsystem_devtype(monitor,
+ "usb", 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 cable_exit(void)
+{
+ DBG("Cleanup 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(cable, VERSION,
+ BLUETOOTH_PLUGIN_PRIORITY_DEFAULT, cable_init, cable_exit)
diff --git a/src/adapter.c b/src/adapter.c
index 6e04faf..0488891 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -952,6 +952,25 @@ static struct btd_device *adapter_create_device(DBusConnection *conn,
return device;
}
+void adapter_create_device_for_device(DBusConnection *conn,
+ struct btd_adapter *adapter,
+ struct btd_device *device)
+{
+ const char *path;
+
+ device_set_temporary(device, TRUE);
+
+ adapter->devices = g_slist_append(adapter->devices, device);
+
+ path = device_get_path(device);
+ g_dbus_emit_signal(conn, adapter->path,
+ ADAPTER_INTERFACE, "DeviceCreated",
+ DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID);
+
+ adapter_update_devices(adapter);
+}
+
void adapter_remove_device(DBusConnection *conn, struct btd_adapter *adapter,
struct btd_device *device,
gboolean remove_storage)
diff --git a/src/adapter.h b/src/adapter.h
index b7ea62b..ac0aa2e 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -114,6 +114,9 @@ void adapter_update_found_devices(struct btd_adapter *adapter,
uint8_t *data, uint8_t data_len);
void adapter_emit_device_found(struct btd_adapter *adapter,
struct remote_dev_info *dev);
+void adapter_create_device_for_device(DBusConnection *conn,
+ struct btd_adapter *adapter,
+ struct btd_device *device);
void adapter_mode_changed(struct btd_adapter *adapter, uint8_t scan_mode);
int adapter_set_name(struct btd_adapter *adapter, const char *name);
void adapter_name_changed(struct btd_adapter *adapter, const char *name);
--
1.7.10.2

View file

@ -0,0 +1,58 @@
From 3027cb7141fb65cf3eeda69c688db8c4045e2d3f Mon Sep 17 00:00:00 2001
From: Giovanni Campagna <gcampagna-cNUdlRotFMnNLxjTenLetw@public.gmane.org>
Date: Sat, 12 Oct 2013 17:45:25 +0200
Subject: [PATCH] Allow using obexd without systemd in the user session
Not all sessions run systemd --user (actually, the majority
doesn't), so the dbus daemon must be able to spawn obexd
directly, and to do so it needs the full path of the daemon.
---
Makefile.obexd | 4 ++--
obexd/src/org.bluez.obex.service | 4 ----
obexd/src/org.bluez.obex.service.in | 4 ++++
3 files changed, 6 insertions(+), 6 deletions(-)
delete mode 100644 obexd/src/org.bluez.obex.service
create mode 100644 obexd/src/org.bluez.obex.service.in
diff --git a/Makefile.obexd b/Makefile.obexd
index 3760867..142e7c3 100644
--- a/Makefile.obexd
+++ b/Makefile.obexd
@@ -2,12 +2,12 @@
if SYSTEMD
systemduserunitdir = @SYSTEMD_USERUNITDIR@
systemduserunit_DATA = obexd/src/obex.service
+endif
dbussessionbusdir = @DBUS_SESSIONBUSDIR@
dbussessionbus_DATA = obexd/src/org.bluez.obex.service
-endif
-EXTRA_DIST += obexd/src/obex.service.in obexd/src/org.bluez.obex.service
+EXTRA_DIST += obexd/src/obex.service.in obexd/src/org.bluez.obex.service.in
obex_plugindir = $(libdir)/obex/plugins
diff --git a/obexd/src/org.bluez.obex.service b/obexd/src/org.bluez.obex.service
deleted file mode 100644
index a538088..0000000
--- a/obexd/src/org.bluez.obex.service
+++ /dev/null
@@ -1,4 +0,0 @@
-[D-BUS Service]
-Name=org.bluez.obex
-Exec=/bin/false
-SystemdService=dbus-org.bluez.obex.service
diff --git a/obexd/src/org.bluez.obex.service.in b/obexd/src/org.bluez.obex.service.in
new file mode 100644
index 0000000..9c815f2
--- /dev/null
+++ b/obexd/src/org.bluez.obex.service.in
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=org.bluez.obex
+Exec=@libexecdir@/obexd
+SystemdService=dbus-org.bluez.obex.service
--
1.8.3.1

View file

@ -1,37 +0,0 @@
From c70bf65af6e301f18063491b22112300c0fb9b89 Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Sun, 17 Jun 2012 01:25:46 +0200
Subject: [PATCH 1/3] input: Add helper function to request disconnect
---
input/device.c | 7 +++++++
input/device.h | 1 +
2 files changed, 8 insertions(+)
diff --git a/input/device.c b/input/device.c
index 0e3f4a9..8fdd4e0 100644
--- a/input/device.c
+++ b/input/device.c
@@ -1306,3 +1306,10 @@ int input_device_close_channels(const bdaddr_t *src, const bdaddr_t *dst)
return 0;
}
+
+void input_device_request_disconnect(struct fake_input *fake)
+{
+ if (fake == NULL || fake->idev == NULL)
+ return;
+ device_request_disconnect(fake->idev->device, NULL);
+}
diff --git a/input/device.h b/input/device.h
index 509a353..ff52967 100644
--- a/input/device.h
+++ b/input/device.h
@@ -49,3 +49,4 @@ int input_device_unregister(const char *path, const char *uuid);
int input_device_set_channel(const bdaddr_t *src, const bdaddr_t *dst, int psm,
GIOChannel *io);
int input_device_close_channels(const bdaddr_t *src, const bdaddr_t *dst);
+void input_device_request_disconnect(struct fake_input *fake);
--
1.7.10

View file

@ -0,0 +1,38 @@
From f7861d27fbcbc519f57d8496aa9486f487908821 Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Sat, 9 Nov 2013 18:13:43 +0100
Subject: [PATCH 1/5] obex: Use GLib helper function to manipulate paths
Instead of trying to do it by hand. This also makes sure that
relative paths aren't used by the agent.
---
obexd/src/manager.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/obexd/src/manager.c b/obexd/src/manager.c
index cec8a39..f18896e 100644
--- a/obexd/src/manager.c
+++ b/obexd/src/manager.c
@@ -651,14 +651,14 @@ static void agent_reply(DBusPendingCall *call, void *user_data)
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID)) {
/* Splits folder and name */
- const char *slash = strrchr(name, '/');
+ gboolean is_relative = !g_path_is_absolute(name);
DBG("Agent replied with %s", name);
- if (!slash) {
- agent->new_name = g_strdup(name);
+ if (is_relative) {
+ agent->new_name = g_path_get_basename(name);
agent->new_folder = NULL;
} else {
- agent->new_name = g_strdup(slash + 1);
- agent->new_folder = g_strndup(name, slash - name);
+ agent->new_name = g_path_get_basename(name);
+ agent->new_folder = g_path_get_dirname(name);
}
}
--
1.8.4.2

View file

@ -0,0 +1,29 @@
From aa73bf5039dfd2cf0a52dd6fd22501d955cc1a00 Mon Sep 17 00:00:00 2001
From: Tommy <mesilliac@gmail.com>
Date: Thu, 10 Jan 2013 09:18:43 +0100
Subject: [PATCH] work around Logitech diNovo Edge keyboard firmware issue
https://bugs.launchpad.net/ubuntu/+source/bluez/+bug/269851
---
tools/hid2hci.rules | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/tools/hid2hci.rules b/tools/hid2hci.rules
index db6bb03..7db4572 100644
--- a/tools/hid2hci.rules
+++ b/tools/hid2hci.rules
@@ -11,7 +11,10 @@ ATTR{bInterfaceClass}=="03", ATTR{bInterfaceSubClass}=="01", ATTR{bInterfaceProt
RUN+="hid2hci --method=dell --devpath=%p", ENV{HID2HCI_SWITCH}="1"
# Logitech devices
-KERNEL=="hiddev*", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c70[345abce]|c71[34bc]", \
+KERNEL=="hiddev*", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c70[345abce]|c71[3bc]", \
+ RUN+="hid2hci --method=logitech-hid --devpath=%p"
+# Logitech, Inc. diNovo Edge Keyboard
+KERNEL=="hidraw*", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c714", \
RUN+="hid2hci --method=logitech-hid --devpath=%p"
ENV{DEVTYPE}!="usb_device", GOTO="hid2hci_end"
--
1.8.0.1

View file

@ -0,0 +1,47 @@
From c16ae7041c7511d8d1ed8441f696716fa6a9117e Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Tue, 19 Nov 2013 14:11:39 +0100
Subject: [PATCH 2/5] autopair: Don't handle the iCade
We can't easily enter digits other than 1 through 4 (inclusive)
so leave it up to the agent to figure out a good passcode
for the iCade.
Note that we can not use the VID/PID of the device, as it is not
yet known at that point.
---
plugins/autopair.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/plugins/autopair.c b/plugins/autopair.c
index 8c98c12..5d2f6f7 100644
--- a/plugins/autopair.c
+++ b/plugins/autopair.c
@@ -57,13 +57,23 @@ static ssize_t autopair_pincb(struct btd_adapter *adapter,
{
char addr[18];
char pinstr[7];
+ char name[25];
uint32_t class;
ba2str(device_get_address(device), addr);
class = btd_device_get_class(device);
- DBG("device %s 0x%x", addr, class);
+ device_get_name(device, name, sizeof(name));
+ name[sizeof(name) - 1] = 0;
+
+ DBG("device %s (%s) 0x%x", addr, name, class);
+
+ g_message ("vendor 0x%X product: 0x%X", btd_device_get_vendor (device), btd_device_get_product (device));
+
+ /* The iCade shouldn't use random PINs like normal keyboards */
+ if (name != NULL && strstr(name, "iCade") != NULL)
+ return 0;
/* This is a class-based pincode guesser. Ignore devices with an
* unknown class.
--
1.8.4.2

View file

@ -1,118 +0,0 @@
From cca11542bcd4d1748c850806c1599ed1b76ea19a Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Sun, 17 Jun 2012 01:26:18 +0200
Subject: [PATCH 2/3] fakehid: Disconnect from PS3 remote after 10 mins
After 10 minutes, disconnect the PS3 BD Remote to avoid draining its
battery. This is consistent with its behaviour on the PS3.
Original patch by Ruslan N. Marchenko <rufferson@gmail.com>
---
input/device.h | 1 +
input/fakehid.c | 36 ++++++++++++++++++++++++++++++++++++
2 files changed, 37 insertions(+)
diff --git a/input/device.h b/input/device.h
index ff52967..d8baa2c 100644
--- a/input/device.h
+++ b/input/device.h
@@ -33,6 +33,7 @@ struct fake_input {
int uinput; /* uinput socket */
int rfcomm; /* RFCOMM socket */
uint8_t ch; /* RFCOMM channel number */
+ guint timeout_id; /* Disconnect timeout ID */
gboolean (*connect) (struct input_conn *iconn, GError **err);
int (*disconnect) (struct input_conn *iconn);
void *priv;
diff --git a/input/fakehid.c b/input/fakehid.c
index 3181538..a125356 100644
--- a/input/fakehid.c
+++ b/input/fakehid.c
@@ -44,6 +44,9 @@
#include "fakehid.h"
#include "uinput.h"
+/* Timeout to get the PS3 remote disconnected, in seconds */
+#define PS3_REMOTE_TIMEOUT 10 * 60
+
enum ps3remote_special_keys {
PS3R_BIT_PS = 0,
PS3R_BIT_ENTER = 3,
@@ -141,6 +144,20 @@ static unsigned int ps3remote_keymap[] = {
[0xff] = KEY_MAX,
};
+static gboolean ps3_remote_timeout_cb(gpointer user_data);
+
+static void ps3remote_set_timeout(struct fake_input *fake, gboolean enable)
+{
+ if (enable) {
+ fake->timeout_id = g_timeout_add_seconds(PS3_REMOTE_TIMEOUT, ps3_remote_timeout_cb, fake);
+ } else {
+ if (fake->timeout_id > 0) {
+ g_source_remove(fake->timeout_id);
+ fake->timeout_id = 0;
+ }
+ }
+}
+
static int ps3remote_decode(char *buff, int size, unsigned int *value)
{
static unsigned int lastkey = 0;
@@ -203,6 +220,16 @@ error:
return -1;
}
+static gboolean
+ps3_remote_timeout_cb(gpointer user_data)
+{
+ struct fake_input *fake = (struct fake_input *) user_data;
+ input_device_request_disconnect(fake);
+ DBG("Disconnected PS3 BD Remote after timeout");
+ fake->timeout_id = 0;
+ return FALSE;
+}
+
static gboolean ps3remote_event(GIOChannel *chan, GIOCondition cond,
gpointer data)
{
@@ -221,6 +248,9 @@ static gboolean ps3remote_event(GIOChannel *chan, GIOCondition cond,
goto failed;
}
+ /* Remove the old timeout */
+ ps3remote_set_timeout(fake, FALSE);
+
fd = g_io_channel_unix_get_fd(chan);
memset(buff, 0, sizeof(buff));
@@ -256,6 +286,8 @@ static gboolean ps3remote_event(GIOChannel *chan, GIOCondition cond,
goto failed;
}
+ ps3remote_set_timeout(fake, TRUE);
+
return TRUE;
failed:
@@ -318,6 +350,8 @@ static int ps3remote_setup_uinput(struct fake_input *fake,
goto err;
}
+ ps3remote_set_timeout(fake, TRUE);
+
return 0;
err:
@@ -378,6 +412,8 @@ struct fake_input *fake_hid_connadd(struct fake_input *fake,
for (l = fake_hid->devices; l != NULL; l = l->next) {
old = l->data;
if (old->idev == fake->idev) {
+ if (fake->timeout_id > 0)
+ g_source_remove(fake->timeout_id);
g_free(fake);
fake = old;
fake_hid->connect(fake, NULL);
--
1.7.10

View file

@ -1,107 +0,0 @@
From 4319a0601457772591e520e407019b606780d035 Mon Sep 17 00:00:00 2001
From: Alexander Khryukin <alexander@mezon.ru>
Date: Mon, 25 Jun 2012 13:16:23 -0400
Subject: [PATCH 2/2] test
---
Makefile.am | 21 ++++++++++++++++++---
configure.ac | 7 +++++++
scripts/bluetooth.service.in | 14 ++++++++++++++
scripts/org.bluez.service | 5 +++++
4 files changed, 44 insertions(+), 3 deletions(-)
create mode 100644 scripts/bluetooth.service.in
create mode 100644 scripts/org.bluez.service
diff --git a/Makefile.am b/Makefile.am
index 1c214c6..024aa36 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -414,9 +414,24 @@ endif
rules_DATA = $(foreach file,$(udev_files), scripts/97-$(notdir $(file)))
endif
+if HAVE_SYSTEMD
+systemdsystemunit_DATA = \
+ scripts/bluetooth.service
+
+scripts/bluetooth.service: scripts/bluetooth.service.in
+ @$(SED) -e "s|\@sbindir\@|$(sbindir)|" $< >$@
+
+dbussystemservicesdir = $(datadir)/dbus-1/system-services
+
+dbussystemservices_DATA = \
+ scripts/org.bluez.service
+endif
+
+
CLEANFILES += $(rules_DATA)
-EXTRA_DIST += scripts/bluetooth-hid2hci.rules scripts/bluetooth-serial.rules
+EXTRA_DIST += scripts/bluetooth-hid2hci.rules scripts/bluetooth-serial.rules \
+ scripts/bluetooth.service.in scripts/org.bluez.service
EXTRA_DIST += doc/manager-api.txt \
doc/adapter-api.txt doc/device-api.txt \
@@ -460,9 +475,9 @@ pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = bluez.pc
-DISTCHECK_CONFIGURE_FLAGS = --disable-datafiles
+DISTCHECK_CONFIGURE_FLAGS = --disable-datafiles --with-systemdsystemunitdir=
-DISTCLEANFILES = $(pkgconfig_DATA)
+DISTCLEANFILES = $(pkgconfig_DATA) scripts/bluetooth.service
MAINTAINERCLEANFILES = Makefile.in \
aclocal.m4 configure config.h.in config.sub config.guess \
diff --git a/configure.ac b/configure.ac
index f2db920..6f6b4c0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -60,5 +60,12 @@ if (test -n "${path_systemdunit}"); then
AC_SUBST(SYSTEMD_UNITDIR)
fi
AM_CONDITIONAL(SYSTEMD, test -n "${path_systemdunit}")
+# systemd
+AC_ARG_WITH([systemdsystemunitdir],
+ AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
+ [],
+ [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)])
+AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
+AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir"])
AC_OUTPUT(Makefile doc/version.xml src/bluetoothd.8 src/bluetooth.service bluez.pc)
diff --git a/scripts/bluetooth.service.in b/scripts/bluetooth.service.in
new file mode 100644
index 0000000..5ec0e2a
--- /dev/null
+++ b/scripts/bluetooth.service.in
@@ -0,0 +1,14 @@
+[Unit]
+Description=Bluetooth Manager
+After=syslog.target
+
+[Service]
+Type=dbus
+BusName=org.bluez
+ExecStart=@sbindir@/bluetoothd -n
+StandardOutput=syslog
+
+[Install]
+WantedBy=bluetooth.target
+Alias=dbus-org.bluez.service
+
diff --git a/scripts/org.bluez.service b/scripts/org.bluez.service
new file mode 100644
index 0000000..dd7ae8f
--- /dev/null
+++ b/scripts/org.bluez.service
@@ -0,0 +1,5 @@
+[D-BUS Service]
+Name=org.bluez
+Exec=/bin/false
+User=root
+SystemdService=dbus-org.bluez.service
--
1.7.9.2

View file

@ -1,26 +0,0 @@
From a354165e58f937ee12c16ab48ce334b664c8f163 Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Sun, 17 Jun 2012 01:29:01 +0200
Subject: [PATCH 3/3] fakehid: Use the same constant as declared
ps3remote_keymap[] uses 0xff as the max value, so should we.
---
input/fakehid.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/input/fakehid.c b/input/fakehid.c
index a125356..a758413 100644
--- a/input/fakehid.c
+++ b/input/fakehid.c
@@ -335,7 +335,7 @@ static int ps3remote_setup_uinput(struct fake_input *fake,
}
/* enabling keys */
- for (i = 0; i < 256; i++)
+ for (i = 0; i < 0xff; i++)
if (ps3remote_keymap[i] != KEY_RESERVED)
if (ioctl(fake->uinput, UI_SET_KEYBIT,
ps3remote_keymap[i]) < 0) {
--
1.7.10

View file

@ -0,0 +1,25 @@
From 67e5477687a2753d3f7b300bcfdc74464d8ad41f Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Mon, 9 Dec 2013 18:04:56 +0100
Subject: [PATCH 4/5] agent: Assert possible infinite loop
---
src/agent.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/agent.c b/src/agent.c
index bcba969..b292881 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -203,6 +203,8 @@ void agent_unref(struct agent *agent)
if (agent->ref > 0)
return;
+ g_assert (agent->ref == 0);
+
if (agent->request) {
DBusError err;
agent_pincode_cb pincode_cb;
--
1.8.4.2

View file

@ -1,29 +0,0 @@
From 811b28ca458c3e886a836c919fefa59eb0c4e53e Mon Sep 17 00:00:00 2001
From: Colin Guthrie <colin@mageia.org>
Date: Mon, 5 Mar 2012 23:54:21 +0000
Subject: [PATCH 503/503] systemd: Fix unit to correct path to bluetoothd.
---
src/bluetooth.service.in | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/bluetooth.service.in b/src/bluetooth.service.in
index 2a576a3..957aa35 100644
--- a/src/bluetooth.service.in
+++ b/src/bluetooth.service.in
@@ -1,10 +1,10 @@
[Unit]
-Description=Bluetooth service
+Description=Bluetooth Manager
[Service]
Type=dbus
BusName=org.bluez
-ExecStart=@prefix@/sbin/bluetoothd -n
+ExecStart=@sbindir@/bluetoothd -n
[Install]
WantedBy=bluetooth.target
--
1.7.11

View file

@ -1,11 +0,0 @@
--- bluez-4.101/configure.ac.bero 2013-01-15 18:49:07.755043126 +0100
+++ bluez-4.101/configure.ac 2013-01-15 18:49:15.743947380 +0100
@@ -2,7 +2,7 @@ AC_PREREQ(2.60)
AC_INIT(bluez, 4.101)
AM_INIT_AUTOMAKE([foreign subdir-objects color-tests])
-AM_CONFIG_HEADER(config.h)
+AC_CONFIG_HEADERS([config.h])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])

View file

@ -1,23 +0,0 @@
--- bluez-4.101/lib/bluetooth.h.c++11~ 2012-06-28 23:59:45.676069338 +0200
+++ bluez-4.101/lib/bluetooth.h 2012-06-28 23:59:50.973003117 +0200
@@ -140,16 +140,16 @@ enum {
#define bt_get_unaligned(ptr) \
({ \
struct __attribute__((packed)) { \
- typeof(*(ptr)) __v; \
- } *__p = (typeof(__p)) (ptr); \
+ __typeof__(*(ptr)) __v; \
+ } *__p = (__typeof__(__p)) (ptr); \
__p->__v; \
})
#define bt_put_unaligned(val, ptr) \
do { \
struct __attribute__((packed)) { \
- typeof(*(ptr)) __v; \
- } *__p = (typeof(__p)) (ptr); \
+ __typeof__(*(ptr)) __v; \
+ } *__p = (__typeof__(__p)) (ptr); \
__p->__v = (val); \
} while(0)

View file

@ -1,12 +0,0 @@
diff --git a/scripts/bluetooth-serial.rules b/scripts/bluetooth-serial.rules
index 072335f..f6284ff 100644
--- a/scripts/bluetooth-serial.rules
+++ b/scripts/bluetooth-serial.rules
@@ -33,3 +33,7 @@ SUBSYSTEM=="tty", SUBSYSTEMS=="pcmcia", ATTRS{prod_id1}=="PCMCIA", ATTRS{prod_id
# CC&C BT0100M
SUBSYSTEM=="tty", SUBSYSTEMS=="pcmcia", ATTRS{prod_id1}=="Bluetooth BT0100M", ENV{HCIOPTS}="bcsp 115200", RUN+="bluetooth_serial"
+
+# SocketMobile CF Connection Kit
+SUBSYSTEM=="tty", SUBSYSTEMS=="pcmcia", ATTRS{prod_id1}=="Socket", ATTRS{prod_id2}=="CF+ Personal Network Card Rev 2.5", ENV{HCIOPTS}="socket", RUN+="bluetooth_serial"
+

View file

@ -2,12 +2,10 @@
%define libname %mklibname %{name} %{major}
%define devname %mklibname -d %{name}
%bcond_without systemd
Name: bluez
Summary: Official Linux Bluetooth protocol stack
Version: 4.101
Release: 9
Version: 5.18
Release: 4
License: GPLv2+
Group: Communications
URL: http://www.bluez.org/
@ -18,99 +16,88 @@ Source8: hidd.conf
Source9: rfcomm.conf
Source10: bluez-uinput.modules
# http://thread.gmane.org/gmane.linux.bluez.kernel/8645
Patch0: 0002-systemd-unitdir-enable.patch
Patch1: bluez-4.101-automake-1.13.patch
Patch4: bluez-socket-mobile-cf-connection-kit.patch
# http://thread.gmane.org/gmane.linux.bluez.kernel/2396
Patch5: 0001-Add-sixaxis-cable-pairing-plugin.patch
# PS3 BD Remote patches
Patch6: 0001-input-Add-helper-function-to-request-disconnect.patch
Patch7: 0002-fakehid-Disconnect-from-PS3-remote-after-10-mins.patch
Patch8: 0003-fakehid-Use-the-same-constant-as-declared.patch
Patch9: bluez-4.101-fix-c++11-compatibility.patch
## https://bugzilla.redhat.com/show_bug.cgi?id=874015#c0
Patch1: playstation-peripheral-pugin-v5.x.patch
## Ubuntu patches
Patch2: 0001-work-around-Logitech-diNovo-Edge-keyboard-firmware-i.patch
# Non-upstream
Patch3: 0001-Allow-using-obexd-without-systemd-in-the-user-sessio.patch
Patch0503: 0503-systemd-Fix-unit-to-correct-path-to-bluetoothd.patch
Patch4: 0001-obex-Use-GLib-helper-function-to-manipulate-paths.patch
Patch5: 0002-autopair-Don-t-handle-the-iCade.patch
Patch7: 0004-agent-Assert-possible-infinite-loop.patch
Requires(pre): rpm-helper
BuildRequires: flex
BuildRequires: bison
BuildRequires: systemd
BuildRequires: readline-devel
BuildRequires: expat-devel
BuildRequires: pkgconfig(alsa)
BuildRequires: cups-devel
BuildRequires: pkgconfig(dbus-1)
BuildRequires: pkgconfig(gstreamer-plugins-base-0.10)
BuildRequires: pkgconfig(gstreamer-0.10)
BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(libcap-ng)
BuildRequires: pkgconfig(libusb)
BuildRequires: pkgconfig(libusb-1.0)
BuildRequires: pkgconfig(libical)
BuildRequires: pkgconfig(udev) >= 186
BuildRequires: pkgconfig(libical)
BuildRequires: pkgconfig(systemd)
Requires: bluez-pin
Suggests: obex-data-server
Suggests: bluez-firmware
Obsoletes: bluez-alsa < 5.0
Obsoletes: bluez-gstreamer < 5.0
%description
These are the official Bluetooth communication libraries for Linux.
%post
update-alternatives --install /bin/bluepin bluepin /usr/bin/bluepin 5
#migrate old configuration
if [ "$1" = "2" -a -d %{_var}/lib/lib/bluetooth ]; then
mv -f %{_var}/lib/lib/bluetooth/* %{_var}/lib/bluetooth/ > /dev/null 2>&1 || exit 0
rmdir %{_var}/lib/lib/bluetooth/ > /dev/null 2>&1 || exit 0
rmdir %{_var}/lib/lib/ > /dev/null 2>&1 || exit 0
fi
if [ $1 -eq 1 ]; then
/bin/systemctl enable bluetooth.service >/dev/null 2>&1 || :
fi
%_post_service bluetooth
%postun
if [ "$1" = "0" ]; then
update-alternatives --remove bluepin /usr/bin/bluepin
fi
/bin/systemctl daemon-reload >/dev/null 2>&1 || :
if [ $1 -ge 1 ] ; then
/bin/systemctl try-restart bluetooth.service >/dev/null 2>&1 || :
fi
%triggerun -- bluez < 4.94-4
/bin/systemctl --no-reload enable bluetooth.service >/dev/null 2>&1 || :
%_preun_service bluetooth
%files
%{_bindir}/ciptool
%{_bindir}/dfutool
%{_bindir}/gatttool
%{_bindir}/hcitool
%{_bindir}/hidd
%{_bindir}/l2ping
%{_bindir}/rfcomm
%{_bindir}/sdptool
### compat
%{_bindir}/dund
%{_bindir}/pand
###
%{_sbindir}/bccmd
%{_sbindir}/hciattach
%{_sbindir}/hciconfig
%{_sbindir}/bluetoothd
/bin/hidd
/sbin/bluetoothd
%if %{with systemd}
%{_unitdir}/*.service
%endif
%{_mandir}/man?/*
%{_bindir}/bccmd
%{_bindir}/bluetoothctl
%{_bindir}/btmon
%{_bindir}/hciattach
%{_bindir}/hciconfig
%{_bindir}/hcidump
%{_bindir}/bluemoon
%{_libexecdir}/bluetooth/bluetoothd
%{_libexecdir}/bluetooth/obexd
%{_unitdir}/bluetooth.service
%{_unitdir}/dbus-org.bluez.service
%{_userunitdir}/obex.service
%{_mandir}/man1/ciptool.1.*
%{_mandir}/man1/hcitool.1.*
%{_mandir}/man1/rfcomm.1.*
%{_mandir}/man1/sdptool.1.*
%{_mandir}/man1/bccmd.1.*
%{_mandir}/man1/hciattach.1.*
%{_mandir}/man1/hciconfig.1.*
%{_mandir}/man1/hcidump.1.*
%{_mandir}/man1/l2ping.1.*
%{_mandir}/man1/rctest.1.*
%{_mandir}/man8/*
%config(noreplace) %{_sysconfdir}/sysconfig/*
%config(noreplace) %{_sysconfdir}/dbus-1/system.d/*.conf
%config(noreplace) %{_sysconfdir}/bluetooth
%{_datadir}/dbus-1/system-services/org.bluez.service
/lib/udev/bluetooth_serial
/lib/udev/hid2hci
%{_sysconfdir}/udev/rules.d/97-bluetooth-serial.rules
%{_sysconfdir}/udev/rules.d/97-bluetooth-hid2hci.rules
%{_datadir}/dbus-1/services/org.bluez.obex.service
%{_localstatedir}/lib/bluetooth
%dir %{_libdir}/bluetooth
%dir %{_libdir}/bluetooth/plugins
%{_libdir}/bluetooth/plugins/sixaxis.so
%{_libdir}/bluetooth/plugins/playstation-peripheral.so
#--------------------------------------------------------------------
@ -127,31 +114,6 @@ This package contains the CUPS backend for Bluetooth printers.
#--------------------------------------------------------------------
%package gstreamer
Summary: Gstreamer support for SBC audio format
Group: Sound
%description gstreamer
This package contains gstreamer plugins for the Bluetooth SBC audio format
%files gstreamer
%{_libdir}/gstreamer-*/*.so
#--------------------------------------------------------------------
%package alsa
Summary: ALSA support for Bluetooth audio devices
Group: Sound
%description alsa
This package contains ALSA support for Bluetooth audio devices
%files alsa
%{_libdir}/alsa-lib/*.so
%{_datadir}/alsa/bluetooth.conf
#--------------------------------------------------------------------
%package -n %{libname}
Summary: Official Linux Bluetooth protocol stack
Group: System/Libraries
@ -160,7 +122,39 @@ Group: System/Libraries
These are the official Bluetooth communication libraries for Linux.
%files -n %{libname}
/%{_lib}/lib*.so.%{major}*
/%{_lib}/libbluetooth.so.%{major}*
#--------------------------------------------------------------------
%package hid2hci
Summary: Put HID proxying bluetooth HCI's into HCI mode
Group: Communications
%description hid2hci
Most allinone PC's and bluetooth keyboard / mouse sets which include a
bluetooth dongle, ship with a so called HID proxying bluetooth HCI.
The HID proxying makes the keyboard / mouse show up as regular USB HID
devices (after connecting using the connect button on the device + keyboard),
which makes them work without requiring any manual configuration.
The bluez-hid2hci package contains the hid2hci utility and udev rules to
automatically switch supported Bluetooth devices into regular HCI mode.
Install this package if you want to use the bluetooth function of the HCI
with other bluetooth devices like for example a mobile phone.
Note that after installing this package you will first need to pair your
bluetooth keyboard and mouse with the bluetooth adapter before you can use
them again. Since you cannot use your bluetooth keyboard and mouse until
they are paired, this will require the use of a regular (wired) USB keyboard
and mouse.
%files hid2hci
/lib/udev/hid2hci
%{_mandir}/man1/hid2hci.1*
/lib/udev/rules.d/97-hid2hci.rules
%post hid2hci
%{_bindir}/udevadm trigger --subsystem-match=usb
#--------------------------------------------------------------------
@ -176,10 +170,11 @@ BLUETOOTH trademarks are owned by Bluetooth SIG, Inc., U.S.A.
%files test
%{_bindir}/simple-agent
%{_bindir}/l2test
%{_bindir}/rctest
%{_bindir}/test-*
#--------------------------------------------------------------------
%package -n %{devname}
Summary: Headers for developing programs that will use %{name}
Group: Development/C++
@ -194,9 +189,8 @@ applications which will use libraries from %{name}.
%doc AUTHORS ChangeLog README
%dir %{_includedir}/bluetooth
%{_includedir}/bluetooth/*.h
/%{_lib}/*.so
%{_libdir}/*.so
%{_libdir}/pkgconfig/bluez.pc
#--------------------------------------------------------------------
%prep
@ -208,82 +202,61 @@ autoreconf -fi
%build
%configure2_5x \
--libdir=/%{_lib} \
%if !%{with systemd}
--without-systemdsystemunitdir \
%endif
--enable-cups \
--enable-dfutool \
--enable-audio \
--enable-health \
--disable-hal \
--enable-pnat \
--enable-wiimote \
--enable-sixaxis \
--enable-udev \
--enable-tools \
--enable-bccmd \
--enable-gstreamer \
--enable-hidd \
--enable-pand \
--enable-dund \
--enable-hid2hci \
--enable-pcmcia \
--with-systemdsystemunitdir=/lib/systemd/system
--enable-library \
--enable-usb \
--enable-threads \
--enable-monitor \
--enable-obex \
--enable-client \
--enable-systemd \
--with-systemdsystemunitdir=%{_unitdir} \
--with-systemduserunitdir=%{_userunitdir} \
--with-udevdir=/lib/udev \
--enable-datafiles \
--enable-experimental \
--enable-playstation-peripheral
%make
%install
%makeinstall_std rulesdir=%{_sysconfdir}/udev/rules.d udevdir=/lib/udev
mkdir -p %{buildroot}%{_libdir}
mv %{buildroot}/%{_lib}/gstreamer-0.10 %{buildroot}%{_libdir}
cat << EOF > %{buildroot}%{_sysconfdir}/bluetooth/pin
1234
EOF
mkdir -p %{buildroot}%{_sysconfdir}/bluetooth
echo "1234" > %{buildroot}%{_sysconfdir}/bluetooth/pin
chmod 600 %{buildroot}%{_sysconfdir}/bluetooth/pin
rm -f %{buildroot}%{_sysconfdir}/default/bluetooth %{buildroot}%{_sysconfdir}/init.d/bluetooth
install -m644 %{SOURCE6} -D %{buildroot}%{_sysconfdir}/sysconfig/pand
install -m644 %{SOURCE7} -D %{buildroot}%{_sysconfdir}/sysconfig/dund
install -m644 %{SOURCE8} -D %{buildroot}%{_sysconfdir}/sysconfig/hidd
install -m644 %{SOURCE9} -D %{buildroot}%{_sysconfdir}/sysconfig/rfcomm
rm -rf %{buildroot}/%{_lib}/pkgconfig
install -m644 bluez.pc -D %{buildroot}%{_libdir}/pkgconfig/bluez.pc
mkdir -p %{buildroot}/%{_lib}
mv %{buildroot}%{_libdir}/libbluetooth.so.%{major}* %{buildroot}/%{_lib}
ln -srf %{buildroot}/%{_lib}/libbluetooth.so.%{major}.*.* %{buildroot}%{_libdir}/libbluetooth.so
# Remove the cups backend from libdir, and install it in /usr/lib whatever the install
if test -d %{buildroot}/%{_lib}/cups ; then
install -D -m0755 %{buildroot}/%{_lib}/cups/backend/bluetooth %{buildroot}%{_prefix}/lib/cups/backend/bluetooth
rm -rf %{buildroot}/%{_lib}/cups
fi
%if "%{_lib}" == "lib64"
install -d %{buildroot}%{_prefix}/lib
mv %{buildroot}%{_libdir}/cups %{buildroot}%{_prefix}/lib/cups
%endif
cp test/test-* %{buildroot}%{_bindir}
cp test/simple-agent %{buildroot}%{_bindir}/simple-agent
rm -f %{buildroot}%{_bindir}/test-*.c
mkdir -p %{buildroot}/{bin,sbin}
mv %{buildroot}%{_bindir}/hidd %{buildroot}/bin
mv %{buildroot}%{_sbindir}/bluetoothd %{buildroot}/sbin
# sym link just to be safe
pushd %{buildroot}
ln -s /bin/hidd %{buildroot}%{_bindir}/hidd
ln -s /sbin/bluetoothd %{buildroot}%{_sbindir}/bluetoothd
popd
rm %{buildroot}%{_sysconfdir}/udev/rules.d/*.rules
install -p -m644 tools/hid2hci.rules -D %{buildroot}/lib/udev/rules.d/97-hid2hci.rules
#install more config files
install -m0644 audio/audio.conf %{buildroot}%{_sysconfdir}/bluetooth/
install -m0644 network/network.conf %{buildroot}%{_sysconfdir}/bluetooth/
install -m0644 input/input.conf %{buildroot}%{_sysconfdir}/bluetooth/
install -m0644 serial/serial.conf %{buildroot}%{_sysconfdir}/bluetooth/
mkdir -p %{buildroot}%{_libdir}/alsa-lib/
mv %{buildroot}/%{_lib}/alsa-lib/*.so %{buildroot}%{_libdir}/alsa-lib/
install -m0644 profiles/network/network.conf %{buildroot}%{_sysconfdir}/bluetooth/
install -m0644 src/main.conf %{buildroot}%{_sysconfdir}/bluetooth/
install -m0644 profiles/input/input.conf %{buildroot}%{_sysconfdir}/bluetooth/
install -m0644 profiles/proximity/proximity.conf %{buildroot}%{_sysconfdir}/bluetooth/
install -d -m0755 %{buildroot}%{_localstatedir}/lib/bluetooth
ln -s bluetooth.service %{buildroot}%{_unitdir}/dbus-org.bluez.service
# (akdengi) enable auto for a2pd
sed -e 's/#AutoConnect=true/AutoConnect=true/' -i %{buildroot}%{_sysconfdir}/bluetooth/audio.conf

View file

@ -0,0 +1,835 @@
--- bluez-5.18/Makefile.am.playstation~ 2014-03-25 21:53:41.000000000 +0100
+++ bluez-5.18/Makefile.am 2014-05-06 22:13:18.967174167 +0200
@@ -115,6 +115,15 @@ builtin_nodist =
include Makefile.plugins
+if PLAYSTATION_PERIPHERAL_PLUGIN
+plugin_LTLIBRARIES += plugins/playstation-peripheral.la
+plugins_playstation_peripheral_la_DEPENDENCIES = src/bluetoothd
+plugins_playstation_peripheral_la_SOURCES = plugins/playstation-peripheral.c plugins/playstation-peripheral-hid.c
+plugins_playstation_peripheral_la_LDFLAGS = -module -avoid-version -no-undefined @UDEV_LIBS@
+plugins_playstation_peripheral_la_CFLAGS = -fvisibility=hidden @DBUS_CFLAGS@ @GLIB_CFLAGS@ @UDEV_CFLAGS@
+plugins_playstation_peripheral_la_CPPFLAGS = -I$(srcdir)/src -I$(srcdir)/lib
+endif
+
if MAINTAINER_MODE
plugin_LTLIBRARIES += plugins/external-dummy.la
plugins_external_dummy_la_SOURCES = plugins/external-dummy.c
--- bluez-5.18/configure.ac.playstation~ 2014-04-12 12:13:29.000000000 +0200
+++ bluez-5.18/configure.ac 2014-05-06 22:09:30.225172158 +0200
@@ -221,6 +221,16 @@ AC_ARG_ENABLE(sixaxis, AC_HELP_STRING([-
AM_CONDITIONAL(SIXAXIS, test "${enable_sixaxis}" = "yes" &&
test "${enable_udev}" != "no")
+AC_ARG_ENABLE(playstation_peripheral, AC_HELP_STRING([--enable-playstation-peripheral],
+ [enable playstation-peripheral plugin]),
+ [enable_playstation_peripheral=${enableval}])
+
+if (test "${enble_playstation_peripheral}" != "no" && test "${enable_udev}" != "no"); then
+ AC_DEFINE(HAVE_PLAYSTATION_PERIPHERAL_PLUGIN, 1, [Define to 1 if you have playstation-peripheral plugin.])
+fi
+
+AM_CONDITIONAL(PLAYSTATION_PERIPHERAL_PLUGIN, test "${enable_playstation_peripheral}" != "no" && test "${enable_udev}" != "no")
+
if (test "${prefix}" = "NONE"); then
dnl no prefix and no localstatedir, so default to /var
if (test "$localstatedir" = '${prefix}/var'); then
--- bluez-5.18/plugins/playstation-peripheral-hid.c.playstation~ 2014-05-06 22:09:30.225172158 +0200
+++ bluez-5.18/plugins/playstation-peripheral-hid.c 2014-05-06 22:09:30.225172158 +0200
@@ -0,0 +1,263 @@
+/*
+ * playstation peripheral plugin: lowlevel hid functions
+ *
+ * Copyright (C) 2011 Antonio Ospite <ospite@studenti.unina.it>
+ *
+ *
+ * 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
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <linux/hidraw.h>
+
+#include "log.h"
+#include "playstation-peripheral-hid.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 */
+
+#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
+
+/* 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:%s() calloc failed", __FILE__, __func__);
+ return NULL;
+ }
+
+ buf[0] = report_number;
+
+ ret = ioctl(fd, HIDIOCGFEATURE(len), buf);
+ if (ret < 0) {
+ error("%s:%s() HIDIOCGFEATURE ret = %d",
+ __FILE__, __func__, ret);
+ free(buf);
+ 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:%s() HIDIOCSFEATURE failed, ret = %d",
+ __FILE__, __func__, ret);
+
+ return ret;
+}
+
+char *sixaxis_get_device_bdaddr(int fd)
+{
+ unsigned char *buf;
+ char *address;
+
+ buf = get_feature_report(fd, 0xf2, 18);
+ if (buf == NULL) {
+ error("%s:%s() cannot get feature report", __FILE__, __func__);
+ return NULL;
+ }
+
+ address = calloc(BDADDR_STR_SIZE, sizeof(*address));
+ if (address == NULL) {
+ error("%s:%s() calloc failed", __FILE__, __func__);
+ free(buf);
+ return NULL;
+ }
+
+ snprintf(address, BDADDR_STR_SIZE,
+ "%02X:%02X:%02X:%02X:%02X:%02X",
+ buf[4], buf[5], buf[6], buf[7], buf[8], buf[9]);
+
+ free(buf);
+ return address;
+}
+
+char *sixaxis_get_master_bdaddr(int fd)
+{
+ unsigned char *buf;
+ char *address;
+
+ buf = get_feature_report(fd, 0xf5, 8);
+ if (buf == NULL) {
+ error("%s:%s() cannot get feature report", __FILE__, __func__);
+ return NULL;
+ }
+
+ address = calloc(BDADDR_STR_SIZE, sizeof(*address));
+ if (address == NULL) {
+ error("%s:%s() calloc failed", __FILE__, __func__);
+ free(buf);
+ return NULL;
+ }
+
+ snprintf(address, BDADDR_STR_SIZE,
+ "%02X:%02X:%02X:%02X:%02X:%02X",
+ buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
+
+ free(buf);
+ return address;
+}
+
+int sixaxis_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:%s() Parsing the bt address failed",
+ __FILE__, __func__);
+ return -EINVAL;
+ }
+
+ report = malloc(8);
+ if (report == NULL) {
+ error("%s:%s() malloc failed", __FILE__, __func__);
+ return -ENOMEM;
+ }
+
+ 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:%s() cannot set feature report",
+ __FILE__, __func__);
+ goto out;
+ }
+
+ DBG("New Master Bluetooth address: %s", adapter_bdaddr);
+
+out:
+ free(report);
+ return ret;
+}
+
+
+/* Led setting section */
+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 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 is 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))
+ error("%s:%s() Unable to write to hidraw device",
+ __FILE__, __func__);
+
+ return ret;
+}
+
+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("%s:%s() Only 7 controllers supported for now",
+ __FILE__, __func__);
+ return -1;
+ }
+
+ return set_leds(fd, leds_status);
+}
--- bluez-5.18/plugins/playstation-peripheral-hid.h.playstation~ 2014-05-06 22:09:30.226172158 +0200
+++ bluez-5.18/plugins/playstation-peripheral-hid.h 2014-05-06 22:09:30.226172158 +0200
@@ -0,0 +1,10 @@
+#ifndef __PLAYSTATION_PERIPHERAL_HID_H
+#define __PLAYSTATION_PERIPHERAL_HID_H
+
+char *sixaxis_get_device_bdaddr(int fd);
+char *sixaxis_get_master_bdaddr(int fd);
+int sixaxis_set_master_bdaddr(int fd, char *adapter_bdaddr);
+
+int set_controller_number(int fd, unsigned int n);
+
+#endif /* __PLAYSTATION_PERIPHERAL_HID_H */
--- bluez-5.18/plugins/playstation-peripheral.c.playstation~ 2014-05-06 22:09:30.227172158 +0200
+++ bluez-5.18/plugins/playstation-peripheral.c 2014-05-06 22:09:30.227172158 +0200
@@ -0,0 +1,409 @@
+/*
+ * playstation peripheral plugin: support for Playstation peripherals
+ *
+ * Copyright (C) 2009 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2011 Antonio Ospite <ospite@studenti.unina.it>
+ *
+ *
+ * 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:
+ *
+ * - peripheral: a Playstation peripheral (Sixaxis, DS3, headset, etc.)
+ * - controller: an input peripheral
+ * - adapter: the bluetooth dongle on the host system.
+ * - adapter_bdaddr: the bdaddr of the bluetooth adapter.
+ * - device_bdaddr: the bdaddr of the Playstation peripheral.
+ * - master_bdaddr: the bdaddr of the adapter to be configured into the
+ * Playstation peripheral
+ *
+ * WHAT we need the plugin to do:
+ *
+ * - When a device is connected via USB:
+ * + Fetch the (default) adapter bdaddr (from BlueZ) and store it into
+ * the device
+ * + Fetch the device bdaddr (from the device via USB/HID) and make the
+ * device _trusted_ by the adapter (is "trusted" the correct term
+ * here? Or maybe this is more like a "static association"? Are the
+ * term "trusted" and "associated" in bluetooth context defined
+ * anywhere?)
+ *
+ * - When the device is connected via BT:
+ * + Nothing! It should work automatically.
+ *
+ * - Set LEDs when possible.
+ *
+ * WHY we need that:
+ *
+ * Playstation peripherals require/support USB cable pairing.
+ *
+ * It is required in the sense that devices will talk only to adapters
+ * they know.
+ *
+ * It is supported in the sense that this mechanism is optional on _some_
+ * devices like the PS3 Keypad.
+ *
+ * On the PS3 these cable paired devices can be used via BT without
+ * further association steps once they have been connected
+ * _at_least_once_ via USB to a certain host (with a certain BT adapter
+ * that is), we would like to have the same behavior with BlueZ.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <glib.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 "storage.h"
+#include "sdp_lib.h"
+
+#include "playstation-peripheral-hid.h"
+
+struct playstation_peripheral {
+ uint16_t vendor_id;
+ uint16_t product_id;
+ char *name;
+ char *sdp_record;
+ char *uuid;
+
+ /* device specific callbacks to get master/device bdaddr and set
+ * master bdaddr
+ */
+ char * (*get_device_bdaddr)(int);
+ char * (*get_master_bdaddr)(int);
+ int (*set_master_bdaddr) (int, char *);
+};
+
+static struct playstation_peripheral peripherals[] = {
+ {
+ .vendor_id = 0x054c,
+ .product_id = 0x0268,
+ .name = "PLAYSTATION(R)3 Controller",
+ .sdp_record = "3601920900000A000100000900013503191124090004350D35061901000900113503190011090006350909656E09006A0901000900093508350619112409010009000D350F350D350619010009001335031900110901002513576972656C65737320436F6E74726F6C6C65720901012513576972656C65737320436F6E74726F6C6C6572090102251B536F6E7920436F6D707574657220456E7465727461696E6D656E740902000901000902010901000902020800090203082109020428010902052801090206359A35980822259405010904A101A102850175089501150026FF00810375019513150025013500450105091901291381027501950D0600FF8103150026FF0005010901A10075089504350046FF0009300931093209358102C0050175089527090181027508953009019102750895300901B102C0A1028502750895300901B102C0A10285EE750895300901B102C0A10285EF750895300901B102C0C0090207350835060904090901000902082800090209280109020A280109020B09010009020C093E8009020D280009020E2800",
+ .uuid = "00001124-0000-1000-8000-00805f9b34fb",
+ .get_device_bdaddr = sixaxis_get_device_bdaddr,
+ .get_master_bdaddr = sixaxis_get_master_bdaddr,
+ .set_master_bdaddr = sixaxis_set_master_bdaddr,
+ },
+};
+
+static struct udev *ctx;
+static struct udev_monitor *monitor;
+static guint watch_id;
+
+static int create_peripheral_association(char *adapter_address,
+ char *device_address,
+ struct playstation_peripheral *peripheral)
+{
+ return btd_create_stored_device(adapter_address, device_address,
+ peripheral->name,
+ 0x0002, /* VersionIDSource = USB Implementer's Forum */
+ peripheral->vendor_id,
+ peripheral->product_id,
+ 0, /* version is hardcoded to 0 for now */
+ peripheral->uuid,
+ peripheral->sdp_record,
+ 1);
+}
+
+static int peripheral_pair(int fd, char *adapter_bdaddr,
+ struct playstation_peripheral *peripheral)
+{
+ char *device_bdaddr;
+ char *master_bdaddr;
+ int ret = 0;
+
+ master_bdaddr = peripheral->get_master_bdaddr(fd);
+ if (master_bdaddr == NULL) {
+ DBG("Failed to get the Old master Bluetooth address from the device");
+ return -EPERM;
+ }
+
+ /* Only set the master bdaddr when needed, this is how the PS3 does
+ * it, perhaps to avoid unnecessary writes to some eeprom.
+ */
+ if (g_strcmp0(master_bdaddr, adapter_bdaddr) != 0) {
+ DBG("Old master Bluetooth address was: %s", master_bdaddr);
+ ret = peripheral->set_master_bdaddr(fd, adapter_bdaddr);
+ if (ret < 0) {
+ DBG("Failed to set the master Bluetooth address");
+ free(master_bdaddr);
+ return ret;
+ }
+ }
+
+ device_bdaddr = peripheral->get_device_bdaddr(fd);
+ if (device_bdaddr == NULL) {
+ DBG("Failed to get the Bluetooth address from the device");
+ free(master_bdaddr);
+ return -EPERM;
+ }
+
+ DBG("Device bdaddr %s", device_bdaddr);
+
+ ret = create_peripheral_association(adapter_bdaddr, device_bdaddr, peripheral);
+
+ free(device_bdaddr);
+ free(master_bdaddr);
+ return ret;
+}
+
+static inline struct playstation_peripheral *find_playstation_peripheral(const char *hid_id)
+{
+ unsigned int array_size = sizeof(peripherals)/sizeof(peripherals[0]);
+ unsigned int i;
+ int ret;
+ uint16_t protocol;
+ uint16_t vendor_id;
+ uint16_t product_id;
+
+ ret = sscanf(hid_id, "%hx:%hx:%hx", &protocol, &vendor_id, &product_id);
+ if (ret != 3) {
+ error("%s:%s() Parsing HID_ID failed",
+ __FILE__, __func__);
+ return NULL;
+ }
+
+ for (i = 0; i < array_size; i++) {
+ if (peripherals[i].vendor_id == vendor_id &&
+ peripherals[i].product_id == product_id)
+ return &peripherals[i];
+ }
+
+ return NULL;
+}
+
+static inline int is_usb_peripheral(const char *hid_id)
+{
+ int ret;
+ uint16_t protocol;
+ uint16_t vendor_id;
+ uint16_t product_id;
+
+ ret = sscanf(hid_id, "%hx:%hx:%hx", &protocol, &vendor_id, &product_id);
+ if (ret != 3) {
+ error("%s:%s() Parsing HID_ID failed",
+ __FILE__, __func__);
+ return 0;
+ }
+
+ DBG("%hx:%hx:%hx", protocol, vendor_id, product_id);
+ return (protocol == 3);
+}
+
+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_id;
+ const char *hid_phys;
+ const char *hidraw_node;
+ unsigned char is_usb = FALSE;
+ int js_num = 0;
+ int fd;
+ struct playstation_peripheral *peripheral;
+
+ hid_parent = udev_device_get_parent_with_subsystem_devtype(udevice,
+ "hid", NULL);
+ if (!hid_parent) {
+ error("%s:%s() cannot get parent hid device",
+ __FILE__, __func__);
+ return;
+ }
+
+ hid_id = udev_device_get_property_value(hid_parent, "HID_ID");
+ DBG("HID_ID: %s", hid_id);
+
+ peripheral = find_playstation_peripheral(hid_id);
+ if (!peripheral) {
+ error("No supported peripheral found");
+ return;
+ }
+
+ DBG("Found a Playstation peripheral: %s", peripheral->name);
+
+ hidraw_node = udev_device_get_devnode(udevice);
+
+ /* looking for joysticks */
+ hid_phys = udev_device_get_property_value(hid_parent, "HID_PHYS");
+
+ 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("%s:%s() cannot get parent input device.",
+ __FILE__, __func__);
+ 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", js_num);
+ DBG("hidraw_node: %s", hidraw_node);
+ }
+
+ udev_device_unref(js_dev);
+ }
+
+ udev_enumerate_unref(enumerate);
+
+ fd = open(hidraw_node, O_RDWR);
+ if (fd < 0) {
+ error("%s:%s() hidraw open", __FILE__, __func__);
+ return;
+ }
+
+ is_usb = is_usb_peripheral(hid_id);
+ if (is_usb) {
+ char *adapter_bdaddr;
+
+ adapter_bdaddr = btd_adapter_get_default_address();
+ if (adapter_bdaddr == NULL) {
+ error("No adapters, exiting");
+ return;
+ }
+
+ DBG("Adapter bdaddr %s", adapter_bdaddr);
+
+ peripheral_pair(fd, adapter_bdaddr, peripheral);
+ free(adapter_bdaddr);
+ }
+
+ if (js_num > 0) {
+ char c;
+
+ /* wait for events before setting leds */
+ if (read(fd, &c, 1) != 1)
+ error("%s:%s(): read error: %s", __FILE__, __func__,
+ strerror(errno));
+
+ set_controller_number(fd, js_num);
+ }
+
+ close(fd);
+}
+
+static gboolean device_event_idle(struct udev_device *udevice)
+{
+ handle_device_plug(udevice);
+ udev_device_unref(udevice);
+ return FALSE;
+}
+
+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;
+ }
+
+ /* Give UDEV some time to load kernel modules */
+ g_timeout_add_seconds(1, (GSourceFunc) device_event_idle, udevice);
+
+out:
+ return TRUE;
+}
+
+static int playstation_peripheral_init(void)
+{
+ GIOChannel *channel;
+
+ DBG("Setup Playstation peripheral plugin");
+
+ ctx = udev_new();
+ monitor = udev_monitor_new_from_netlink(ctx, "udev");
+ if (monitor == NULL) {
+ error("%s:%s() Could not get udev monitor",
+ __FILE__, __func__);
+ 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 playstation_peripheral_exit(void)
+{
+ DBG("Cleanup Playstation peripheral 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(playstation_peripheral, VERSION,
+ BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+ playstation_peripheral_init,
+ playstation_peripheral_exit)
--- bluez-5.18/src/adapter.c.playstation~ 2014-04-12 12:13:29.000000000 +0200
+++ bluez-5.18/src/adapter.c 2014-05-06 22:09:30.229172158 +0200
@@ -240,6 +240,23 @@ struct btd_adapter *btd_adapter_get_defa
return NULL;
}
+char *btd_adapter_get_default_address(void)
+{
+ struct btd_adapter *adapter;
+ char *str;
+
+ adapter = btd_adapter_get_default();
+ if (adapter == NULL)
+ return NULL;
+
+ str = bt_malloc(18);
+ if (str == NULL)
+ return NULL;
+
+ ba2str(btd_adapter_get_address(adapter), str);
+ return str;
+}
+
bool btd_adapter_is_default(struct btd_adapter *adapter)
{
if (!adapter)
@@ -6787,3 +6804,55 @@ void adapter_shutdown(void)
if (!adapter_remaining)
btd_exit();
}
+
+int btd_create_stored_device(char *adapter_address,
+ char *device_address,
+ char *name,
+ uint16_t vendor_id_source,
+ uint16_t vendor_id,
+ uint16_t product_id,
+ uint16_t version_id,
+ const char *uuid,
+ char *sdp_record,
+ bool trusted)
+{
+ struct btd_adapter *adapter;
+ struct btd_device *device;
+ bdaddr_t dst;
+ int ret = 0;
+
+ store_sdp_record(adapter_address, device_address, 0x10000, sdp_record);
+
+ str2ba(device_address, &dst);
+
+ adapter = btd_adapter_get_default();
+ if (adapter == NULL) {
+ DBG("Failed to get the adapter");
+ ret = -EPERM;
+ goto out;
+ }
+
+ /* This will create the device if necessary */
+ device = btd_adapter_get_device(adapter, &dst, BDADDR_BREDR);
+ if (device == NULL) {
+ DBG("Failed to get the device");
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (name)
+ btd_device_device_set_name(device, name);
+
+ btd_device_set_pnpid(device, vendor_id_source,
+ vendor_id, product_id, version_id);
+
+ if (uuid)
+ btd_device_add_uuid(device, uuid);
+
+ btd_device_set_temporary(device, FALSE);
+
+ if (trusted)
+ btd_device_set_trusted(device, TRUE);
+out:
+ return ret;
+}
--- bluez-5.18/src/adapter.h.playstation~ 2014-03-25 21:53:42.000000000 +0100
+++ bluez-5.18/src/adapter.h 2014-05-06 22:09:30.230172158 +0200
@@ -39,6 +39,7 @@ struct btd_adapter;
struct btd_device;
struct btd_adapter *btd_adapter_get_default(void);
+char *btd_adapter_get_default_address(void);
bool btd_adapter_is_default(struct btd_adapter *adapter);
uint16_t btd_adapter_get_index(struct btd_adapter *adapter);
@@ -199,3 +200,14 @@ gboolean btd_adapter_check_oob_handler(s
void btd_adapter_for_each_device(struct btd_adapter *adapter,
void (*cb)(struct btd_device *device, void *data),
void *data);
+
+int btd_create_stored_device(char *btd_adapter_address,
+ char *device_address,
+ char *name,
+ uint16_t vendor_id_source,
+ uint16_t vendor_id,
+ uint16_t product_id,
+ uint16_t version_id,
+ const char *uuid,
+ char *sdp_record,
+ bool trusted);