* Copyright (C) 2022 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 <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bluetooth.h"
#include "bt_adapter.h"
#include "bt_lea_tbs.h"
#include "bt_tools.h"
static int tbs_add(void* handle, int argc, char* argv[]);
static int tbs_remove(void* handle, int argc, char* argv[]);
static int tbs_set_telephone_bearer_info(void* handle, int argc, char* argv[]);
static int tbs_add_call(void* handle, int argc, char* argv[]);
static int tbs_remove_call(void* handle, int argc, char* argv[]);
static int tbs_provider_name_changed(void* handle, int argc, char* argv[]);
static int tbs_bearer_technology_changed(void* handle, int argc, char* argv[]);
static int tbs_uri_schemes_supported_list_changed(void* handle, int argc, char* argv[]);
static int tbs_signal_strength_changed(void* handle, int argc, char* argv[]);
static int tbs_signal_strength_report_interval_changed(void* handle, int argc, char* argv[]);
static int tbs_status_flags_changed(void* handle, int argc, char* argv[]);
static int tbs_call_state_changed(void* handle, int argc, char* argv[]);
static int tbs_notify_termination_reason(void* handle, int argc, char* argv[]);
static int tbs_call_control_response(void* handle, int argc, char* argv[]);
#define TBS_SET_BEARER "set bearer param: <ref><name><uci><uri_schemes><tech><strength><interval><status_flags><optional_op>"
#define TBS_ADD_CALL "add a call param: <index><state><flags><call_uri><incoming_target_uri><friendly_name>"
static bt_command_t g_lea_tbs_tables[] = {
{ "add", tbs_add, 0, "add TBS instance param: <NULL>" },
{ "remove", tbs_remove, 0, "remove TBS instance param: <NULL>" },
{ "tele", tbs_set_telephone_bearer_info, 0, TBS_SET_BEARER },
{ "call", tbs_add_call, 0, TBS_ADD_CALL },
{ "rmcall", tbs_remove_call, 0, "remove a call param: <call_index>" },
{ "providername", tbs_provider_name_changed, 0, "TBS notify provider name changed param: <name>" },
{ "technology", tbs_bearer_technology_changed, 0, "TBS notify bearer tech changed param: <technology>" },
{ "urischemes", tbs_uri_schemes_supported_list_changed, 0, "TBS notify uri supported list changed param: <uri_schemes>" },
{ "signalstrength", tbs_signal_strength_changed, 0, "TBS notify signal strength changed param: <strength>" },
{ "reportinterval", tbs_signal_strength_report_interval_changed, 0, "TBS notify ss report interval changed param: <interval>" },
{ "statusflags", tbs_status_flags_changed, 0, "TBS notify status flags changed param: <status_flags>" },
{ "state", tbs_call_state_changed, 0, "TBS notify call state param: <number><index><state><flags>" },
{ "term_reason", tbs_notify_termination_reason, 0, "TBS notify termination reason param: <call_index><reason>" },
{ "resp", tbs_call_control_response, 0, "TBS call control response param: <call_index><result>" },
};
static void* tbs_callbacks = NULL;
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_lea_tbs_tables); i++) {
printf("\t%-8s\t%s\n", g_lea_tbs_tables[i].cmd, g_lea_tbs_tables[i].help);
}
}
static int tbs_add(void* handle, int argc, char* argv[])
{
if (bt_lea_tbs_service_add(handle) != BT_STATUS_SUCCESS)
return CMD_ERROR;
return CMD_OK;
}
static int tbs_remove(void* handle, int argc, char* argv[])
{
if (bt_lea_tbs_service_remove(handle) != BT_STATUS_SUCCESS)
return CMD_ERROR;
return CMD_OK;
}
static int tbs_set_telephone_bearer_info(void* handle, int argc, char* argv[])
{
if (argc < 9)
return CMD_PARAM_NOT_ENOUGH;
lea_tbs_telephone_bearer_t* bearer = (lea_tbs_telephone_bearer_t*)malloc(sizeof(lea_tbs_telephone_bearer_t));
bearer->bearer_ref = (void*)atoi(argv[0]);
strcpy((char*)bearer->provider_name, argv[1]);
strcpy((char*)bearer->uci, argv[2]);
strcpy((char*)bearer->uri_schemes, argv[3]);
bearer->technology = (uint8_t)atoi(argv[4]);
bearer->signal_strength = (uint8_t)atoi(argv[5]);
bearer->signal_strength_report_interval = (uint8_t)atoi(argv[6]);
bearer->status_flags = (uint8_t)atoi(argv[7]);
bearer->optional_opcodes_supported = (uint8_t)atoi(argv[8]);
if (bt_lea_tbs_set_telephone_bearer_info(handle, bearer) != BT_STATUS_SUCCESS)
return CMD_ERROR;
return CMD_OK;
}
static int tbs_add_call(void* handle, int argc, char* argv[])
{
if (argc < 6)
return CMD_PARAM_NOT_ENOUGH;
lea_tbs_calls_t* call_s = (lea_tbs_calls_t*)malloc(sizeof(lea_tbs_calls_t));
call_s->index = (uint8_t)atoi(argv[0]);
call_s->state = (uint8_t)atoi(argv[1]);
call_s->flags = (uint8_t)atoi(argv[2]);
strcpy((char*)call_s->call_uri, argv[3]);
strcpy((char*)call_s->incoming_target_uri, argv[4]);
strcpy((char*)call_s->friendly_name, argv[5]);
if (bt_lea_tbs_add_call(handle, call_s) != BT_STATUS_SUCCESS)
return CMD_ERROR;
return CMD_OK;
}
static int tbs_remove_call(void* handle, int argc, char* argv[])
{
if (argc < 1)
return CMD_PARAM_NOT_ENOUGH;
uint8_t call_index = (uint8_t)atoi(argv[0]);
if (bt_lea_tbs_remove_call(handle, call_index) != BT_STATUS_SUCCESS)
return CMD_ERROR;
return CMD_OK;
}
static int tbs_provider_name_changed(void* handle, int argc, char* argv[])
{
if (argc < 1)
return CMD_PARAM_NOT_ENOUGH;
uint8_t* name = (uint8_t*)atoi(argv[0]);
if (bt_lea_tbs_provider_name_changed(handle, name) != BT_STATUS_SUCCESS)
return CMD_ERROR;
return CMD_OK;
}
static int tbs_bearer_technology_changed(void* handle, int argc, char* argv[])
{
if (argc < 1)
return CMD_PARAM_NOT_ENOUGH;
uint8_t technology = (uint8_t)atoi(argv[0]);
if (bt_lea_tbs_bearer_technology_changed(handle, technology) != BT_STATUS_SUCCESS)
return CMD_ERROR;
return CMD_OK;
}
static int tbs_uri_schemes_supported_list_changed(void* handle, int argc, char* argv[])
{
if (argc < 1)
return CMD_PARAM_NOT_ENOUGH;
uint8_t* uri_schemes = (uint8_t*)atoi(argv[0]);
if (bt_lea_tbs_uri_schemes_supported_list_changed(handle, uri_schemes) != BT_STATUS_SUCCESS)
return CMD_ERROR;
return CMD_OK;
}
static int tbs_signal_strength_changed(void* handle, int argc, char* argv[])
{
if (argc < 1)
return CMD_PARAM_NOT_ENOUGH;
uint8_t strength = (uint8_t)atoi(argv[0]);
if (bt_lea_tbs_rssi_value_changed(handle, strength) != BT_STATUS_SUCCESS)
return CMD_ERROR;
return CMD_OK;
}
static int tbs_signal_strength_report_interval_changed(void* handle, int argc, char* argv[])
{
if (argc < 1)
return CMD_PARAM_NOT_ENOUGH;
uint8_t interval = (uint8_t)atoi(argv[0]);
if (bt_lea_tbs_rssi_interval_changed(handle, interval) != BT_STATUS_SUCCESS)
return CMD_ERROR;
return CMD_OK;
}
static int tbs_status_flags_changed(void* handle, int argc, char* argv[])
{
if (argc < 1)
return CMD_PARAM_NOT_ENOUGH;
uint8_t status_flags = (uint8_t)atoi(argv[0]);
if (bt_lea_tbs_status_flags_changed(handle, status_flags) != BT_STATUS_SUCCESS)
return CMD_ERROR;
return CMD_OK;
}
static int tbs_call_state_changed(void* handle, int argc, char* argv[])
{
if (argc < 4)
return CMD_PARAM_NOT_ENOUGH;
uint8_t number = (uint8_t)atoi(argv[0]);
lea_tbs_call_state_t* states_s;
states_s = (lea_tbs_call_state_t*)malloc(sizeof(lea_tbs_call_state_t) * number);
lea_tbs_call_state_t* sub_state = states_s;
for (int i = 0; i < number; i++) {
(sub_state)->index = (uint8_t)atoi(argv[i]);
(sub_state)->state = (uint8_t)atoi(argv[i]);
(sub_state)->flags = (uint8_t)atoi(argv[i]);
sub_state++;
}
if (bt_lea_tbs_call_state_changed(handle, number, states_s) != BT_STATUS_SUCCESS)
return CMD_ERROR;
return CMD_OK;
}
static int tbs_notify_termination_reason(void* handle, int argc, char* argv[])
{
if (argc < 2)
return CMD_PARAM_NOT_ENOUGH;
uint8_t call_index = (uint8_t)atoi(argv[0]);
uint8_t reason = (uint8_t)atoi(argv[1]);
if (bt_lea_tbs_notify_termination_reason(handle, call_index, reason) != BT_STATUS_SUCCESS)
return CMD_ERROR;
return CMD_OK;
}
static int tbs_call_control_response(void* handle, int argc, char* argv[])
{
if (argc < 2)
return CMD_PARAM_NOT_ENOUGH;
uint8_t call_index = (uint8_t)atoi(argv[0]);
uint8_t result = atoi(argv[1]);
if (bt_lea_tbs_call_control_response(handle, call_index, result) != BT_STATUS_SUCCESS)
return CMD_ERROR;
return CMD_OK;
}
static void tbs_test_callback(void* cookie, uint8_t value, bool added)
{
printf("lea_tbs_state_callback");
}
static const lea_tbs_callbacks_t lea_tbs_cbs = {
sizeof(lea_tbs_cbs),
tbs_test_callback,
};
int lea_tbs_command_init(void* handle)
{
tbs_callbacks = bt_lea_tbs_register_callbacks(handle, &lea_tbs_cbs);
return CMD_OK;
}
void lea_tbs_command_uninit(void* handle)
{
bt_status_t ret;
bt_lea_tbs_unregister_callbacks(handle, tbs_callbacks);
ret = bluetooth_stop_service(handle, PROFILE_LEAUDIO_TBS);
if (ret != BT_STATUS_SUCCESS) {
PRINT("%s, failed ret:%d", __func__, ret);
}
}
int lea_tbs_command_exec(void* handle, int argc, char* argv[])
{
int ret = CMD_USAGE_FAULT;
if (argc > 0)
ret = execute_command_in_table(handle, g_lea_tbs_tables, ARRAY_SIZE(g_lea_tbs_tables), argc, argv);
if (ret < 0)
usage();
return ret;
}