subdirs = [
"test_vendor_lib",
+ "linux",
]
--- /dev/null
+subdirs = [
+ "interface",
+]
+++ /dev/null
-#
-# Copyright (C) 2015 Intel Corporation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-ifeq ($(BOARD_HAVE_BLUETOOTH_LINUX), true)
-
-# libbt-vendor shared library for target
-# ========================================================
-include $(CLEAR_VARS)
-
-LOCAL_CPP_EXTENSION := .cc
-
-LOCAL_SRC_FILES := \
- bt_vendor_linux.cc
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/../../
-
-LOCAL_SHARED_LIBRARIES := \
- liblog \
- libcutils
-
-LOCAL_STATIC_LIBRARIES := libosi
-
-LOCAL_MODULE := libbt-vendor
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS += $(test-vendor_CFLAGS)
-LOCAL_CONLYFLAGS += $(test-vendor_CONLYFLAGS)
-
-include $(BUILD_SHARED_LIBRARY)
-
-endif # BOARD_HAVE_BLUETOOTH_LINUX
+++ /dev/null
-/**********************************************************************
- *
- * Copyright (C) 2015 Intel Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- * implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- **********************************************************************/
-
-#define LOG_TAG "bt_vendor"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <poll.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-
-#include "hci/include/bt_vendor_lib.h"
-#include "osi/include/compat.h"
-#include "osi/include/log.h"
-#include "osi/include/osi.h"
-#include "osi/include/properties.h"
-
-#define BTPROTO_HCI 1
-#define HCI_CHANNEL_USER 1
-#define HCI_CHANNEL_CONTROL 3
-#define HCI_DEV_NONE 0xffff
-
-#define RFKILL_TYPE_BLUETOOTH 2
-#define RFKILL_OP_CHANGE_ALL 3
-
-#define MGMT_OP_INDEX_LIST 0x0003
-#define MGMT_EV_INDEX_ADDED 0x0004
-#define MGMT_EV_COMMAND_COMP 0x0001
-#define MGMT_EV_SIZE_MAX 1024
-#define MGMT_EV_POLL_TIMEOUT 3000 /* 3000ms */
-
-#define IOCTL_HCIDEVDOWN _IOW('H', 202, int)
-
-struct sockaddr_hci {
- sa_family_t hci_family;
- unsigned short hci_dev;
- unsigned short hci_channel;
-};
-
-struct rfkill_event {
- uint32_t idx;
- uint8_t type;
- uint8_t op;
- uint8_t soft, hard;
-} __attribute__((packed));
-
-struct mgmt_pkt {
- uint16_t opcode;
- uint16_t index;
- uint16_t len;
- uint8_t data[MGMT_EV_SIZE_MAX];
-} __attribute__((packed));
-
-struct mgmt_event_read_index {
- uint16_t cc_opcode;
- uint8_t status;
- uint16_t num_intf;
- uint16_t index[0];
-} __attribute__((packed));
-
-static const bt_vendor_callbacks_t* bt_vendor_callbacks;
-static unsigned char bt_vendor_local_bdaddr[6];
-static int bt_vendor_fd = -1;
-static int hci_interface;
-static int rfkill_en;
-static int bt_hwcfg_en;
-
-static int bt_vendor_init(const bt_vendor_callbacks_t* p_cb,
- unsigned char* local_bdaddr) {
- char prop_value[PROPERTY_VALUE_MAX];
-
- LOG_INFO(LOG_TAG, "%s", __func__);
-
- if (p_cb == NULL) {
- LOG_ERROR(LOG_TAG, "init failed with no user callbacks!");
- return -1;
- }
-
- bt_vendor_callbacks = p_cb;
-
- memcpy(bt_vendor_local_bdaddr, local_bdaddr, sizeof(bt_vendor_local_bdaddr));
-
- osi_property_get("bluetooth.interface", prop_value, "0");
-
- errno = 0;
- if (memcmp(prop_value, "hci", 3))
- hci_interface = strtol(prop_value, NULL, 10);
- else
- hci_interface = strtol(prop_value + 3, NULL, 10);
- if (errno) hci_interface = 0;
-
- LOG_INFO(LOG_TAG, "Using interface hci%d", hci_interface);
-
- osi_property_get("bluetooth.rfkill", prop_value, "0");
-
- rfkill_en = atoi(prop_value);
- if (rfkill_en) LOG_INFO(LOG_TAG, "RFKILL enabled");
-
- bt_hwcfg_en =
- osi_property_get("bluetooth.hwcfg", prop_value, NULL) > 0 ? 1 : 0;
- if (bt_hwcfg_en) LOG_INFO(LOG_TAG, "HWCFG enabled");
-
- return 0;
-}
-
-static int bt_vendor_hw_cfg(int stop) {
- if (!bt_hwcfg_en) return 0;
-
- if (stop) {
- if (osi_property_set("bluetooth.hwcfg", "stop") < 0) {
- LOG_ERROR(LOG_TAG, "%s cannot stop btcfg service via prop", __func__);
- return 1;
- }
- } else {
- if (osi_property_set("bluetooth.hwcfg", "start") < 0) {
- LOG_ERROR(LOG_TAG, "%s cannot start btcfg service via prop", __func__);
- return 1;
- }
- }
- return 0;
-}
-
-static int bt_vendor_wait_hcidev(void) {
- struct sockaddr_hci addr;
- struct pollfd fds[1];
- struct mgmt_pkt ev;
- int fd;
- int ret = 0;
-
- LOG_INFO(LOG_TAG, "%s", __func__);
-
- fd = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
- if (fd < 0) {
- LOG_ERROR(LOG_TAG, "Bluetooth socket error: %s", strerror(errno));
- return -1;
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.hci_family = AF_BLUETOOTH;
- addr.hci_dev = HCI_DEV_NONE;
- addr.hci_channel = HCI_CHANNEL_CONTROL;
-
- if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
- LOG_ERROR(LOG_TAG, "HCI Channel Control: %s", strerror(errno));
- close(fd);
- return -1;
- }
-
- fds[0].fd = fd;
- fds[0].events = POLLIN;
-
- /* Read Controller Index List Command */
- ev.opcode = MGMT_OP_INDEX_LIST;
- ev.index = HCI_DEV_NONE;
- ev.len = 0;
-
- ssize_t wrote;
- OSI_NO_INTR(wrote = write(fd, &ev, 6));
- if (wrote != 6) {
- LOG_ERROR(LOG_TAG, "Unable to write mgmt command: %s", strerror(errno));
- ret = -1;
- goto end;
- }
-
- while (1) {
- int n;
- OSI_NO_INTR(n = poll(fds, 1, MGMT_EV_POLL_TIMEOUT));
- if (n == -1) {
- LOG_ERROR(LOG_TAG, "Poll error: %s", strerror(errno));
- ret = -1;
- break;
- } else if (n == 0) {
- LOG_ERROR(LOG_TAG, "Timeout, no HCI device detected");
- ret = -1;
- break;
- }
-
- if (fds[0].revents & POLLIN) {
- OSI_NO_INTR(n = read(fd, &ev, sizeof(struct mgmt_pkt)));
- if (n < 0) {
- LOG_ERROR(LOG_TAG, "Error reading control channel: %s",
- strerror(errno));
- ret = -1;
- break;
- }
-
- if (ev.opcode == MGMT_EV_INDEX_ADDED && ev.index == hci_interface) {
- goto end;
- } else if (ev.opcode == MGMT_EV_COMMAND_COMP) {
- struct mgmt_event_read_index* cc;
- int i;
-
- cc = (struct mgmt_event_read_index*)ev.data;
-
- if (cc->cc_opcode != MGMT_OP_INDEX_LIST || cc->status != 0) continue;
-
- for (i = 0; i < cc->num_intf; i++) {
- if (cc->index[i] == hci_interface) goto end;
- }
- }
- }
- }
-
-end:
- close(fd);
- return ret;
-}
-
-static int bt_vendor_open(void* param) {
- int(*fd_array)[] = (int(*)[])param;
- int fd;
-
- LOG_INFO(LOG_TAG, "%s", __func__);
-
- fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
- if (fd < 0) {
- LOG_ERROR(LOG_TAG, "socket create error %s", strerror(errno));
- return -1;
- }
-
- (*fd_array)[CH_CMD] = fd;
- (*fd_array)[CH_EVT] = fd;
- (*fd_array)[CH_ACL_OUT] = fd;
- (*fd_array)[CH_ACL_IN] = fd;
-
- bt_vendor_fd = fd;
-
- LOG_INFO(LOG_TAG, "%s returning %d", __func__, bt_vendor_fd);
-
- return 1;
-}
-
-static int bt_vendor_close(void* param) {
- (void)(param);
-
- LOG_INFO(LOG_TAG, "%s", __func__);
-
- if (bt_vendor_fd != -1) {
- close(bt_vendor_fd);
- bt_vendor_fd = -1;
- }
-
- return 0;
-}
-
-static int bt_vendor_rfkill(int block) {
- struct rfkill_event event;
- int fd;
-
- LOG_INFO(LOG_TAG, "%s", __func__);
-
- fd = open("/dev/rfkill", O_WRONLY);
- if (fd < 0) {
- LOG_ERROR(LOG_TAG, "Unable to open /dev/rfkill");
- return -1;
- }
-
- memset(&event, 0, sizeof(struct rfkill_event));
- event.op = RFKILL_OP_CHANGE_ALL;
- event.type = RFKILL_TYPE_BLUETOOTH;
- event.hard = block;
- event.soft = block;
-
- ssize_t len;
- OSI_NO_INTR(len = write(fd, &event, sizeof(event)));
- if (len < 0) {
- LOG_ERROR(LOG_TAG, "Failed to change rfkill state");
- close(fd);
- return 1;
- }
-
- close(fd);
- return 0;
-}
-
-/* TODO: fw config should thread the device waiting and return immedialty */
-static void bt_vendor_fw_cfg(void) {
- struct sockaddr_hci addr;
- int fd = bt_vendor_fd;
-
- LOG_INFO(LOG_TAG, "%s", __func__);
-
- if (fd == -1) {
- LOG_ERROR(LOG_TAG, "bt_vendor_fd: %s", strerror(EBADF));
- goto failure;
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.hci_family = AF_BLUETOOTH;
- addr.hci_dev = hci_interface;
- addr.hci_channel = HCI_CHANNEL_USER;
-
- if (bt_vendor_wait_hcidev()) {
- LOG_ERROR(LOG_TAG, "HCI interface (%d) not found", hci_interface);
- goto failure;
- }
-
- if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
- LOG_ERROR(LOG_TAG, "socket bind error %s", strerror(errno));
- goto failure;
- }
-
- LOG_INFO(LOG_TAG, "HCI device ready");
-
- bt_vendor_callbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
-
- return;
-
-failure:
- LOG_ERROR(LOG_TAG, "Hardware Config Error");
- bt_vendor_callbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
-}
-
-static int bt_vendor_op(bt_vendor_opcode_t opcode, void* param) {
- int retval = 0;
-
- LOG_INFO(LOG_TAG, "%s op %d", __func__, opcode);
-
- switch (opcode) {
- case BT_VND_OP_POWER_CTRL:
- if (!rfkill_en || !param) break;
-
- if (*((int*)param) == BT_VND_PWR_ON) {
- retval = bt_vendor_rfkill(0);
- if (!retval) retval = bt_vendor_hw_cfg(0);
- } else {
- retval = bt_vendor_hw_cfg(1);
- if (!retval) retval = bt_vendor_rfkill(1);
- }
-
- break;
-
- case BT_VND_OP_FW_CFG:
- bt_vendor_fw_cfg();
- break;
-
- case BT_VND_OP_SCO_CFG:
- bt_vendor_callbacks->scocfg_cb(BT_VND_OP_RESULT_SUCCESS);
- break;
-
- case BT_VND_OP_USERIAL_OPEN:
- retval = bt_vendor_open(param);
- break;
-
- case BT_VND_OP_USERIAL_CLOSE:
- retval = bt_vendor_close(param);
- break;
-
- case BT_VND_OP_GET_LPM_IDLE_TIMEOUT:
- *((uint32_t*)param) = 3000;
- retval = 0;
- break;
-
- case BT_VND_OP_LPM_SET_MODE:
- bt_vendor_callbacks->lpm_cb(BT_VND_OP_RESULT_SUCCESS);
- break;
-
- case BT_VND_OP_LPM_WAKE_SET_STATE:
- break;
-
- case BT_VND_OP_SET_AUDIO_STATE:
- bt_vendor_callbacks->audio_state_cb(BT_VND_OP_RESULT_SUCCESS);
- break;
-
- case BT_VND_OP_EPILOG:
- bt_vendor_callbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
- break;
-
- case BT_VND_OP_A2DP_OFFLOAD_START:
- break;
-
- case BT_VND_OP_A2DP_OFFLOAD_STOP:
- break;
- }
-
- LOG_INFO(LOG_TAG, "%s op %d retval %d", __func__, opcode, retval);
-
- return retval;
-}
-
-static void bt_vendor_cleanup(void) {
- LOG_INFO(LOG_TAG, "%s", __func__);
-
- bt_vendor_callbacks = NULL;
-}
-
-EXPORT_SYMBOL const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
- sizeof(bt_vendor_interface_t), bt_vendor_init, bt_vendor_op,
- bt_vendor_cleanup,
-};
--- /dev/null
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_binary {
+ name: "android.hardware.bluetooth@1.0-service.btlinux",
+ proprietary: true,
+ relative_install_path: "hw",
+ srcs: [
+ "hci_packetizer.cc",
+ "h4_protocol.cc",
+ "bluetooth_hci.cc",
+ "async_fd_watcher.cc",
+ "service.cc"
+ ],
+ shared_libs: [
+ "android.hardware.bluetooth@1.0",
+ "libbase",
+ "libcutils",
+ "libhardware",
+ "libhidlbase",
+ "libhidltransport",
+ "liblog",
+ "libutils",
+ ],
+ conlyflags: [
+ "-std=c99",
+ ],
+ init_rc: ["android.hardware.bluetooth@1.0-service.btlinux.rc"],
+}
+
--- /dev/null
+service btlinux-1.0 /vendor/bin/hw/android.hardware.bluetooth@1.0-service.btlinux
+ class hal
+ user bluetooth
+ group bluetooth net_admin net_bt_admin
+ capabilities NET_ADMIN
--- /dev/null
+//
+// Copyright 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "async_fd_watcher.h"
+
+#include <algorithm>
+#include <atomic>
+#include <condition_variable>
+#include <log/log.h>
+#include <map>
+#include <mutex>
+#include <thread>
+#include <vector>
+#include "fcntl.h"
+#include "sys/select.h"
+#include "unistd.h"
+
+static const int INVALID_FD = -1;
+static const int BT_RT_PRIORITY = 1;
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace async {
+
+int AsyncFdWatcher::WatchFdForNonBlockingReads(
+ int file_descriptor, const ReadCallback& on_read_fd_ready_callback) {
+ // Add file descriptor and callback
+ {
+ std::unique_lock<std::mutex> guard(internal_mutex_);
+ watched_fds_[file_descriptor] = on_read_fd_ready_callback;
+ }
+
+ // Start the thread if not started yet
+ return tryStartThread();
+}
+
+int AsyncFdWatcher::ConfigureTimeout(
+ const std::chrono::milliseconds timeout,
+ const TimeoutCallback& on_timeout_callback) {
+ // Add timeout and callback
+ {
+ std::unique_lock<std::mutex> guard(timeout_mutex_);
+ timeout_cb_ = on_timeout_callback;
+ timeout_ms_ = timeout;
+ }
+
+ notifyThread();
+ return 0;
+}
+
+void AsyncFdWatcher::StopWatchingFileDescriptors() { stopThread(); }
+
+AsyncFdWatcher::~AsyncFdWatcher() {}
+
+// Make sure to call this with at least one file descriptor ready to be
+// watched upon or the thread routine will return immediately
+int AsyncFdWatcher::tryStartThread() {
+ if (std::atomic_exchange(&running_, true)) return 0;
+
+ // Set up the communication channel
+ int pipe_fds[2];
+ if (pipe2(pipe_fds, O_NONBLOCK)) return -1;
+
+ notification_listen_fd_ = pipe_fds[0];
+ notification_write_fd_ = pipe_fds[1];
+
+ thread_ = std::thread([this]() { ThreadRoutine(); });
+ if (!thread_.joinable()) return -1;
+
+ return 0;
+}
+
+int AsyncFdWatcher::stopThread() {
+ if (!std::atomic_exchange(&running_, false)) return 0;
+
+ notifyThread();
+ if (std::this_thread::get_id() != thread_.get_id()) {
+ thread_.join();
+ }
+
+ {
+ std::unique_lock<std::mutex> guard(internal_mutex_);
+ watched_fds_.clear();
+ }
+
+ {
+ std::unique_lock<std::mutex> guard(timeout_mutex_);
+ timeout_cb_ = nullptr;
+ }
+
+ return 0;
+}
+
+int AsyncFdWatcher::notifyThread() {
+ uint8_t buffer[] = {0};
+ if (TEMP_FAILURE_RETRY(write(notification_write_fd_, &buffer, 1)) < 0) {
+ return -1;
+ }
+ return 0;
+}
+
+void AsyncFdWatcher::ThreadRoutine() {
+
+ // Make watching thread RT.
+ struct sched_param rt_params;
+ rt_params.sched_priority = BT_RT_PRIORITY;
+ if (sched_setscheduler(gettid(), SCHED_FIFO, &rt_params)) {
+ ALOGE("%s unable to set SCHED_FIFO for pid %d, tid %d, error %s", __func__,
+ getpid(), gettid(), strerror(errno));
+ }
+
+ while (running_) {
+ fd_set read_fds;
+ FD_ZERO(&read_fds);
+ FD_SET(notification_listen_fd_, &read_fds);
+ int max_read_fd = INVALID_FD;
+ for (auto& it : watched_fds_) {
+ FD_SET(it.first, &read_fds);
+ max_read_fd = std::max(max_read_fd, it.first);
+ }
+
+ struct timeval timeout;
+ struct timeval* timeout_ptr = NULL;
+ if (timeout_ms_ > std::chrono::milliseconds(0)) {
+ timeout.tv_sec = timeout_ms_.count() / 1000;
+ timeout.tv_usec = (timeout_ms_.count() % 1000) * 1000;
+ timeout_ptr = &timeout;
+ }
+
+ // Wait until there is data available to read on some FD.
+ int nfds = std::max(notification_listen_fd_, max_read_fd);
+ int retval = select(nfds + 1, &read_fds, NULL, NULL, timeout_ptr);
+
+ // There was some error.
+ if (retval < 0) continue;
+
+ // Timeout.
+ if (retval == 0) {
+ // Allow the timeout callback to modify the timeout.
+ TimeoutCallback saved_cb;
+ {
+ std::unique_lock<std::mutex> guard(timeout_mutex_);
+ if (timeout_ms_ > std::chrono::milliseconds(0))
+ saved_cb = timeout_cb_;
+ }
+ if (saved_cb != nullptr)
+ saved_cb();
+ continue;
+ }
+
+ // Read data from the notification FD.
+ if (FD_ISSET(notification_listen_fd_, &read_fds)) {
+ char buffer[] = {0};
+ TEMP_FAILURE_RETRY(read(notification_listen_fd_, buffer, 1));
+ continue;
+ }
+
+ // Invoke the data ready callbacks if appropriate.
+ {
+ // Hold the mutex to make sure that the callbacks are still valid.
+ std::unique_lock<std::mutex> guard(internal_mutex_);
+ for (auto& it : watched_fds_) {
+ if (FD_ISSET(it.first, &read_fds)) {
+ it.second(it.first);
+ }
+ }
+ }
+ }
+}
+
+} // namespace async
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
--- /dev/null
+//
+// Copyright 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#pragma once
+
+#include <map>
+#include <mutex>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace async {
+
+using ReadCallback = std::function<void(int)>;
+using TimeoutCallback = std::function<void(void)>;
+
+class AsyncFdWatcher {
+ public:
+ AsyncFdWatcher() = default;
+ ~AsyncFdWatcher();
+
+ int WatchFdForNonBlockingReads(int file_descriptor,
+ const ReadCallback& on_read_fd_ready_callback);
+ int ConfigureTimeout(const std::chrono::milliseconds timeout,
+ const TimeoutCallback& on_timeout_callback);
+ void StopWatchingFileDescriptors();
+
+ private:
+ AsyncFdWatcher(const AsyncFdWatcher&) = delete;
+ AsyncFdWatcher& operator=(const AsyncFdWatcher&) = delete;
+
+ int tryStartThread();
+ int stopThread();
+ int notifyThread();
+ void ThreadRoutine();
+
+ std::atomic_bool running_{false};
+ std::thread thread_;
+ std::mutex internal_mutex_;
+ std::mutex timeout_mutex_;
+
+ std::map<int, ReadCallback> watched_fds_;
+ int notification_listen_fd_;
+ int notification_write_fd_;
+ TimeoutCallback timeout_cb_;
+ std::chrono::milliseconds timeout_ms_;
+};
+
+
+} // namespace async
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
--- /dev/null
+//
+// Copyright 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#define LOG_TAG "android.hardware.bluetooth@1.0-btlinux"
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/socket.h>
+
+#include <utils/Log.h>
+
+#include "bluetooth_hci.h"
+
+#define BTPROTO_HCI 1
+
+#define HCI_CHANNEL_USER 1
+#define HCI_CHANNEL_CONTROL 3
+#define HCI_DEV_NONE 0xffff
+
+/* reference from <kernel>/include/net/bluetooth/mgmt.h */
+#define MGMT_OP_INDEX_LIST 0x0003
+#define MGMT_EV_INDEX_ADDED 0x0004
+#define MGMT_EV_COMMAND_COMP 0x0001
+#define MGMT_EV_SIZE_MAX 1024
+#define MGMT_EV_POLL_TIMEOUT 3000 /* 3000ms */
+#define WRITE_NO_INTR(fn) \
+ do { \
+ } while ((fn) == -1 && errno == EINTR)
+
+struct sockaddr_hci {
+ sa_family_t hci_family;
+ unsigned short hci_dev;
+ unsigned short hci_channel;
+};
+
+struct mgmt_pkt {
+ uint16_t opcode;
+ uint16_t index;
+ uint16_t len;
+ uint8_t data[MGMT_EV_SIZE_MAX];
+} __attribute__((packed));
+
+struct mgmt_event_read_index {
+ uint16_t cc_opcode;
+ uint8_t status;
+ uint16_t num_intf;
+ uint16_t index[0];
+ } __attribute__((packed));
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace V1_0 {
+namespace btlinux {
+
+int BluetoothHci::openBtHci() {
+
+ ALOGI( "%s", __func__);
+
+ int hci_interface = 0;
+ rfkill_state_ = NULL;
+ rfKill(1);
+
+ int fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (fd < 0) {
+ ALOGE( "Bluetooth socket error: %s", strerror(errno));
+ return -1;
+ }
+ bt_soc_fd_ = fd;
+
+ if (waitHciDev(hci_interface)) {
+ ALOGE( "HCI interface (%d) not found", hci_interface);
+ ::close(fd);
+ return -1;
+ }
+ struct sockaddr_hci addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.hci_family = AF_BLUETOOTH;
+ addr.hci_dev = hci_interface;
+ addr.hci_channel = HCI_CHANNEL_USER;
+ if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
+ ALOGE( "HCI Channel Control: %s", strerror(errno));
+ ::close(fd);
+ return -1;
+ }
+ ALOGI( "HCI device ready");
+ return fd;
+}
+
+void BluetoothHci::closeBtHci() {
+ if (bt_soc_fd_ != -1) {
+ ::close(bt_soc_fd_);
+ bt_soc_fd_ = -1;
+ }
+ rfKill(0);
+ free(rfkill_state_);
+}
+
+int BluetoothHci::waitHciDev(int hci_interface) {
+ struct sockaddr_hci addr;
+ struct pollfd fds[1];
+ struct mgmt_pkt ev;
+ int fd;
+ int ret = 0;
+
+ ALOGI( "%s", __func__);
+ fd = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (fd < 0) {
+ ALOGE( "Bluetooth socket error: %s", strerror(errno));
+ return -1;
+ }
+ memset(&addr, 0, sizeof(addr));
+ addr.hci_family = AF_BLUETOOTH;
+ addr.hci_dev = HCI_DEV_NONE;
+ addr.hci_channel = HCI_CHANNEL_CONTROL;
+ if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
+ ALOGE( "HCI Channel Control: %s", strerror(errno));
+ ret = -1;
+ goto end;
+ }
+
+ fds[0].fd = fd;
+ fds[0].events = POLLIN;
+
+ /* Read Controller Index List Command */
+ ev.opcode = MGMT_OP_INDEX_LIST;
+ ev.index = HCI_DEV_NONE;
+ ev.len = 0;
+
+ ssize_t wrote;
+ WRITE_NO_INTR(wrote = write(fd, &ev, 6));
+ if (wrote != 6) {
+ ALOGE( "Unable to write mgmt command: %s", strerror(errno));
+ ret = -1;
+ goto end;
+ }
+ /* validate mentioned hci interface is present and registered with sock system */
+ while (1) {
+ int n;
+ WRITE_NO_INTR(n = poll(fds, 1, MGMT_EV_POLL_TIMEOUT));
+ if (n == -1) {
+ ALOGE( "Poll error: %s", strerror(errno));
+ ret = -1;
+ break;
+ } else if (n == 0) {
+ ALOGE( "Timeout, no HCI device detected");
+ ret = -1;
+ break;
+ }
+
+ if (fds[0].revents & POLLIN) {
+ WRITE_NO_INTR(n = read(fd, &ev, sizeof(struct mgmt_pkt)));
+ if (n < 0) {
+ ALOGE( "Error reading control channel: %s",
+ strerror(errno));
+ ret = -1;
+ break;
+ }
+
+ if (ev.opcode == MGMT_EV_INDEX_ADDED && ev.index == hci_interface) {
+ goto end;
+ } else if (ev.opcode == MGMT_EV_COMMAND_COMP) {
+ struct mgmt_event_read_index* cc;
+ int i;
+
+ cc = (struct mgmt_event_read_index*)ev.data;
+
+ if (cc->cc_opcode != MGMT_OP_INDEX_LIST || cc->status != 0) continue;
+
+ for (i = 0; i < cc->num_intf; i++) {
+ if (cc->index[i] == hci_interface) goto end;
+ }
+ }
+ }
+ }
+
+end:
+ ::close(fd);
+ return ret;
+}
+
+int BluetoothHci::findRfKill() {
+ char rfkill_type[64];
+ char type[16];
+ int fd, size, i;
+ for(i = 0; rfkill_state_ == NULL; i++)
+ {
+ snprintf(rfkill_type, sizeof(rfkill_type), "/sys/class/rfkill/rfkill%d/type", i);
+ if ((fd = open(rfkill_type, O_RDONLY)) < 0)
+ {
+ ALOGE("open(%s) failed: %s (%d)\n", rfkill_type, strerror(errno), errno);
+ return -1;
+ }
+
+ size = read(fd, &type, sizeof(type));
+ ::close(fd);
+
+ if ((size >= 9) && !memcmp(type, "bluetooth", 9))
+ {
+ ::asprintf(&rfkill_state_, "/sys/class/rfkill/rfkill%d/state", i);
+ break;
+ }
+ }
+ return 0;
+}
+
+int BluetoothHci::rfKill(int block) {
+ int fd;
+ char on = (block)?'1':'0';
+ if (findRfKill() != 0) return 0;
+
+ fd = open(rfkill_state_, O_WRONLY);
+ if (fd < 0) {
+ ALOGE( "Unable to open /dev/rfkill");
+ return -1;
+ }
+ ssize_t len;
+ WRITE_NO_INTR(len = write(fd, &on, 1));
+ if (len < 0) {
+ ALOGE( "Failed to change rfkill state");
+ ::close(fd);
+ return -1;
+ }
+ ::close(fd);
+ return 0;
+}
+
+class BluetoothDeathRecipient : public hidl_death_recipient {
+ public:
+ BluetoothDeathRecipient(const sp<IBluetoothHci> hci) : mHci(hci) {}
+
+ virtual void serviceDied(
+ uint64_t /*cookie*/,
+ const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
+ ALOGE("BluetoothDeathRecipient::serviceDied - Bluetooth service died");
+ has_died_ = true;
+ mHci->close();
+ }
+ sp<IBluetoothHci> mHci;
+ bool getHasDied() const { return has_died_; }
+ void setHasDied(bool has_died) { has_died_ = has_died; }
+
+ private:
+ bool has_died_;
+};
+
+BluetoothHci::BluetoothHci()
+ : death_recipient_(new BluetoothDeathRecipient(this)) {}
+
+Return<void> BluetoothHci::initialize(
+ const ::android::sp<IBluetoothHciCallbacks>& cb) {
+ ALOGI("BluetoothHci::initialize()");
+ if (cb == nullptr) {
+ ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
+ return Void();
+ }
+
+ death_recipient_->setHasDied(false);
+ cb->linkToDeath(death_recipient_, 0);
+ int hci_fd = openBtHci();
+ auto hidl_status = cb->initializationComplete(
+ hci_fd > 0 ? Status::SUCCESS : Status::INITIALIZATION_ERROR);
+ if (!hidl_status.isOk()) {
+ ALOGE("VendorInterface -> Unable to call initializationComplete(ERR)");
+ }
+ hci::H4Protocol* h4_hci = new hci::H4Protocol(
+ hci_fd,
+ [cb](const hidl_vec<uint8_t>& packet) { cb->hciEventReceived(packet); },
+ [cb](const hidl_vec<uint8_t>& packet) { cb->aclDataReceived(packet); },
+ [cb](const hidl_vec<uint8_t>& packet) { cb->scoDataReceived(packet); });
+
+ fd_watcher_.WatchFdForNonBlockingReads(
+ hci_fd, [h4_hci](int fd) { h4_hci->OnDataReady(fd); });
+ hci_handle_ = h4_hci;
+
+ unlink_cb_ = [cb](sp<BluetoothDeathRecipient>& death_recipient) {
+ if (death_recipient->getHasDied())
+ ALOGI("Skipping unlink call, service died.");
+ else
+ cb->unlinkToDeath(death_recipient);
+ };
+
+ return Void();
+}
+
+Return<void> BluetoothHci::close() {
+ ALOGI("BluetoothHci::close()");
+ unlink_cb_(death_recipient_);
+ fd_watcher_.StopWatchingFileDescriptors();
+
+ if (hci_handle_ != nullptr) {
+ delete hci_handle_;
+ hci_handle_ = nullptr;
+ }
+ closeBtHci();
+ return Void();
+}
+
+Return<void> BluetoothHci::sendHciCommand(const hidl_vec<uint8_t>& command) {
+ sendDataToController(HCI_DATA_TYPE_COMMAND, command);
+ return Void();
+}
+
+Return<void> BluetoothHci::sendAclData(const hidl_vec<uint8_t>& data) {
+ sendDataToController(HCI_DATA_TYPE_ACL, data);
+ return Void();
+}
+
+Return<void> BluetoothHci::sendScoData(const hidl_vec<uint8_t>& data) {
+ sendDataToController(HCI_DATA_TYPE_SCO, data);
+ return Void();
+}
+
+void BluetoothHci::sendDataToController(const uint8_t type,
+ const hidl_vec<uint8_t>& data) {
+ hci_handle_->Send(type, data.data(), data.size());
+}
+
+IBluetoothHci* HIDL_FETCH_IBluetoothHci(const char* /* name */) {
+ return new BluetoothHci();
+}
+
+} // namespace btlinux
+} // namespace V1_0
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
--- /dev/null
+//
+// Copyright 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef HIDL_GENERATED_android_hardware_bluetooth_V1_0_BluetoothHci_H_
+#define HIDL_GENERATED_android_hardware_bluetooth_V1_0_BluetoothHci_H_
+
+#include <android/hardware/bluetooth/1.0/IBluetoothHci.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include "async_fd_watcher.h"
+#include "h4_protocol.h"
+#include "hci_internals.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace V1_0 {
+namespace btlinux {
+
+using ::android::hardware::Return;
+using ::android::hardware::hidl_vec;
+
+class BluetoothDeathRecipient;
+
+class BluetoothHci : public IBluetoothHci {
+ public:
+ BluetoothHci();
+ Return<void> initialize(
+ const ::android::sp<IBluetoothHciCallbacks>& cb) override;
+ Return<void> sendHciCommand(const hidl_vec<uint8_t>& packet) override;
+ Return<void> sendAclData(const hidl_vec<uint8_t>& data) override;
+ Return<void> sendScoData(const hidl_vec<uint8_t>& data) override;
+ Return<void> close() override;
+
+ private:
+ async::AsyncFdWatcher fd_watcher_;
+ hci::H4Protocol* hci_handle_;
+ int bt_soc_fd_;
+ char *rfkill_state_;
+
+ const uint8_t HCI_DATA_TYPE_COMMAND = 1;
+ const uint8_t HCI_DATA_TYPE_ACL = 2;
+ const uint8_t HCI_DATA_TYPE_SCO = 3;
+
+ int waitHciDev(int hci_interface);
+ int findRfKill(void);
+ int rfKill(int block);
+ int openBtHci(void);
+ void closeBtHci(void);
+
+ void sendDataToController(const uint8_t type, const hidl_vec<uint8_t>& data);
+ ::android::sp<BluetoothDeathRecipient> death_recipient_;
+ std::function<void(sp<BluetoothDeathRecipient>&)> unlink_cb_;
+};
+
+extern "C" IBluetoothHci* HIDL_FETCH_IBluetoothHci(const char* name);
+
+} // namespace btlinux
+} // namespace V1_0
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
+
+#endif // HIDL_GENERATED_android_hardware_bluetooth_V1_0_BluetoothHci_H_
--- /dev/null
+//
+// Copyright 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "h4_protocol.h"
+
+#define LOG_TAG "android.hardware.bluetooth-hci-h4"
+#include <android-base/logging.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace hci {
+
+size_t H4Protocol::Send(uint8_t type, const uint8_t* data, size_t length) {
+ /* For HCI communication over USB dongle, multiple write results in
+ * response timeout as driver expect type + data at once to process
+ * the command, so using "writev"(for atomicity) here.
+ */
+ struct iovec iov[2];
+ ssize_t ret = 0;
+ iov[0].iov_base = &type;
+ iov[0].iov_len = sizeof(type);
+ iov[1].iov_base = (void *)data;
+ iov[1].iov_len = length;
+ while (1) {
+ ret = TEMP_FAILURE_RETRY(writev(uart_fd_, iov, 2));
+ if (ret == -1) {
+ if (errno == EAGAIN) {
+ ALOGE("%s error writing to UART (%s)", __func__, strerror(errno));
+ continue;
+ }
+ } else if (ret == 0) {
+ // Nothing written :(
+ ALOGE("%s zero bytes written - something went wrong...", __func__);
+ break;
+ }
+ break;
+ }
+ return ret;
+}
+
+void H4Protocol::OnPacketReady() {
+ switch (hci_packet_type_) {
+ case HCI_PACKET_TYPE_EVENT:
+ event_cb_(hci_packetizer_.GetPacket());
+ break;
+ case HCI_PACKET_TYPE_ACL_DATA:
+ acl_cb_(hci_packetizer_.GetPacket());
+ break;
+ case HCI_PACKET_TYPE_SCO_DATA:
+ sco_cb_(hci_packetizer_.GetPacket());
+ break;
+ default: {
+ bool bad_packet_type = true;
+ CHECK(!bad_packet_type);
+ }
+ }
+ // Get ready for the next type byte.
+ hci_packet_type_ = HCI_PACKET_TYPE_UNKNOWN;
+}
+
+void H4Protocol::OnDataReady(int fd) {
+ if (hci_packet_type_ == HCI_PACKET_TYPE_UNKNOWN) {
+ /**
+ * read full buffer. ACL max length is 2 bytes, and SCO max length is 2
+ * byte. so taking 64K as buffer length.
+ * Question : Why to read in single chunk rather than multiple reads,
+ * which can give parameter length arriving in response ?
+ * Answer: The multiple reads does not work with BT USB dongle. At least
+ * with Bluetooth 2.0 supported USB dongle. After first read, either
+ * firmware/kernel (do not know who is responsible - inputs ??) driver
+ * discard the whole message and successive read results in forever
+ * blocking loop. - Is there any other way to make it work with multiple
+ * reads, do not know yet (it can eliminate need of this function) ?
+ * Reading in single shot gives expected response.
+ */
+ const size_t max_plen = 64*1024;
+ hidl_vec<uint8_t> tpkt;
+ tpkt.resize(max_plen);
+ size_t bytes_read = TEMP_FAILURE_RETRY(read(fd, tpkt.data(), max_plen));
+ hci_packet_type_ = static_cast<HciPacketType>(tpkt.data()[0]);
+ hci_packetizer_.CbHciPacket(tpkt.data()+1, bytes_read-1);
+ }
+}
+
+} // namespace hci
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
--- /dev/null
+//
+// Copyright 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#pragma once
+
+#include <hidl/HidlSupport.h>
+
+#include "async_fd_watcher.h"
+#include "hci_internals.h"
+#include "hci_packetizer.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace hci {
+
+using ::android::hardware::hidl_vec;
+using PacketReadCallback = std::function<void(const hidl_vec<uint8_t>&)>;
+
+class H4Protocol {
+ public:
+ H4Protocol(int fd, PacketReadCallback event_cb, PacketReadCallback acl_cb,
+ PacketReadCallback sco_cb)
+ : uart_fd_(fd),
+ event_cb_(event_cb),
+ acl_cb_(acl_cb),
+ sco_cb_(sco_cb),
+ hci_packetizer_([this]() { OnPacketReady(); }) {}
+
+ size_t Send(uint8_t type, const uint8_t* data, size_t length);
+
+ void OnPacketReady();
+
+ void OnDataReady(int fd);
+
+ private:
+ int uart_fd_;
+
+ PacketReadCallback event_cb_;
+ PacketReadCallback acl_cb_;
+ PacketReadCallback sco_cb_;
+
+ HciPacketType hci_packet_type_{HCI_PACKET_TYPE_UNKNOWN};
+ HciPacketizer hci_packetizer_;
+};
+
+} // namespace hci
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
--- /dev/null
+//
+// Copyright 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#pragma once
+
+#include <stdlib.h>
+
+// HCI UART transport packet types (Volume 4, Part A, 2)
+enum HciPacketType {
+ HCI_PACKET_TYPE_UNKNOWN = 0,
+ HCI_PACKET_TYPE_COMMAND = 1,
+ HCI_PACKET_TYPE_ACL_DATA = 2,
+ HCI_PACKET_TYPE_SCO_DATA = 3,
+ HCI_PACKET_TYPE_EVENT = 4
+};
+
+// 2 bytes for opcode, 1 byte for parameter length (Volume 2, Part E, 5.4.1)
+const size_t HCI_COMMAND_PREAMBLE_SIZE = 3;
+const size_t HCI_LENGTH_OFFSET_CMD = 2;
+
+// 2 bytes for handle, 2 bytes for data length (Volume 2, Part E, 5.4.2)
+const size_t HCI_ACL_PREAMBLE_SIZE = 4;
+const size_t HCI_LENGTH_OFFSET_ACL = 2;
+
+// 2 bytes for handle, 1 byte for data length (Volume 2, Part E, 5.4.3)
+const size_t HCI_SCO_PREAMBLE_SIZE = 3;
+const size_t HCI_LENGTH_OFFSET_SCO = 2;
+
+// 1 byte for event code, 1 byte for parameter length (Volume 2, Part E, 5.4.4)
+const size_t HCI_EVENT_PREAMBLE_SIZE = 2;
+const size_t HCI_LENGTH_OFFSET_EVT = 1;
+
+const size_t HCI_PREAMBLE_SIZE_MAX = HCI_ACL_PREAMBLE_SIZE;
+
+// Event codes (Volume 2, Part E, 7.7.14)
+const uint8_t HCI_COMMAND_COMPLETE_EVENT = 0x0E;
--- /dev/null
+//
+// Copyright 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "hci_packetizer.h"
+
+#define LOG_TAG "android.hardware.bluetooth.hci_packetizer"
+#include <android-base/logging.h>
+#include <utils/Log.h>
+
+#include <dlfcn.h>
+#include <fcntl.h>
+
+namespace {
+
+const size_t preamble_size_for_type[] = {
+ 0, HCI_COMMAND_PREAMBLE_SIZE, HCI_ACL_PREAMBLE_SIZE, HCI_SCO_PREAMBLE_SIZE,
+ HCI_EVENT_PREAMBLE_SIZE};
+const size_t packet_length_offset_for_type[] = {
+ 0, HCI_LENGTH_OFFSET_CMD, HCI_LENGTH_OFFSET_ACL, HCI_LENGTH_OFFSET_SCO,
+ HCI_LENGTH_OFFSET_EVT};
+
+size_t HciGetPacketLengthForType(HciPacketType type, const uint8_t* preamble) {
+ size_t offset = packet_length_offset_for_type[type];
+ if (type != HCI_PACKET_TYPE_ACL_DATA) return preamble[offset];
+ return (((preamble[offset + 1]) << 8) | preamble[offset]);
+}
+
+} // namespace
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace hci {
+
+const hidl_vec<uint8_t>& HciPacketizer::GetPacket() const { return packet_; }
+
+void HciPacketizer::CbHciPacket(uint8_t *data, size_t len) {
+ packet_.setToExternal(data, len);
+ packet_ready_cb_();
+}
+
+void HciPacketizer::OnDataReady(int fd, HciPacketType packet_type) {
+ switch (state_) {
+ case HCI_PREAMBLE: {
+ size_t bytes_read = TEMP_FAILURE_RETRY(
+ read(fd, preamble_ + bytes_read_,
+ preamble_size_for_type[packet_type] - bytes_read_));
+ CHECK(bytes_read > 0);
+ bytes_read_ += bytes_read;
+ if (bytes_read_ == preamble_size_for_type[packet_type]) {
+ size_t packet_length =
+ HciGetPacketLengthForType(packet_type, preamble_);
+ packet_.resize(preamble_size_for_type[packet_type] + packet_length);
+ memcpy(packet_.data(), preamble_, preamble_size_for_type[packet_type]);
+ bytes_remaining_ = packet_length;
+ state_ = HCI_PAYLOAD;
+ bytes_read_ = 0;
+ }
+ break;
+ }
+
+ case HCI_PAYLOAD: {
+ size_t bytes_read = TEMP_FAILURE_RETRY(read(
+ fd,
+ packet_.data() + preamble_size_for_type[packet_type] + bytes_read_,
+ bytes_remaining_));
+ CHECK(bytes_read > 0);
+ bytes_remaining_ -= bytes_read;
+ bytes_read_ += bytes_read;
+ if (bytes_remaining_ == 0) {
+ packet_ready_cb_();
+ state_ = HCI_PREAMBLE;
+ bytes_read_ = 0;
+ }
+ break;
+ }
+ }
+}
+
+} // namespace hci
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
--- /dev/null
+//
+// Copyright 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#pragma once
+
+#include <functional>
+
+#include <hidl/HidlSupport.h>
+
+#include "hci_internals.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace hci {
+
+using ::android::hardware::hidl_vec;
+using HciPacketReadyCallback = std::function<void(void)>;
+
+class HciPacketizer {
+ public:
+ HciPacketizer(HciPacketReadyCallback packet_cb)
+ : packet_ready_cb_(packet_cb){};
+ void OnDataReady(int fd, HciPacketType packet_type);
+ void CbHciPacket(uint8_t* data, size_t length);
+ const hidl_vec<uint8_t>& GetPacket() const;
+
+ protected:
+ enum State { HCI_PREAMBLE, HCI_PAYLOAD };
+ State state_{HCI_PREAMBLE};
+ uint8_t preamble_[HCI_PREAMBLE_SIZE_MAX];
+ hidl_vec<uint8_t> packet_;
+ size_t bytes_remaining_{0};
+ size_t bytes_read_{0};
+ HciPacketReadyCallback packet_ready_cb_;
+};
+
+} // namespace hci
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
--- /dev/null
+//
+// Copyright 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#define LOG_TAG "android.hardware.bluetooth@1.0-service.btlinux"
+
+#include <android/hardware/bluetooth/1.0/IBluetoothHci.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <utils/Log.h>
+
+#include "bluetooth_hci.h"
+
+using ::android::hardware::configureRpcThreadpool;
+using ::android::hardware::bluetooth::V1_0::IBluetoothHci;
+using ::android::hardware::bluetooth::V1_0::btlinux::BluetoothHci;
+using ::android::hardware::joinRpcThreadpool;
+using ::android::sp;
+
+int main(int /* argc */, char** /* argv */) {
+ sp<IBluetoothHci> bluetooth = new BluetoothHci;
+ configureRpcThreadpool(1, true);
+ android::status_t status = bluetooth->registerAsService();
+ if (status == android::OK)
+ joinRpcThreadpool();
+ else
+ ALOGE("Could not register as a service!");
+}
--- /dev/null
+/sys/class/rfkill/rfkill[0-9]/state u:object_r:sysfs_bluetooth_writable:s0
+/system/vendor/bin/hw/android\.hardware\.bluetooth@1\.0-service\.btlinux u:object_r:hal_bluetooth_btlinux_exec:s0
--- /dev/null
+type hal_bluetooth_btlinux, domain;
+type hal_bluetooth_btlinux_exec, exec_type, file_type;
+
+hal_server_domain(hal_bluetooth_btlinux, hal_bluetooth)
+init_daemon_domain(hal_bluetooth_btlinux)
+
+allow hal_bluetooth_btlinux self:socket { create bind read write };
+allow hal_bluetooth_btlinux self:bluetooth_socket { create bind read write };