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

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

HCI interface improvements

This patch improves btu_hcif_send_cmd_with_cb, which will accept
base::Callback instead of function pointer as argument. It will also
carry information about where was packet send from, which can be
displayed when command status is received, greatly improving logs.

The improved method is also used for handling VSC advertising.

Bug: 30622771
Test: sl4a ConcurrentBleAdvertiserTest
Change-Id: I55c3e32f9231c00bfa85f971265809d6f1fecdfb
parent bc9a6dbe
Loading
Loading
Loading
Loading
+55 −77
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#include "ble_advertiser_hci_interface.h"
#include <base/callback.h>
#include <base/location.h>
#include <base/logging.h>
#include <queue>
#include <utility>
@@ -39,48 +40,45 @@

using status_cb = BleAdvertiserHciInterface::status_cb;

typedef void (*hci_cmd_complete_cb)(uint16_t opcode, uint8_t* return_parameters,
                                    uint16_t return_parameters_length);
extern void btu_hcif_send_cmd_with_cb(uint16_t opcode, uint8_t* params,
                                      uint8_t params_len,
                                      hci_cmd_complete_cb cb);
using hci_cmd_cb = base::Callback<void(uint8_t* /* return_parameters */,
                                       uint16_t /* return_parameters_length*/)>;
extern void btu_hcif_send_cmd_with_cb(
    const tracked_objects::Location& posted_from, uint16_t opcode,
    uint8_t* params, uint8_t params_len, hci_cmd_cb cb);

namespace {
BleAdvertiserHciInterface* instance = nullptr;
std::queue<std::pair<uint8_t, status_cb>>* pending_ops = nullptr;

void btm_ble_multi_adv_vsc_cmpl_cback(tBTM_VSC_CMPL* p_params) {
void btm_ble_multi_adv_vsc_cmpl_cback(uint8_t expected_opcode,
                                      status_cb command_complete,
                                      uint8_t* param, uint16_t param_len) {
  uint8_t status, subcode;
  uint8_t* p = p_params->p_param_buf;
  uint16_t len = p_params->param_len;

  // All multi-adv commands respond with status and inst_id.
  LOG_ASSERT(len == 2) << "Received bad response length to multi-adv VSC";
  LOG_ASSERT(param_len == 2) << "Received bad response length to multi-adv VSC";

  STREAM_TO_UINT8(status, p);
  STREAM_TO_UINT8(subcode, p);
  STREAM_TO_UINT8(status, param);
  STREAM_TO_UINT8(subcode, param);

  VLOG(1) << "subcode = " << +subcode << ", status: " << +status;

  auto pending_op = pending_ops->front();
  uint8_t opcode = pending_op.first;
  pending_ops->pop();

  if (opcode != subcode) {
  if (expected_opcode != subcode) {
    LOG(ERROR) << "unexpected VSC cmpl, expect: " << +subcode
               << " get: " << +opcode;
               << " get: " << +expected_opcode;
    return;
  }

  pending_op.second.Run(status);
  command_complete.Run(status);
}

class BleAdvertiserVscHciInterfaceImpl : public BleAdvertiserHciInterface {
  void SendVscMultiAdvCmd(uint8_t param_len, uint8_t* param_buf,
  void SendAdvCmd(const tracked_objects::Location& posted_from,
                  uint8_t param_len, uint8_t* param_buf,
                  status_cb command_complete) {
    BTM_VendorSpecificCommand(HCI_BLE_MULTI_ADV_OCF, param_len, param_buf,
                              btm_ble_multi_adv_vsc_cmpl_cback);
    pending_ops->push(std::make_pair(param_buf[0], command_complete));
    btu_hcif_send_cmd_with_cb(posted_from, HCI_BLE_MULTI_ADV_OCF, param_buf,
                              param_len,
                              base::Bind(&btm_ble_multi_adv_vsc_cmpl_cback,
                                         param_buf[0], command_complete));
  }

  void ReadInstanceCount(
@@ -134,7 +132,7 @@ class BleAdvertiserVscHciInterfaceImpl : public BleAdvertiserHciInterface {
    UINT8_TO_STREAM(pp, handle);
    INT8_TO_STREAM(pp, tx_power);

    SendVscMultiAdvCmd(BTM_BLE_MULTI_ADV_SET_PARAM_LEN, param,
    SendAdvCmd(FROM_HERE, BTM_BLE_MULTI_ADV_SET_PARAM_LEN, param,
               command_complete);
  }

@@ -151,7 +149,7 @@ class BleAdvertiserVscHciInterfaceImpl : public BleAdvertiserHciInterface {
    ARRAY_TO_STREAM(pp, data, data_length);
    param[BTM_BLE_MULTI_ADV_WRITE_DATA_LEN - 1] = handle;

    SendVscMultiAdvCmd((uint8_t)BTM_BLE_MULTI_ADV_WRITE_DATA_LEN, param,
    SendAdvCmd(FROM_HERE, (uint8_t)BTM_BLE_MULTI_ADV_WRITE_DATA_LEN, param,
               command_complete);
  }

@@ -170,7 +168,7 @@ class BleAdvertiserVscHciInterfaceImpl : public BleAdvertiserHciInterface {
    ARRAY_TO_STREAM(pp, scan_response_data, scan_response_data_length);
    param[BTM_BLE_MULTI_ADV_WRITE_DATA_LEN - 1] = handle;

    SendVscMultiAdvCmd((uint8_t)BTM_BLE_MULTI_ADV_WRITE_DATA_LEN, param,
    SendAdvCmd(FROM_HERE, (uint8_t)BTM_BLE_MULTI_ADV_WRITE_DATA_LEN, param,
               command_complete);
  }

@@ -185,7 +183,7 @@ class BleAdvertiserVscHciInterfaceImpl : public BleAdvertiserHciInterface {
    BDADDR_TO_STREAM(pp, random_address);
    UINT8_TO_STREAM(pp, handle);

    SendVscMultiAdvCmd((uint8_t)BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN, param,
    SendAdvCmd(FROM_HERE, (uint8_t)BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN, param,
               command_complete);
  }

@@ -201,7 +199,7 @@ class BleAdvertiserVscHciInterfaceImpl : public BleAdvertiserHciInterface {
    UINT8_TO_STREAM(pp, enable);
    UINT8_TO_STREAM(pp, handle);

    SendVscMultiAdvCmd((uint8_t)BTM_BLE_MULTI_ADV_ENB_LEN, param,
    SendAdvCmd(FROM_HERE, (uint8_t)BTM_BLE_MULTI_ADV_ENB_LEN, param,
               command_complete);
  }

@@ -236,33 +234,19 @@ class BleAdvertiserVscHciInterfaceImpl : public BleAdvertiserHciInterface {
  AdvertisingEventObserver* advertising_event_observer = nullptr;
};

std::queue<std::pair<uint16_t, status_cb>>* legacy_pending_ops = nullptr;
void adv_cmd_cmpl_cback(uint16_t opcode, uint8_t* return_parameters,
void adv_cmd_cmpl_cback(status_cb cb, uint8_t* return_parameters,
                        uint16_t return_parameters_length) {
  uint8_t status = *return_parameters;

  VLOG(1) << "opcode = " << +opcode << ", status: " << +status;

  auto pending_op = legacy_pending_ops->front();
  uint16_t pending_opc_opcode = pending_op.first;
  legacy_pending_ops->pop();

  if (opcode != pending_opc_opcode) {
    LOG(ERROR) << "unexpected command complete, expect: " << +pending_opc_opcode
               << " get: " << +opcode;
    return;
  }

  pending_op.second.Run(status);
  cb.Run(status);
}

class BleAdvertiserLegacyHciInterfaceImpl : public BleAdvertiserHciInterface {
  void SendAdvCmd(uint16_t opcode, uint8_t* param_buf, uint8_t param_buf_len,
  void SendAdvCmd(const tracked_objects::Location& posted_from, uint16_t opcode,
                  uint8_t* param_buf, uint8_t param_buf_len,
                  status_cb command_complete) {
    btu_hcif_send_cmd_with_cb(opcode, param_buf, param_buf_len,
                              adv_cmd_cmpl_cback);

    legacy_pending_ops->push(std::make_pair(opcode, command_complete));
    btu_hcif_send_cmd_with_cb(
        posted_from, opcode, param_buf, param_buf_len,
        base::Bind(&adv_cmd_cmpl_cback, command_complete));
  }

  void ReadInstanceCount(
@@ -309,7 +293,7 @@ class BleAdvertiserLegacyHciInterfaceImpl : public BleAdvertiserHciInterface {
    UINT8_TO_STREAM(pp, channel_map);
    UINT8_TO_STREAM(pp, filter_policy);

    SendAdvCmd(HCI_BLE_WRITE_ADV_PARAMS, param,
    SendAdvCmd(FROM_HERE, HCI_BLE_WRITE_ADV_PARAMS, param,
               HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS, command_complete);
  }

@@ -325,7 +309,7 @@ class BleAdvertiserLegacyHciInterfaceImpl : public BleAdvertiserHciInterface {
    UINT8_TO_STREAM(pp, data_length);
    ARRAY_TO_STREAM(pp, data, data_length);

    SendAdvCmd(HCI_BLE_WRITE_ADV_DATA, param,
    SendAdvCmd(FROM_HERE, HCI_BLE_WRITE_ADV_DATA, param,
               HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1, command_complete);
  }

@@ -342,7 +326,7 @@ class BleAdvertiserLegacyHciInterfaceImpl : public BleAdvertiserHciInterface {
    UINT8_TO_STREAM(pp, scan_response_data_length);
    ARRAY_TO_STREAM(pp, scan_response_data, scan_response_data_length);

    SendAdvCmd(HCI_BLE_WRITE_SCAN_RSP_DATA, param,
    SendAdvCmd(FROM_HERE, HCI_BLE_WRITE_SCAN_RSP_DATA, param,
               HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1, command_complete);
  }

@@ -355,7 +339,7 @@ class BleAdvertiserLegacyHciInterfaceImpl : public BleAdvertiserHciInterface {
    uint8_t* pp = param;
    BDADDR_TO_STREAM(pp, random_address);

    SendAdvCmd(HCI_BLE_WRITE_RANDOM_ADDR, param,
    SendAdvCmd(FROM_HERE, HCI_BLE_WRITE_RANDOM_ADDR, param,
               HCIC_PARAM_SIZE_WRITE_RANDOM_ADDR_CMD, command_complete);
  }

@@ -368,18 +352,18 @@ class BleAdvertiserLegacyHciInterfaceImpl : public BleAdvertiserHciInterface {
    uint8_t* pp = param;
    UINT8_TO_STREAM(pp, enable);

    SendAdvCmd(HCI_BLE_WRITE_ADV_ENABLE, param,
    SendAdvCmd(FROM_HERE, HCI_BLE_WRITE_ADV_ENABLE, param,
               HCIC_PARAM_SIZE_WRITE_ADV_ENABLE, command_complete);
  }
};

class BleAdvertiserHciExtendedImpl : public BleAdvertiserHciInterface {
  void SendAdvCmd(uint16_t opcode, uint8_t* param_buf, uint8_t param_buf_len,
  void SendAdvCmd(const tracked_objects::Location& posted_from, uint16_t opcode,
                  uint8_t* param_buf, uint8_t param_buf_len,
                  status_cb command_complete) {
    btu_hcif_send_cmd_with_cb(opcode, param_buf, param_buf_len,
                              adv_cmd_cmpl_cback);

    legacy_pending_ops->push(std::make_pair(opcode, command_complete));
    btu_hcif_send_cmd_with_cb(
        posted_from, opcode, param_buf, param_buf_len,
        base::Bind(&adv_cmd_cmpl_cback, command_complete));
  }

  void ReadInstanceCount(
@@ -424,7 +408,7 @@ class BleAdvertiserHciExtendedImpl : public BleAdvertiserHciInterface {
    UINT8_TO_STREAM(pp, advertising_sid);
    UINT8_TO_STREAM(pp, scan_request_notify_enable);

    SendAdvCmd(HCI_LE_SET_EXT_ADVERTISING_PARAM, param,
    SendAdvCmd(FROM_HERE, HCI_LE_SET_EXT_ADVERTISING_PARAM, param,
               HCI_LE_SET_EXT_ADVERTISING_PARAM_LEN, command_complete);
  }

@@ -444,7 +428,7 @@ class BleAdvertiserHciExtendedImpl : public BleAdvertiserHciInterface {
    UINT8_TO_STREAM(pp, data_length);
    ARRAY_TO_STREAM(pp, data, data_length);

    SendAdvCmd(HCI_LE_SET_EXT_ADVERTISING_DATA, param, cmd_length,
    SendAdvCmd(FROM_HERE, HCI_LE_SET_EXT_ADVERTISING_DATA, param, cmd_length,
               command_complete);
  }

@@ -466,8 +450,8 @@ class BleAdvertiserHciExtendedImpl : public BleAdvertiserHciInterface {
    UINT8_TO_STREAM(pp, scan_response_data_length);
    ARRAY_TO_STREAM(pp, scan_response_data, scan_response_data_length);

    SendAdvCmd(HCI_LE_SET_EXT_ADVERTISING_SCAN_RESP, param, cmd_length,
               command_complete);
    SendAdvCmd(FROM_HERE, HCI_LE_SET_EXT_ADVERTISING_SCAN_RESP, param,
               cmd_length, command_complete);
  }

  void SetRandomAddress(uint8_t handle, uint8_t random_address[6],
@@ -482,7 +466,7 @@ class BleAdvertiserHciExtendedImpl : public BleAdvertiserHciInterface {
    UINT8_TO_STREAM(pp, handle);
    BDADDR_TO_STREAM(pp, random_address);

    SendAdvCmd(HCI_LE_SET_EXT_ADVERTISING_RANDOM_ADDRESS, param,
    SendAdvCmd(FROM_HERE, HCI_LE_SET_EXT_ADVERTISING_RANDOM_ADDRESS, param,
               LE_SET_ADVERTISING_SET_RANDOM_ADDRESS_LEN, command_complete);
  }

@@ -504,7 +488,7 @@ class BleAdvertiserHciExtendedImpl : public BleAdvertiserHciInterface {
    UINT16_TO_STREAM(pp, duration);
    UINT8_TO_STREAM(pp, max_extended_advertising_events);

    SendAdvCmd(HCI_LE_SET_EXT_ADVERTISING_ENABLE, param, cmd_length,
    SendAdvCmd(FROM_HERE, HCI_LE_SET_EXT_ADVERTISING_ENABLE, param, cmd_length,
               command_complete);
  }

@@ -545,8 +529,6 @@ void btm_le_on_advertising_set_terminated(uint8_t* p, uint16_t length) {
void BleAdvertiserHciInterface::Initialize() {
  VLOG(1) << __func__;
  LOG_ASSERT(instance == nullptr) << "Was already initialized.";
  pending_ops = new std::queue<std::pair<uint8_t, status_cb>>();
  legacy_pending_ops = new std::queue<std::pair<uint16_t, status_cb>>();

  if (controller_get_interface()->supports_ble_extended_advertising()) {
    instance = new BleAdvertiserHciExtendedImpl();
@@ -569,10 +551,6 @@ void BleAdvertiserHciInterface::CleanUp() {
        BleAdvertiserVscHciInterfaceImpl::VendorSpecificEventCback, false);
  }

  delete pending_ops;
  pending_ops = nullptr;
  delete legacy_pending_ops;
  legacy_pending_ops = nullptr;
  delete instance;
  instance = nullptr;
}
+45 −9
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@

#define LOG_TAG "bt_btu_hcif"

#include <base/callback.h>
#include <base/location.h>
#include <base/logging.h>
#include <stdio.h>
#include <stdlib.h>
@@ -45,6 +47,8 @@
#include "osi/include/log.h"
#include "osi/include/osi.h"

using tracked_objects::Location;

// TODO(zachoverflow): remove this horrible hack
extern fixed_queue_t* btu_hci_msg_queue;

@@ -378,8 +382,23 @@ void btu_hcif_send_cmd(UNUSED_ATTR uint8_t controller_id, BT_HDR* p_buf) {
#endif
}

typedef void (*hci_cmd_complete_cb)(uint16_t opcode, uint8_t* return_parameters,
                                    uint16_t return_parameters_length);
using hci_cmd_cb = base::Callback<void(uint8_t* /* return_parameters */,
                                       uint16_t /* return_parameters_length*/)>;

struct cmd_with_cb_data {
  hci_cmd_cb cb;
  Location posted_from;
};

void cmd_with_cb_data_init(cmd_with_cb_data* cb_wrapper) {
  new (&cb_wrapper->cb) hci_cmd_cb;
  new (&cb_wrapper->posted_from) Location;
}

void cmd_with_cb_data_cleanup(cmd_with_cb_data* cb_wrapper) {
  cb_wrapper->cb.~hci_cmd_cb();
  cb_wrapper->posted_from.~Location();
}

static void btu_hcif_command_complete_evt_with_cb_on_task(BT_HDR* event) {
  command_complete_hack_t* hack = (command_complete_hack_t*)&event->data[0];
@@ -390,8 +409,12 @@ static void btu_hcif_command_complete_evt_with_cb_on_task(BT_HDR* event) {
      3;  // 2 to skip the event headers, 1 to skip the command credits
  STREAM_TO_UINT16(opcode, stream);

  hci_cmd_complete_cb cb = (hci_cmd_complete_cb)hack->context;
  cb(opcode, stream, hack->response->len - 5);
  cmd_with_cb_data* cb_wrapper = (cmd_with_cb_data*)hack->context;
  HCI_TRACE_DEBUG("command complete for: %s",
                  cb_wrapper->posted_from.ToString().c_str());
  cb_wrapper->cb.Run(stream, hack->response->len - 5);
  cmd_with_cb_data_cleanup(cb_wrapper);
  osi_free(cb_wrapper);

  osi_free(hack->response);
  osi_free(event);
@@ -418,10 +441,15 @@ static void btu_hcif_command_status_evt_with_cb_on_task(BT_HDR* event) {
  uint8_t* stream = hack->command->data + hack->command->offset;
  STREAM_TO_UINT16(opcode, stream);

  hci_cmd_complete_cb cb = (hci_cmd_complete_cb)hack->context;
  CHECK(hack->status != 0);

  // report command status error
  cb(opcode, &hack->status, sizeof(uint16_t));
  cmd_with_cb_data* cb_wrapper = (cmd_with_cb_data*)hack->context;
  HCI_TRACE_DEBUG("command status for: %s",
                  cb_wrapper->posted_from.ToString().c_str());
  cb_wrapper->cb.Run(&hack->status, sizeof(uint16_t));
  cmd_with_cb_data_cleanup(cb_wrapper);
  osi_free(cb_wrapper);

  osi_free(hack->command);
  osi_free(event);
@@ -452,8 +480,9 @@ static void btu_hcif_command_status_evt_with_cb(uint8_t status, BT_HDR* command,
/* This function is called to send commands to the Host Controller. |cb| is
 * called when command status event is called with error code, or when the
 * command complete event is received. */
void btu_hcif_send_cmd_with_cb(uint16_t opcode, uint8_t* params,
                               uint8_t params_len, hci_cmd_complete_cb cb) {
void btu_hcif_send_cmd_with_cb(const tracked_objects::Location& posted_from,
                               uint16_t opcode, uint8_t* params,
                               uint8_t params_len, hci_cmd_cb cb) {
  BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE);
  uint8_t* pp = (uint8_t*)(p + 1);

@@ -466,9 +495,16 @@ void btu_hcif_send_cmd_with_cb(uint16_t opcode, uint8_t* params,
    memcpy(pp, params, params_len);
  }

  cmd_with_cb_data* cb_wrapper =
      (cmd_with_cb_data*)osi_malloc(sizeof(cmd_with_cb_data));

  cmd_with_cb_data_init(cb_wrapper);
  cb_wrapper->cb = cb;
  cb_wrapper->posted_from = posted_from;

  hci_layer_get_interface()->transmit_command(
      p, btu_hcif_command_complete_evt_with_cb,
      btu_hcif_command_status_evt_with_cb, (void*)cb);
      btu_hcif_command_status_evt_with_cb, (void*)cb_wrapper);

#if (HCILP_INCLUDED == TRUE)
  btu_check_bt_sleep();
+6 −0
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@
#ifndef BTU_H
#define BTU_H

#include <base/callback.h>
#include <base/location.h>
#include "bt_common.h"
#include "bt_target.h"
#include "osi/include/alarm.h"
@@ -67,6 +69,10 @@ extern void btu_check_bt_sleep(void);
*/
extern void btu_hcif_process_event(uint8_t controller_id, BT_HDR* p_buf);
extern void btu_hcif_send_cmd(uint8_t controller_id, BT_HDR* p_msg);
extern void btu_hcif_send_cmd_with_cb(
    const tracked_objects::Location& posted_from, uint16_t opcode,
    uint8_t* params, uint8_t params_len,
    base::Callback<void(uint8_t*, uint16_t)> cb);

/* Functions provided by btu_init.cc
 ***********************************