-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
OS-Upgrade: Add a BT storage transformation tool.
bug: v/47945 Rootcause: Due to the differences in the storage format of Bluetooth information in different system versions, in order to ensure that saved information can continue to be used after system upgrades, the storage transformation tool has been added. Signed-off-by: chejinxian1 <[email protected]>
- Loading branch information
1 parent
dbde6f0
commit a08d305
Showing
4 changed files
with
371 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,342 @@ | ||
/**************************************************************************** | ||
* 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" | ||
|
||
// Defined macro in rel-3.5 | ||
#define BT_DEVICE_NAME_MAX_LEN 63 // 63 used in rel-3.5 | ||
#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" | ||
|
||
// Type dependency for rel-3.5 | ||
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; | ||
|
||
// Storage format in rel-3.5 | ||
|
||
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; // undefined BT_IO_CAPABILITY_UNKNOW in rel-3.5 | ||
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; // 1 Byte | ||
char bt_name[BT_DEVICE_NAME_MAX_LEN + 1]; | ||
BT_UUID_T uuids[10]; | ||
uint8_t link_key[16]; | ||
uint8_t link_key_type; // 1 Byte | ||
uint16_t device_volume; // 2 Bytes | ||
uint32_t device_profile; // 4 Bytes | ||
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)); // shorter 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; // +1 for adaption | ||
} | ||
|
||
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; // The correspondence of this field has not been confirmed. | ||
memcpy(device_property->smp_key, smp_keys, sizeof(device_property->smp_key)); | ||
device_property->device_type = 0; // unknown | ||
} | ||
|
||
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); // There is no adapter info in rel-3.5 in default | ||
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); // obtain the address of the first device | ||
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; | ||
} |