* Copyright (C) 2024 Xiaomi 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.
***************************************************************************/
#include <inttypes.h>
#include <kvdb.h>
#include "bluetooth_define.h"
#include "storage.h"
#include "syslog.h"
#include "uv_ext.h"
#define BLUETOOTH_V35_UPGRDE_TAG "persist.bluetooth.v35.upgraded"
#define BT_STORAGE_FILE_PATH "/data/misc/bt/bt_storage.db"
#define BT_DEVICE_NAME_MAX_LEN 63
#define SMP_KEYS_MAX_SIZE 80
#define UUID_SIZE 16
#define BD_ADDR_SIZE 6
#define BT_CONFIG_FILE_PATH "/data/misc/bt/bt_config.db"
#define BT_KEY_DEVICE_INFO "key_deviceinfo"
#define BT_KEY_BTBOND "key_btbond"
#define BT_KEY_BLEBOND "key_blebond"
#define BT_KEY_BLEWHITELIST "key_blewhitelist"
typedef uint8_t BT_UUID_T[UUID_SIZE];
typedef uint8_t BD_ADDR[BD_ADDR_SIZE];
typedef enum {
STORAGE_TYPE_BT,
STORAGE_TYPE_BLE,
} storage_type;
typedef struct {
BD_ADDR bd_addr;
uint8_t addr_type;
} SERVICE_REMOTE_BLE_DEVICE_S;
typedef struct
{
uint8_t bd[6];
uint8_t atype;
uint8_t cap;
uint8_t ltk_len;
uint8_t div[2];
uint8_t ltk[16];
uint8_t ediv[2];
uint8_t rand[8];
uint8_t irk[16];
uint8_t csrk[16];
} smp_keys_parsing_t;
typedef struct {
uint32_t size;
uint32_t check_sum;
uint8_t spk_volume;
uint8_t mic_volume;
uint16_t bonded_number;
storage_type type;
void* bonded_devices;
} bt_storage_t;
typedef struct gap_ble_whitelist_data {
uint32_t size;
uint32_t num;
SERVICE_REMOTE_BLE_DEVICE_S* devices;
} gap_ble_whitelist_data;
typedef struct {
uint32_t cod;
bt_io_capability_t io_capability;
char bt_name[BT_DEVICE_NAME_MAX_LEN];
bt_scan_mode_t scan_mode;
bool bondable;
} bt_device_info_t;
typedef struct {
BD_ADDR bd_addr;
uint8_t addr_type;
char bt_name[BT_DEVICE_NAME_MAX_LEN + 1];
BT_UUID_T uuids[10];
uint8_t link_key[16];
uint8_t link_key_type;
uint16_t device_volume;
uint32_t device_profile;
uint32_t cod;
uint8_t device_type;
uint8_t rssi;
} SERVICE_REMOTE_DEVICE_S;
typedef struct {
uint8_t smp_keys[SMP_KEYS_MAX_SIZE];
} ble_keys_t;
typedef struct {
uv_loop_t* loop;
uv_db_t* read_db;
} bt_storage_transformer_t;
static void transform_deviceinfo_to_adapterinfo(bt_device_info_t* device_info, adapter_storage_t* adapter_info)
{
syslog(LOG_INFO, __func__);
strlcpy(adapter_info->name, device_info->bt_name, sizeof(adapter_info->name));
adapter_info->class_of_device = device_info->cod;
adapter_info->io_capability = device_info->io_capability;
adapter_info->scan_mode = device_info->scan_mode;
adapter_info->bondable = device_info->bondable;
}
static void transform_btbond_to_deviceproperty(SERVICE_REMOTE_DEVICE_S* remote_device, remote_device_properties_t* device_property)
{
syslog(LOG_INFO, __func__);
bt_addr_set(&device_property->addr, remote_device->bd_addr);
device_property->addr_type = remote_device->addr_type;
strlcpy(device_property->name, remote_device->bt_name, sizeof(device_property->name));
memset(&device_property->alias, 0, sizeof(device_property->alias));
device_property->class_of_device = remote_device->cod;
memcpy(device_property->link_key, remote_device->link_key, 16);
device_property->link_key_type = remote_device->link_key_type;
device_property->device_type = remote_device->device_type + 1;
}
static void transform_blebond_to_deviceleproperty(ble_keys_t* remote_device, remote_device_le_properties_t* device_property)
{
smp_keys_parsing_t* smp_keys = (smp_keys_parsing_t*)remote_device->smp_keys;
syslog(LOG_INFO, __func__);
bt_addr_set(&device_property->addr, smp_keys->bd);
device_property->addr_type = smp_keys->atype;
memcpy(device_property->smp_key, smp_keys, sizeof(device_property->smp_key));
device_property->device_type = 0;
}
static void transform_blewhitelist_to_deviceleproperty(SERVICE_REMOTE_BLE_DEVICE_S* remote_device, remote_device_le_properties_t* device_property)
{
syslog(LOG_INFO, __func__);
bt_addr_set(&device_property->addr, remote_device->bd_addr);
device_property->addr_type = remote_device->addr_type;
}
static void load_device_info_cb(int status, const char* key, uv_buf_t value, void* cookie)
{
adapter_storage_t adapter_info;
syslog(LOG_INFO, __func__);
if (status != 0) {
syslog(LOG_WARNING, "adapter info load failed, status is %d\n", status);
return;
}
if (value.len != sizeof(bt_device_info_t)) {
syslog(LOG_ERR, "adapter info load error\n");
return;
}
transform_deviceinfo_to_adapterinfo((bt_device_info_t*)value.base, &adapter_info);
bt_storage_save_adapter_info(&adapter_info);
}
static void load_btbond_cb(int status, const char* key, uv_buf_t value, void* cookie)
{
uint16_t i;
bt_storage_t* bt_storage;
SERVICE_REMOTE_DEVICE_S* device;
remote_device_properties_t* device_properties;
syslog(LOG_INFO, __func__);
if (status != 0) {
syslog(LOG_WARNING, "bt bonded device load failed, status is %d\n", status);
return;
}
bt_storage = (bt_storage_t*)(value.base);
if (bt_storage->check_sum != (bt_storage->size + bt_storage->bonded_number)) {
syslog(LOG_ERR, "loaded bt bonded device info erro\n");
return;
}
syslog(LOG_DEBUG, "loaded %" PRIu32 "bytes info", bt_storage->size);
syslog(LOG_DEBUG, "device type size is %zu", sizeof(SERVICE_REMOTE_DEVICE_S));
device = (SERVICE_REMOTE_DEVICE_S*)(&bt_storage->bonded_devices);
device_properties = (remote_device_properties_t*)malloc(sizeof(remote_device_properties_t) * bt_storage->bonded_number);
if (!device_properties) {
syslog(LOG_ERR, "malloc failed");
return;
}
for (i = 0; i < bt_storage->bonded_number; i++)
transform_btbond_to_deviceproperty(device + i, device_properties + i);
bt_storage_save_bonded_device(device_properties, bt_storage->bonded_number);
free(device_properties);
}
static void load_blebond_cb(int status, const char* key, uv_buf_t value, void* cookie)
{
uint16_t i;
remote_device_le_properties_t* device_properties;
bt_storage_t* bt_storage;
ble_keys_t* keys;
syslog(LOG_INFO, __func__);
if (status != 0) {
syslog(LOG_WARNING, "ble bonded device load failed, status is %d", status);
return;
}
bt_storage = (bt_storage_t*)(value.base);
if (bt_storage->check_sum != (bt_storage->size + bt_storage->bonded_number)) {
syslog(LOG_ERR, "loaded ble bonded device info erro");
return;
}
keys = (ble_keys_t*)(&bt_storage->bonded_devices);
device_properties = (remote_device_le_properties_t*)malloc(sizeof(remote_device_le_properties_t) * bt_storage->bonded_number);
if (!device_properties) {
syslog(LOG_ERR, "malloc failed\n");
return;
}
for (i = 0; i < bt_storage->bonded_number; i++)
transform_blebond_to_deviceleproperty(keys + i, device_properties + i);
bt_storage_save_le_bonded_device(device_properties, bt_storage->bonded_number);
free(device_properties);
}
static void load_blewhitelist_cb(int status, const char* key, uv_buf_t value, void* cookie)
{
uint16_t i;
remote_device_le_properties_t* device_properties;
gap_ble_whitelist_data* ble_whitelist;
SERVICE_REMOTE_BLE_DEVICE_S* whitelist_device;
syslog(LOG_INFO, __func__);
if (status != 0) {
syslog(LOG_WARNING, "ble whitelist device load failed, status is %d\n", status);
return;
}
ble_whitelist = (gap_ble_whitelist_data*)(value.base);
if (ble_whitelist->size != value.len) {
syslog(LOG_ERR, "loaded ble whitelist device info erro\n");
return;
}
syslog(LOG_DEBUG, "loaded %zu bytes info", value.len);
syslog(LOG_DEBUG, "device type size is %zu", sizeof(SERVICE_REMOTE_BLE_DEVICE_S));
whitelist_device = (SERVICE_REMOTE_BLE_DEVICE_S*)(&ble_whitelist->devices);
device_properties = (remote_device_le_properties_t*)malloc(sizeof(remote_device_le_properties_t) * ble_whitelist->num);
if (!device_properties) {
syslog(LOG_ERR, "malloc failed\n");
return;
}
for (i = 0; i < ble_whitelist->num; i++)
transform_blewhitelist_to_deviceleproperty(whitelist_device + i, device_properties + i);
bt_storage_save_whitelist(device_properties, ble_whitelist->num);
free(device_properties);
}
static void load_from_db_with_key(uv_db_t* db, const char* key, void* cb, void* cookie)
{
uv_buf_t buf;
int res;
syslog(LOG_INFO, "load from db with key %s\n", key);
res = uv_db_get(db, key, &buf, cb, cookie);
assert(res == 0);
}
static void bt_storage_transformer_init(bt_storage_transformer_t* transformer)
{
syslog(LOG_INFO, __func__);
transformer->loop = uv_default_loop();
uv_db_init(transformer->loop, &transformer->read_db, BT_CONFIG_FILE_PATH);
bt_storage_init();
}
static void bt_storage_transformer_deinit(bt_storage_transformer_t* transformer)
{
syslog(LOG_INFO, __func__);
if (transformer->read_db)
uv_db_close(transformer->read_db);
bt_storage_cleanup();
uv_loop_close(transformer->loop);
}
static void bt_storage_transformer_work(bt_storage_transformer_t* transformer)
{
syslog(LOG_INFO, __func__);
load_from_db_with_key(transformer->read_db, BT_KEY_DEVICE_INFO, load_device_info_cb, NULL);
load_from_db_with_key(transformer->read_db, BT_KEY_BTBOND, load_btbond_cb, NULL);
load_from_db_with_key(transformer->read_db, BT_KEY_BLEBOND, load_blebond_cb, NULL);
load_from_db_with_key(transformer->read_db, BT_KEY_BLEWHITELIST, load_blewhitelist_cb, NULL);
uv_run(transformer->loop, UV_RUN_DEFAULT);
}
int main(void)
{
bt_storage_transformer_t transformer = { 0 };
if (!access(BT_STORAGE_FILE_PATH, F_OK)) {
syslog(LOG_INFO, "bt_storage.db exits\n");
return 0;
}
if (access(BT_CONFIG_FILE_PATH, F_OK)) {
syslog(LOG_INFO, "bt_config.db not exits\n");
return 0;
}
bt_storage_transformer_init(&transformer);
bt_storage_transformer_work(&transformer);
bt_storage_transformer_deinit(&transformer);
if (property_set_bool(BLUETOOTH_V35_UPGRDE_TAG, true))
syslog(LOG_ERR, "set %s failed\n", BLUETOOTH_V35_UPGRDE_TAG);
return 0;
}