@@ -39,7 +39,9 @@
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
+#if USE_SYSTEMD
#include <systemd/sd-daemon.h>
+#endif
#include <gbinder.h>
@@ -70,8 +72,37 @@
GIOChannel *channel;
GBinderClient *binder_client;
int gio_channel_event_id;
+
+ int binder_replies_pending;
+ gboolean init_failed;
};
+void
+handle_binder_reply(
+ GBinderClient* client,
+ GBinderRemoteReply* reply,
+ int status,
+ void* user_data)
+{
+ struct proxy *proxy = user_data;
+
+ proxy->binder_replies_pending--;
+
+ if (status != GBINDER_STATUS_OK || !reply) {
+ fprintf(stderr, "%s: binder transaction has failed: status = %d reply = %p\n", __func__, status, reply);
+ g_main_loop_quit(proxy->loop);
+ }
+}
+
+gboolean
+waiting_for_binder_reply(
+ gpointer user_data
+)
+{
+ struct proxy *proxy = user_data;
+ return proxy->binder_replies_pending > 0;
+}
+
static
void
host_write_packet(
@@ -79,10 +110,7 @@
void *buf,
uint16_t len)
{
- int status = GBINDER_STATUS_FAILED;
-
GBinderLocalRequest *local_request = NULL;
- GBinderRemoteReply *reply = NULL;
GBinderWriter writer;
local_request = gbinder_client_new_request(proxy->binder_client);
@@ -96,25 +124,26 @@
// data, without the package type.
gbinder_writer_append_hidl_vec(&writer, (void*)((char*)buf + 1), len - 1, sizeof(uint8_t));
+ proxy->binder_replies_pending++;
+ // priority must be higher than the gio channel, otherwise we might process a second command
+ // before the first one was accepted.
+ // but it must be lower than the binder reply callback since otherwise we might send more packets
+ // than the remote can handle.
+ // it is defined in libgbinder as G_PRIORITY_DEFAULT_IDLE and must stay in sync with this
+ g_idle_add_full(G_PRIORITY_DEFAULT_IDLE + 1, waiting_for_binder_reply, proxy, NULL);
+
if (((uint8_t*)buf)[0] == HCI_COMMAND_PKT) {
- reply = gbinder_client_transact_sync_reply(proxy->binder_client, 2 /* sendHciCommand */, local_request, &status);
+ gbinder_client_transact(proxy->binder_client, 2 /* sendHciCommand */, 0, local_request, handle_binder_reply, NULL, proxy);
} else if (((uint8_t*)buf)[0] == HCI_ACLDATA_PKT) {
- reply = gbinder_client_transact_sync_reply(proxy->binder_client, 3 /* sendAclData */, local_request, &status);
+ gbinder_client_transact(proxy->binder_client, 3 /* sendAclData */, 0, local_request, handle_binder_reply, NULL, proxy);
} else if (((uint8_t*)buf)[0] == HCI_SCODATA_PKT) {
- reply = gbinder_client_transact_sync_reply(proxy->binder_client, 4 /* sendScoData */, local_request, &status);
+ gbinder_client_transact(proxy->binder_client, 4 /* sendScoData */, 0, local_request, handle_binder_reply, NULL, proxy);
} else {
fprintf(stderr, "Received incorrect packet type from HCI client.\n");
g_main_loop_quit(proxy->loop);
}
- if (status != GBINDER_STATUS_OK || !reply) {
- fprintf(stderr, "%s: status = %d reply = %p\n", __func__, status, reply);
- // can this happen legitimately?
- g_main_loop_quit(proxy->loop);
- }
-
gbinder_local_request_unref(local_request);
- gbinder_remote_reply_unref(reply);
}
static
@@ -137,7 +166,8 @@
if (status == G_IO_STATUS_ERROR) {
fprintf(stderr, "Writing packet to device failed: %s\n", error->message);
- g_main_loop_quit(proxy->loop);
+ // do not quit here, since this might happen if the user switches off
+ // bt but the hw still wants to send a final event.
return;
}
@@ -196,7 +226,7 @@
if (proxy->host_len < 1)
return true;
- switch (proxy->host_buf[0]) {
+ switch ((guint8)proxy->host_buf[0]) {
case HCI_COMMAND_PKT:
if (proxy->host_len < 1 + sizeof(*cmd_hdr))
return true;
@@ -260,11 +290,13 @@
g_io_channel_set_encoding(proxy->channel, NULL, NULL);
g_io_channel_set_buffered(proxy->channel, FALSE);
- proxy->gio_channel_event_id = g_io_add_watch(
+ proxy->gio_channel_event_id = g_io_add_watch_full(
proxy->channel,
+ G_PRIORITY_DEFAULT_IDLE + 2, // see host_write_packet
G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
host_read_callback,
- proxy);
+ proxy,
+ NULL);
return true;
}
@@ -319,6 +351,30 @@
}
static
+gboolean
+binder_init_complete(
+ struct proxy* proxy)
+{
+ fprintf(stderr, "Binder interface initialized, opening virtual device\n");
+
+ proxy->host_fd = open_vhci(HCI_PRIMARY);
+ if (proxy->host_fd < 0) {
+ fprintf(stderr, "Unable to open virtual device\n");
+ return FALSE;
+ }
+
+ if (!setup_watch(proxy)) {
+ fprintf(stderr, "Unable to setup watch\n");
+ return FALSE;
+ }
+
+ if (proxy->init_failed && proxy->loop)
+ g_main_loop_quit(proxy->loop);
+
+ return TRUE;
+}
+
+static
GBinderLocalReply*
bluebinder_callbacks_transact(
GBinderLocalObject* obj,
@@ -344,35 +400,27 @@
if (result != 0) {
fprintf(stderr, "Bluetooth binder service failed\n");
- g_main_loop_quit(proxy->loop);
- *status = GBINDER_STATUS_FAILED;
- return NULL;
+ /* we need to tell BT service that we properly handled Status::INITIALIZATION_ERROR */
+ *status = GBINDER_STATUS_OK;
+ proxy->init_failed = TRUE;
+ return gbinder_local_reply_append_int32(gbinder_local_object_new_reply(obj), 0);
}
- fprintf(stderr, "Binder interface initialized, opening virtual device\n");
-
- proxy->host_fd = open_vhci(HCI_PRIMARY);
- if (proxy->host_fd < 0) {
- fprintf(stderr, "Unable to open virtual device\n");
- g_main_loop_quit(proxy->loop);
- *status = GBINDER_STATUS_FAILED;
- return NULL;
- }
-
- if (!setup_watch(proxy)) {
- fprintf(stderr, "Unable to setup watch\n");
- g_main_loop_quit(proxy->loop);
+ if (binder_init_complete(proxy)) {
+ proxy->init_failed = FALSE;
+#if USE_SYSTEMD
+ sd_notify(0, "READY=1");
+#endif
+ *status = GBINDER_STATUS_OK;
+ return gbinder_local_reply_append_int32(gbinder_local_object_new_reply(obj), 0);
+ } else {
+ proxy->init_failed = TRUE;
*status = GBINDER_STATUS_FAILED;
return NULL;
}
|
[-]
[+]
|
Added |
_service:tar_git:bluebinder-1.0.12.tar.bz2/bluebinder_post.sh
^
|
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+# Check for port provided script to populate the bluetooth address
+if [ -x /usr/bin/droid/droid-get-bt-address.sh ] ; then
+ /usr/bin/droid/droid-get-bt-address.sh
+fi
+
+# If the bluetooth address is provided by another script use that
+if [ -f /var/lib/bluetooth/board-address ] ; then
+ exit 0
+fi
+
+mkdir -p /var/lib/bluetooth
+
+# Getting address file from properties
+bt_addr_file=$(/usr/bin/getprop ro.bt.bdaddr_path)
+if [ "$bt_addr_file" != "" ]; then
+ if ! cp $bt_addr_file /var/lib/bluetooth/board-address; then
+ echo "Failed to copy $bt_addr_file."
+ exit 1
+ fi
+elif [ "$(getprop persist.vendor.service.bdroid.bdaddr)" != "" ]; then
+ echo $(getprop persist.vendor.service.bdroid.bdaddr |awk -F: '{do printf "%s"(NF>1?FS:RS),$NF;while(--NF)}') > /var/lib/bluetooth/board-address
+ if [ ! -f /var/lib/bluetooth/board-address ]; then
+ echo "Failed to set bluetooth address."
+ exit 1
+ fi
+else
+ echo "Failed to get bluetooth address!"
+ exit 1
+fi
+
+# Set proper permissions
+chown root:root /var/lib/bluetooth/board-address
+chmod 644 /var/lib/bluetooth/board-address
+exit 0
|