From ae84f859b95b5b32524529e2e0a0f8c93a5ad3e0 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Tue, 25 Jul 2017 22:42:42 -0700 Subject: binding: bluetooth: listen for rfkill bluetooth events On certain platforms like RPI3 and Porter there is a possible race condition to systemd-rfkill service if using a USB BT device, and this patchset listens for rfkill events, unblocks and brings up hci interface. Change-Id: I336e496b589a23767003e186473c4aed49471fba Bug-AGL: SPEC-569 Signed-off-by: Matt Ranostay --- binding-bluetooth/bluetooth-api.c | 6 --- binding-bluetooth/bluetooth-manager.c | 99 +++++++++++++++++++++++++++++++++++ binding-bluetooth/bluetooth-manager.h | 8 +++ 3 files changed, 107 insertions(+), 6 deletions(-) diff --git a/binding-bluetooth/bluetooth-api.c b/binding-bluetooth/bluetooth-api.c index 39acb9a..16957ae 100644 --- a/binding-bluetooth/bluetooth-api.c +++ b/binding-bluetooth/bluetooth-api.c @@ -935,12 +935,6 @@ const struct afb_binding *afbBindingV1Register (const struct afb_binding_interfa { afbitf = itf; // records the interface for accessing afb-daemon -#if 1 -//temp solution to fix configure Bluetooth USB Dongle - system("rfkill unblock bluetooth"); - system("hciconfig hci0 up"); -#endif - Binding_RegisterCallback_t API_Callback; API_Callback.binding_device_added = bt_broadcast_device_added; API_Callback.binding_device_removed = bt_broadcast_device_removed; diff --git a/binding-bluetooth/bluetooth-manager.c b/binding-bluetooth/bluetooth-manager.c index 24312c2..13210bb 100644 --- a/binding-bluetooth/bluetooth-manager.c +++ b/binding-bluetooth/bluetooth-manager.c @@ -19,10 +19,14 @@ #include #include #include +#include #include #include +#include #include #include +#include +#include #include #include "bluetooth-manager.h" @@ -968,6 +972,100 @@ static int bt_manager_app_init(void) return 0; } +int hci_interface_enable(int hdev) +{ + int ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); + int ret; + + if (ctl < 0) + return ctl; + + ret = ioctl(ctl, HCIDEVUP, hdev); + + close(ctl); + + return ret; +} + +gboolean bluetooth_rfkill_event(GIOChannel *chan, GIOCondition cond, gpointer data) +{ + LOGD("\n"); + struct rfkill_event event; + gchar *name, buf[8]; + int fd, len; + + fd = g_io_channel_unix_get_fd(chan); + len = read(fd, &event, sizeof(struct rfkill_event)); + + if (len != sizeof(struct rfkill_event)) + return TRUE; + + if (event.type != RFKILL_TYPE_BLUETOOTH) + return TRUE; + + if (event.op == RFKILL_OP_DEL) + return TRUE; + + name = g_strdup_printf("/sys/class/rfkill/rfkill%u/soft", event.idx); + + fd = g_open(name, O_WRONLY); + write(fd, "0", 1); + g_close(fd, NULL); + + g_free(name); + + memset(&buf, 0, sizeof(buf)); + + name = g_strdup_printf("/sys/class/rfkill/rfkill%u/name", event.idx); + fd = g_open(name, O_RDONLY); + len = read(fd, &buf, sizeof(buf) - 1); + + if (len > 0) + { + int idx = 0; + sscanf(buf, "hci%d", &idx); + + /* + * 50 millisecond delay to allow time for rfkill to unblock before + * attempting to bring up HCI interface + */ + g_usleep(50000); + + LOGD ("Enabling hci%d interface\n", idx); + hci_interface_enable(idx); + } + + g_free(name); + + return TRUE; +} + + +/* Create RFKILL monitor to soft unblock bluetooth devices + * + * Returns: 0 - success or other errors + */ +int BluetoothMonitorInit() +{ + int fd = g_open("/dev/rfkill", O_RDWR); + GIOChannel *chan = NULL; + + if (fd < 0) + { + LOGE("Cannot open /dev/rfkill"); + return -1; + } + + chan = g_io_channel_unix_new(fd); + g_io_channel_set_close_on_unref(chan, TRUE); + + BluetoothManage.watch = g_io_add_watch(chan, G_IO_IN, bluetooth_rfkill_event, NULL); + + g_io_channel_unref(chan); + + return 0; +} + /* * Bluetooth Manager Thread * register callback function and create a new GMainLoop structure @@ -985,6 +1083,7 @@ static void *bt_event_loop_thread() devices_list_update(); BluetoothManage_InitFlag_Set(TRUE); + BluetoothMonitorInit(); LOGD("g_main_loop_run\n"); g_main_loop_run(cli.clientloop); diff --git a/binding-bluetooth/bluetooth-manager.h b/binding-bluetooth/bluetooth-manager.h index b11b11d..ed02b28 100644 --- a/binding-bluetooth/bluetooth-manager.h +++ b/binding-bluetooth/bluetooth-manager.h @@ -20,6 +20,7 @@ #include #include #include +#include /* Debug Trace Level */ #define DT_LEVEL_ERROR (1 << 1) @@ -119,6 +120,12 @@ #define ERROR_BLUEZ_REJECT "org.bluez.Error.Rejected" #define ERROR_BLUEZ_CANCELED "org.bluez.Error.Canceled" + +#define HCIDEVUP _IOW('H', 201, int) + +#define AF_BLUETOOTH 31 +#define BTPROTO_HCI 1 + #if 0 void DebugTraceSendMsg(int level, gchar* message); #else @@ -153,6 +160,7 @@ struct btd_device { typedef struct { gboolean inited; GMutex m; + gint watch; GSList * device; } stBluetoothManage; -- cgit 1.2.3-korg