Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c6a9e9c0 authored by Jakub Pawlowski's avatar Jakub Pawlowski
Browse files

Move Android specific HCI code into separate file

Test: manual
Change-Id: I0a99e528acaa1adec39425b7bf6f8d8b5c024632
parent e00c8bcf
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ cc_library_static {
        "src/hci_audio.cc",
        "src/hci_inject.cc",
        "src/hci_layer.cc",
        "src/hci_layer_android.cc",
        "src/hci_packet_factory.cc",
        "src/hci_packet_parser.cc",
        "src/packet_fragmenter.cc",
+23 −88
Original line number Diff line number Diff line
@@ -20,17 +20,11 @@

#include "hci_layer.h"

#include <android/hardware/bluetooth/1.0/IBluetoothHci.h>
#include <android/hardware/bluetooth/1.0/IBluetoothHciCallbacks.h>
#include <android/hardware/bluetooth/1.0/types.h>
#include <base/logging.h>
#include <hwbinder/ProcessState.h>

#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

#include <mutex>

#include "btcore/include/module.h"
@@ -49,17 +43,9 @@

#define BT_HCI_TIMEOUT_TAG_NUM 1010000

using android::hardware::bluetooth::V1_0::IBluetoothHci;
using android::hardware::bluetooth::V1_0::IBluetoothHciCallbacks;
using android::hardware::bluetooth::V1_0::HciPacket;
using android::hardware::bluetooth::V1_0::Status;
using android::hardware::ProcessState;

android::sp<IBluetoothHci> btHci;

using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
extern void hci_initialize();
extern void hci_transmit(BT_HDR* packet);
extern void hci_close();

typedef struct {
  uint16_t opcode;
@@ -123,52 +109,28 @@ static void fragmenter_transmit_finished(BT_HDR* packet,
static const packet_fragmenter_callbacks_t packet_fragmenter_callbacks = {
    transmit_fragment, dispatch_reassembled, fragmenter_transmit_finished};

class BluetoothHciCallbacks : public IBluetoothHciCallbacks {
  BT_HDR* WrapPacketAndCopy(uint16_t event, const hidl_vec<uint8_t>& data) {
    size_t packet_size = data.size() + BT_HDR_SIZE;
    BT_HDR* packet =
        reinterpret_cast<BT_HDR*>(buffer_allocator->alloc(packet_size));
    packet->offset = 0;
    packet->len = data.size();
    packet->layer_specific = 0;
    packet->event = event;
    // TODO(eisenbach): Avoid copy here; if BT_HDR->data can be ensured to
    // be the only way the data is accessed, a pointer could be passed here...
    memcpy(packet->data, data.data(), data.size());
    return packet;
  }

  Return<void> initializationComplete(Status status) {
    CHECK(status == Status::SUCCESS);
void initialization_complete() {
  thread_post(thread, event_finish_startup, NULL);
    return Void();
}

  Return<void> hciEventReceived(const hidl_vec<uint8_t>& event) {
    BT_HDR* packet = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_EVT, event);
void hci_event_received(BT_HDR* packet) {
  btsnoop->capture(packet, true);

  if (!filter_incoming_event(packet)) {
      data_dispatcher_dispatch(interface.event_dispatcher, event[0], packet);
    data_dispatcher_dispatch(interface.event_dispatcher, packet->data[0],
                             packet);
  }

    return Void();
}

  Return<void> aclDataReceived(const hidl_vec<uint8_t>& data) {
    BT_HDR* packet = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_ACL, data);
void acl_event_received(BT_HDR* packet) {
  btsnoop->capture(packet, true);
  packet_fragmenter->reassemble_and_dispatch(packet);
    return Void();
}

  Return<void> scoDataReceived(const hidl_vec<uint8_t>& data) {
    BT_HDR* packet = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_SCO, data);
void sco_data_received(BT_HDR* packet) {
  btsnoop->capture(packet, true);
  packet_fragmenter->reassemble_and_dispatch(packet);
    return Void();
}
};

// Module lifecycle functions

@@ -244,17 +206,7 @@ static future_t* hci_module_start_up(void) {
  fixed_queue_register_dequeue(packet_queue, thread_get_reactor(thread),
                               event_packet_ready, NULL);

  btHci = IBluetoothHci::getService();
  // If android.hardware.bluetooth* is not found, Bluetooth can not continue.
  CHECK(btHci != nullptr);
  LOG_INFO(LOG_TAG, "%s: IBluetoothHci::getService() returned %p (%s)",
            __func__, btHci.get(), (btHci->isRemote() ? "remote" : "local"));

  // Block allows allocation of a variable that might be bypassed by goto.
  {
    android::sp<IBluetoothHciCallbacks> callbacks = new BluetoothHciCallbacks();
    btHci->initialize(callbacks);
  }
  hci_initialize();

  LOG_DEBUG(LOG_TAG, "%s starting async portion", __func__);
  return local_startup_future;
@@ -287,8 +239,7 @@ static future_t* hci_module_shut_down() {
  alarm_free(startup_timer);
  startup_timer = NULL;

  btHci->close();
  btHci = nullptr;
  hci_close();

  thread_free(thread);
  thread = NULL;
@@ -410,25 +361,9 @@ static void event_packet_ready(fixed_queue_t* queue,
static void transmit_fragment(BT_HDR* packet, bool send_transmit_finished) {
  btsnoop->capture(packet, false);

  HciPacket data;
  data.setToExternal(packet->data + packet->offset, packet->len);
  hci_transmit(packet);

  uint16_t event = packet->event & MSG_EVT_MASK;
  switch (event & MSG_EVT_MASK) {
    case MSG_STACK_TO_HC_HCI_CMD:
      btHci->sendHciCommand(data);
      break;
    case MSG_STACK_TO_HC_HCI_ACL:
      btHci->sendAclData(data);
      break;
    case MSG_STACK_TO_HC_HCI_SCO:
      btHci->sendScoData(data);
      break;
    default:
      LOG_ERROR(LOG_TAG, "Unknown packet type (%d)", event);
      break;
  }

  if (event != MSG_STACK_TO_HC_HCI_CMD && send_transmit_finished)
    buffer_allocator->free(packet);
}
+133 −0
Original line number Diff line number Diff line
/******************************************************************************
 *
 *  Copyright (C) 2017 Google, Inc.
 *
 *  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_hci"

#include "hci_layer.h"

#include <base/logging.h>
#include "buffer_allocator.h"
#include "osi/include/log.h"

#include <android/hardware/bluetooth/1.0/IBluetoothHci.h>
#include <android/hardware/bluetooth/1.0/IBluetoothHciCallbacks.h>
#include <android/hardware/bluetooth/1.0/types.h>
#include <hwbinder/ProcessState.h>

using android::hardware::bluetooth::V1_0::IBluetoothHci;
using android::hardware::bluetooth::V1_0::IBluetoothHciCallbacks;
using android::hardware::bluetooth::V1_0::HciPacket;
using android::hardware::bluetooth::V1_0::Status;
using android::hardware::ProcessState;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;

extern void initialization_complete();
extern void hci_event_received(BT_HDR* packet);
extern void acl_event_received(BT_HDR* packet);
extern void sco_data_received(BT_HDR* packet);

android::sp<IBluetoothHci> btHci;

class BluetoothHciCallbacks : public IBluetoothHciCallbacks {
 public:
  BluetoothHciCallbacks() {
    buffer_allocator = buffer_allocator_get_interface();
  }

  BT_HDR* WrapPacketAndCopy(uint16_t event, const hidl_vec<uint8_t>& data) {
    size_t packet_size = data.size() + BT_HDR_SIZE;
    BT_HDR* packet =
        reinterpret_cast<BT_HDR*>(buffer_allocator->alloc(packet_size));
    packet->offset = 0;
    packet->len = data.size();
    packet->layer_specific = 0;
    packet->event = event;
    // TODO(eisenbach): Avoid copy here; if BT_HDR->data can be ensured to
    // be the only way the data is accessed, a pointer could be passed here...
    memcpy(packet->data, data.data(), data.size());
    return packet;
  }

  Return<void> initializationComplete(Status status) {
    CHECK(status == Status::SUCCESS);
    initialization_complete();
    return Void();
  }

  Return<void> hciEventReceived(const hidl_vec<uint8_t>& event) {
    BT_HDR* packet = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_EVT, event);
    hci_event_received(packet);
    return Void();
  }

  Return<void> aclDataReceived(const hidl_vec<uint8_t>& data) {
    BT_HDR* packet = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_ACL, data);
    acl_event_received(packet);
    return Void();
  }

  Return<void> scoDataReceived(const hidl_vec<uint8_t>& data) {
    BT_HDR* packet = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_SCO, data);
    sco_data_received(packet);
    return Void();
  }

  const allocator_t* buffer_allocator;
};

void hci_initialize() {
  btHci = IBluetoothHci::getService();
  // If android.hardware.bluetooth* is not found, Bluetooth can not continue.
  CHECK(btHci != nullptr);
  LOG_INFO(LOG_TAG, "%s: IBluetoothHci::getService() returned %p (%s)",
           __func__, btHci.get(), (btHci->isRemote() ? "remote" : "local"));

  // Block allows allocation of a variable that might be bypassed by goto.
  {
    android::sp<IBluetoothHciCallbacks> callbacks = new BluetoothHciCallbacks();
    btHci->initialize(callbacks);
  }
}

void hci_close() {
  btHci->close();
  btHci = nullptr;
}

void hci_transmit(BT_HDR* packet) {
  HciPacket data;
  data.setToExternal(packet->data + packet->offset, packet->len);

  uint16_t event = packet->event & MSG_EVT_MASK;
  switch (event & MSG_EVT_MASK) {
    case MSG_STACK_TO_HC_HCI_CMD:
      btHci->sendHciCommand(data);
      break;
    case MSG_STACK_TO_HC_HCI_ACL:
      btHci->sendAclData(data);
      break;
    case MSG_STACK_TO_HC_HCI_SCO:
      btHci->sendScoData(data);
      break;
    default:
      LOG_ERROR(LOG_TAG, "Unknown packet type (%d)", event);
      break;
  }
}
 No newline at end of file