mirror of
https://github.com/google/pebble.git
synced 2025-12-02 12:12:23 -05:00
156 lines
5.0 KiB
C
156 lines
5.0 KiB
C
/*
|
|
* Copyright 2024 Google LLC
|
|
*
|
|
* 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 FILE_LOG_COLOR LOG_COLOR_BLUE
|
|
#include "system/logging.h"
|
|
#include "system/passert.h"
|
|
|
|
#include "comm/ble/gap_le_slave_discovery.h"
|
|
#include "kernel/pebble_tasks.h"
|
|
#include "services/common/bluetooth/bluetooth_ctl.h"
|
|
#include "services/common/bluetooth/bluetooth_persistent_storage.h"
|
|
#include "services/common/bluetooth/local_addr.h"
|
|
#include "services/common/bluetooth/pairability.h"
|
|
#include "services/common/regular_timer.h"
|
|
#include "services/common/system_task.h"
|
|
|
|
#include <bluetooth/connectability.h>
|
|
#include <bluetooth/features.h>
|
|
#include <bluetooth/pairability.h>
|
|
|
|
static void prv_pairability_timer_cb(void *unused);
|
|
|
|
static int s_allow_bt_pairing_refcount = 0;
|
|
static int s_allow_ble_pairing_refcount = 0;
|
|
|
|
static RegularTimerInfo s_pairability_timer_info = {
|
|
.cb = prv_pairability_timer_cb,
|
|
};
|
|
|
|
static void evaluate_pairing_refcount(void *data) {
|
|
PBL_ASSERT_TASK(PebbleTask_KernelBackground);
|
|
|
|
if (!bt_ctl_is_bluetooth_running()) {
|
|
return;
|
|
}
|
|
|
|
PBL_LOG(LOG_LEVEL_DEBUG, "Pairabilty state: LE=%u, Classic=%u",
|
|
s_allow_ble_pairing_refcount, s_allow_bt_pairing_refcount);
|
|
|
|
bool is_ble_pairable_and_discoverable = (s_allow_ble_pairing_refcount > 0);
|
|
|
|
bt_driver_le_pairability_set_enabled(is_ble_pairable_and_discoverable);
|
|
if (gap_le_slave_is_discoverable() != is_ble_pairable_and_discoverable) {
|
|
if (is_ble_pairable_and_discoverable) {
|
|
bt_local_addr_pause_cycling();
|
|
} else {
|
|
bt_local_addr_resume_cycling();
|
|
}
|
|
gap_le_slave_set_discoverable(is_ble_pairable_and_discoverable);
|
|
}
|
|
|
|
if (bt_driver_supports_bt_classic()) {
|
|
bt_driver_classic_pairability_set_enabled((s_allow_bt_pairing_refcount > 0));
|
|
bt_driver_classic_update_connectability();
|
|
}
|
|
}
|
|
|
|
static void prv_schedule_evaluation(void) {
|
|
// We used to sparingly schedule the evaluation and had a bug because of this:
|
|
// https://pebbletechnology.atlassian.net/browse/PBL-22884
|
|
// Because this pretty much only happens in response to user input, don't bother limiting this,
|
|
// and always evaluate, even though the state might not have changed:
|
|
system_task_add_callback(evaluate_pairing_refcount, NULL);
|
|
}
|
|
|
|
void bt_pairability_use(void) {
|
|
++s_allow_bt_pairing_refcount;
|
|
++s_allow_ble_pairing_refcount;
|
|
prv_schedule_evaluation();
|
|
}
|
|
|
|
void bt_pairability_use_bt(void) {
|
|
++s_allow_bt_pairing_refcount;
|
|
prv_schedule_evaluation();
|
|
}
|
|
|
|
void bt_pairability_use_ble(void) {
|
|
++s_allow_ble_pairing_refcount;
|
|
prv_schedule_evaluation();
|
|
}
|
|
|
|
static void prv_pairability_timer_cb(void *unused) {
|
|
regular_timer_remove_callback(&s_pairability_timer_info);
|
|
bt_pairability_release_ble();
|
|
}
|
|
|
|
void bt_pairability_use_ble_for_period(uint16_t duration_secs) {
|
|
if (!regular_timer_is_scheduled(&s_pairability_timer_info)) {
|
|
// If this function is called multiple times before the timer is unscheduled, limit to calling
|
|
// "use" only once:
|
|
bt_pairability_use_ble();
|
|
}
|
|
// Always reschedule, even if the duration is shorter than the one that might already be
|
|
// scheduled:
|
|
regular_timer_add_multisecond_callback(&s_pairability_timer_info, duration_secs);
|
|
}
|
|
|
|
void bt_pairability_release(void) {
|
|
PBL_ASSERT(s_allow_bt_pairing_refcount != 0 && s_allow_ble_pairing_refcount != 0, "");
|
|
--s_allow_bt_pairing_refcount;
|
|
--s_allow_ble_pairing_refcount;
|
|
prv_schedule_evaluation();
|
|
}
|
|
|
|
void bt_pairability_release_bt(void) {
|
|
PBL_ASSERT(s_allow_bt_pairing_refcount != 0, "");
|
|
--s_allow_bt_pairing_refcount;
|
|
prv_schedule_evaluation();
|
|
}
|
|
|
|
void bt_pairability_release_ble(void) {
|
|
PBL_ASSERT(s_allow_ble_pairing_refcount != 0, "");
|
|
--s_allow_ble_pairing_refcount;
|
|
prv_schedule_evaluation();
|
|
}
|
|
|
|
//! Call this whenever we modify the number of saved bondings we have.
|
|
void bt_pairability_update_due_to_bonding_change(void) {
|
|
static bool s_pairable_due_to_no_gateway_bondings = false;
|
|
const bool has_classic_bonding =
|
|
(bt_driver_supports_bt_classic() &&
|
|
bt_persistent_storage_has_active_bt_classic_gateway_bonding());
|
|
|
|
if (!has_classic_bonding &&
|
|
!bt_persistent_storage_has_active_ble_gateway_bonding() &&
|
|
!bt_persistent_storage_has_ble_ancs_bonding()) {
|
|
if (!s_pairable_due_to_no_gateway_bondings) {
|
|
bt_pairability_use();
|
|
s_pairable_due_to_no_gateway_bondings = true;
|
|
}
|
|
} else {
|
|
if (s_pairable_due_to_no_gateway_bondings) {
|
|
bt_pairability_release();
|
|
s_pairable_due_to_no_gateway_bondings = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
void bt_pairability_init(void) {
|
|
bt_pairability_update_due_to_bonding_change();
|
|
prv_schedule_evaluation();
|
|
}
|