193 lines
7.9 KiB
C
193 lines
7.9 KiB
C
/****************************************************************************
|
|
* Copyright (C) 2025 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 "bluetooth.h"
|
|
#include "bt_cs.h"
|
|
#include "bt_tools.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#ifdef CONFIG_BLUETOOTH_LE_CS
|
|
|
|
static int cs_start_distance_measurement_cmd(void* handle, int argc, char* argv[]);
|
|
static int cs_stop_distance_measurement_cmd(void* handle, int argc, char* argv[]);
|
|
static int cs_set_config_cmd(void* handle, int argc, char* argv[]);
|
|
#ifdef CONFIG_BT_CS_RAS_TEST
|
|
static int cs_test_cmd(void* handle, int argc, char* argv[]);
|
|
#endif
|
|
|
|
static void* cs_callbacks = NULL;
|
|
|
|
static bt_command_t g_cs_tables[] = {
|
|
{ "start", cs_start_distance_measurement_cmd, 0, "\"start distance measurement :\"" },
|
|
{ "stop", cs_stop_distance_measurement_cmd, 0, "\"stop distance measurement :\"" },
|
|
{ "config", cs_set_config_cmd, 1, "set CS parameters\n"
|
|
"\t -f or --feature, RAS feature bits (hex or decimal)\n"
|
|
"\t Bit 0 (0x01): Real-time Ranging Data\n"
|
|
"\t Bit 1 (0x02): Retrieve Lost Ranging Data Segments\n"
|
|
"\t Bit 2 (0x04): Abort Operation\n"
|
|
"\t Bit 3 (0x08): Filter Ranging Data\n"
|
|
"\t -r or --role, CS role bits (hex or decimal)\n"
|
|
"\t Bit 0 (0x01): Initiator\n"
|
|
"\t Bit 1 (0x02): Reflector\n"
|
|
"\t -a or --antenna, CS_SYNC antenna selection (hex or decimal)\n"
|
|
"\t 0x01 (1): antenna identifier 1\n"
|
|
"\t 0x02 (2): antenna identifier 2\n"
|
|
"\t 0x03 (3): antenna identifier 3\n"
|
|
"\t 0x04 (4): antenna identifier 4\n"
|
|
"\t 0xFD (253): repetitive order 0x01 to Num_Antennae_Supported\n"
|
|
"\t 0xFE (254): repetitive order 0x01 to 0x04\n"
|
|
"\t 0xFF (255): no recommendation\n"
|
|
"\t -p or --power, max TX power in dBm (-127 to 20)\n"
|
|
"\t Examples:\n"
|
|
"\t set -f 0x07\n"
|
|
"\t set -f 0x07 -r 0x01 -a 2 -p 10\n" },
|
|
#ifdef CONFIG_BT_CS_RAS_TEST
|
|
{ "test", cs_test_cmd, 0, "\"Channel Sounding test mode :\"" },
|
|
#endif
|
|
};
|
|
|
|
static void usage(void)
|
|
{
|
|
printf("Usage:\n");
|
|
printf("\taddress: peer device address like 00:01:02:03:04:05\n");
|
|
printf("Commands:\n");
|
|
for (int i = 0; i < ARRAY_SIZE(g_cs_tables); i++) {
|
|
printf("\t%-8s\t%s\n", g_cs_tables[i].cmd, g_cs_tables[i].help);
|
|
}
|
|
}
|
|
|
|
static void le_cs_distance_measure_started_cb(void* cookie, bt_address_t* addr, uint8_t method)
|
|
{
|
|
PRINT("cs distance measure started. cookie:%p, addr:%s, method:%d",
|
|
cookie, bt_addr_bastr(addr), method);
|
|
}
|
|
|
|
static void le_cs_distance_measure_stopped_cb(void* cookie, bt_address_t* addr, uint8_t reason, uint8_t method)
|
|
{
|
|
PRINT("cs distance measure stopped. cookie:%p, addr:%s, reason:%d, method:%d",
|
|
cookie, bt_addr_bastr(addr), reason, method);
|
|
}
|
|
|
|
static void le_cs_distance_measure_result_cb(void* cookie, bt_address_t* addr, bt_distance_measurement_result_t* result)
|
|
{
|
|
}
|
|
|
|
static const cs_callbacks_t le_cs_cbs = {
|
|
sizeof(le_cs_cbs),
|
|
le_cs_distance_measure_started_cb,
|
|
le_cs_distance_measure_stopped_cb,
|
|
le_cs_distance_measure_result_cb,
|
|
};
|
|
|
|
int le_cs_command_init(void* handle)
|
|
{
|
|
cs_callbacks = bt_cs_register_callbacks(handle, &le_cs_cbs);
|
|
PRINT("cs command init.");
|
|
return 0;
|
|
}
|
|
|
|
void le_cs_command_uninit(void* handle)
|
|
{
|
|
bt_cs_unregister_callbacks(handle, cs_callbacks);
|
|
cs_callbacks = NULL;
|
|
}
|
|
|
|
int le_cs_command_exec(void* handle, int argc, char* argv[])
|
|
{
|
|
int ret = CMD_USAGE_FAULT;
|
|
|
|
if (argc > 0)
|
|
ret = execute_command_in_table_offset(handle, g_cs_tables, ARRAY_SIZE(g_cs_tables), argc, argv, 0);
|
|
|
|
if (ret < 0)
|
|
usage();
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int cs_start_distance_measurement_cmd(void* handle, int argc, char* argv[])
|
|
{
|
|
bt_distance_measurement_params_t params;
|
|
|
|
memset(¶ms, 0, sizeof(bt_distance_measurement_params_t));
|
|
params.method = METHOD_CS;
|
|
bt_cs_start_distance_measurement(handle, ¶ms);
|
|
return 0;
|
|
}
|
|
|
|
static int cs_stop_distance_measurement_cmd(void* handle, int argc, char* argv[])
|
|
{
|
|
bt_address_t addr = { 0 };
|
|
bt_cs_stop_distance_measurement(handle, &addr, METHOD_CS, false);
|
|
return 0;
|
|
}
|
|
|
|
static int cs_set_config_cmd(void* handle, int argc, char* argv[])
|
|
{
|
|
bt_cs_set_params_t params;
|
|
bt_address_t addr = { 0 };
|
|
memset(¶ms, 0, sizeof(params));
|
|
|
|
for (int i = 0; i < argc; i++) {
|
|
if ((strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "--feature") == 0) && i + 1 < argc) {
|
|
params.ras_feature = strtoul(argv[++i], NULL, 0);
|
|
} else if ((strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "--role") == 0) && i + 1 < argc) {
|
|
params.role = (uint8_t)strtoul(argv[++i], NULL, 0);
|
|
} else if ((strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--antenna") == 0) && i + 1 < argc) {
|
|
params.cs_sync_antenna_selection = (uint8_t)strtoul(argv[++i], NULL, 0);
|
|
} else if ((strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "--power") == 0) && i + 1 < argc) {
|
|
int power = atoi(argv[++i]);
|
|
if (power < -127 || power > 20) {
|
|
PRINT("error tx power, range must in -127~20");
|
|
return CMD_INVALID_PARAM;
|
|
}
|
|
params.max_tx_power = (int8_t)power;
|
|
}
|
|
}
|
|
|
|
PRINT("Setting CS parameters:");
|
|
PRINT(" Feature: 0x%08" PRIx32, params.ras_feature);
|
|
PRINT(" Real-time Ranging Data: %s", (params.ras_feature & 0x01) ? "Enabled" : "Disabled");
|
|
PRINT(" Retrieve Lost Ranging Data Segments: %s", (params.ras_feature & 0x02) ? "Enabled" : "Disabled");
|
|
PRINT(" Abort Operation: %s", (params.ras_feature & 0x04) ? "Enabled" : "Disabled");
|
|
PRINT(" Filter Ranging Data: %s", (params.ras_feature & 0x08) ? "Enabled" : "Disabled");
|
|
PRINT(" Role: 0x%02x", params.role);
|
|
PRINT(" Initiator: %s", (params.role & 0x01) ? "Enabled" : "Disabled");
|
|
PRINT(" Reflector: %s", (params.role & 0x02) ? "Enabled" : "Disabled");
|
|
PRINT(" Antenna selection: 0x%02x", params.cs_sync_antenna_selection);
|
|
PRINT(" Power: %d dBm", params.max_tx_power);
|
|
|
|
bt_status_t status = bt_cs_set_config(handle, &addr, ¶ms);
|
|
if (status == BT_STATUS_SUCCESS) {
|
|
PRINT("Set CS parameters successfully");
|
|
} else {
|
|
PRINT("Failed to set CS parameters, status: %d", status);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_BT_CS_RAS_TEST
|
|
static int cs_test_cmd(void* handle, int argc, char* argv[])
|
|
{
|
|
uint8_t data[10] = { 0 };
|
|
bt_cs_test(handle, (void*)data, sizeof(data));
|
|
return 0;
|
|
}
|
|
#endif /* CONFIG_BT_CS_RAS_TEST */
|
|
|
|
#endif /* CONFIG_BLUETOOTH_LE_CS */ |