blob: 87111f19b0228682c106e3583a31a3ece9215234 [file] [log] [blame]
/******************************************************************************
*
* Copyright 2021 The Android Open Source Project
*
* 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 "bt_target.h"
#include "bta_csip_int.h"
#include <string.h>
#include "bt_common.h"
#define LOG_TAG "bt_bta_csip"
/*****************************************************************************
* Static methods
****************************************************************************/
static const char* bta_csip_evt_code(uint16_t evt_code);
static const char* bta_csip_state_code(tBTA_CSIP_STATE evt_code);
/*****************************************************************************
* Global data
****************************************************************************/
tBTA_CSIP_CB bta_csip_cb;
enum {
BTA_CSIP_OPEN_ACT,
BTA_CSIP_CLOSE_ACT,
BTA_CSIP_GATT_OPEN_ACT,
BTA_CSIP_GATT_CLOSE_ACT,
BTA_CSIP_GATT_OPEN_FAIL_ACT,
BTA_CSIP_OPEN_CMPL_ACT,
BTA_CSIP_START_SEC_ACT,
BTA_CSIP_SEC_CMPL_ACT,
BTA_CSIP_IGNORE,
};
/* type for action functions */
typedef void (*tBTA_CSIP_ACTION)(tBTA_CSIP_DEV_CB* p_cb, tBTA_CSIP_REQ_DATA* p_data);
/* action functions */
const tBTA_CSIP_ACTION bta_csip_action[] = {
bta_csip_api_open_act,
bta_csip_api_close_act,
bta_csip_gatt_open_act,
bta_csip_gatt_close_act,
bta_csip_gatt_open_fail_act,
bta_csip_open_cmpl_act,
bta_csip_start_sec_act,
bta_csip_sec_cmpl_act,
};
/* state table information */
#define BTA_CSIP_ACTION 0 /* position of action */
#define BTA_CSIP_NEXT_STATE 1 /* position of next state */
#define BTA_CSIP_NUM_COLS 2 /* number of columns */
/* state table in idle state */
const uint8_t bta_csip_st_idle[][BTA_CSIP_NUM_COLS] = {
/* Event Action Next state */
/* BTA_CSIP_API_OPEN_EVT */ {BTA_CSIP_OPEN_ACT, BTA_CSIP_W4_CONN_ST},
/* BTA_CSIP_API_CLOSE_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_IDLE_ST},
/* BTA_CSIP_GATT_OPEN_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_IDLE_ST},
/* BTA_CSIP_GATT_CLOSE_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_IDLE_ST},
/* BTA_CSIP_GATT_OPEN_FAIL_ACT */ {BTA_CSIP_IGNORE, BTA_CSIP_IDLE_ST},
/* BTA_CSIP_OPEN_CMPL_EVT */ {BTA_CSIP_OPEN_CMPL_ACT, BTA_CSIP_CONN_ST},
/* BTA_CSIP_START_ENC_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_IDLE_ST},
/* BTA_CSIP_ENC_CMPL_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_IDLE_ST},
};
/* state table in wait for security state */
const uint8_t bta_csip_st_w4_conn[][BTA_CSIP_NUM_COLS] = {
/* Event Action Next state */
/* BTA_CSIP_API_OPEN_EVT */ {BTA_CSIP_OPEN_ACT, BTA_CSIP_W4_CONN_ST},
/* BTA_CSIP_API_CLOSE_EVT */ {BTA_CSIP_CLOSE_ACT, BTA_CSIP_W4_CONN_ST},
/* BTA_CSIP_GATT_OPEN_EVT */ {BTA_CSIP_GATT_OPEN_ACT, BTA_CSIP_W4_CONN_ST},
/* BTA_CSIP_GATT_CLOSE_EVT */ {BTA_CSIP_GATT_CLOSE_ACT, BTA_CSIP_IDLE_ST},
/* BTA_CSIP_GATT_OPEN_FAIL_ACT */ {BTA_CSIP_GATT_OPEN_FAIL_ACT, BTA_CSIP_IDLE_ST},
/* BTA_CSIP_OPEN_CMPL_EVT */ {BTA_CSIP_OPEN_CMPL_ACT, BTA_CSIP_CONN_ST},
/* BTA_CSIP_START_ENC_EVT */ {BTA_CSIP_START_SEC_ACT, BTA_CSIP_W4_SEC},
/* BTA_CSIP_ENC_CMPL_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_W4_CONN_ST},
};
/* state table in wait for connection state */
const uint8_t bta_csip_st_w4_sec[][BTA_CSIP_NUM_COLS] = {
/* Event Action Next state */
/* BTA_CSIP_API_OPEN_EVT */ {BTA_CSIP_OPEN_ACT, BTA_CSIP_W4_SEC},
/* BTA_CSIP_API_CLOSE_EVT */ {BTA_CSIP_CLOSE_ACT, BTA_CSIP_W4_SEC},
/* BTA_CSIP_GATT_OPEN_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_W4_SEC},
/* BTA_CSIP_GATT_CLOSE_EVT */ {BTA_CSIP_GATT_CLOSE_ACT, BTA_CSIP_IDLE_ST},
/* BTA_CSIP_GATT_OPEN_FAIL_ACT */ {BTA_CSIP_GATT_OPEN_FAIL_ACT, BTA_CSIP_IDLE_ST},
/* BTA_CSIP_OPEN_CMPL_EVT */ {BTA_CSIP_OPEN_CMPL_ACT, BTA_CSIP_CONN_ST},
/* BTA_CSIP_START_ENC_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_W4_SEC},
/* BTA_CSIP_ENC_CMPL_EVT */ {BTA_CSIP_SEC_CMPL_ACT, BTA_CSIP_W4_CONN_ST},
};
/* state table in connection state */
const uint8_t bta_csip_st_connected[][BTA_CSIP_NUM_COLS] = {
/* Event Action Next state */
/* BTA_CSIP_API_OPEN_EVT */ {BTA_CSIP_OPEN_ACT, BTA_CSIP_CONN_ST},
/* BTA_CSIP_API_CLOSE_EVT */ {BTA_CSIP_CLOSE_ACT, BTA_CSIP_CONN_ST},
/* BTA_CSIP_GATT_OPEN_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_CONN_ST},
/* BTA_CSIP_GATT_CLOSE_EVT */ {BTA_CSIP_GATT_CLOSE_ACT, BTA_CSIP_IDLE_ST},
/* BTA_CSIP_GATT_OPEN_FAIL_ACT */ {BTA_CSIP_GATT_OPEN_FAIL_ACT, BTA_CSIP_IDLE_ST},
/* BTA_CSIP_OPEN_CMPL_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_CONN_ST},
/* BTA_CSIP_START_ENC_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_CONN_ST},
/* BTA_CSIP_ENC_CMPL_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_CONN_ST},
};
/* state table in disconnecting state */
const uint8_t bta_csip_st_disconnecting[][BTA_CSIP_NUM_COLS] = {
/* Event Action Next state */
/* BTA_CSIP_API_OPEN_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_DISCONNECTING_ST},
/* BTA_CSIP_API_CLOSE_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_DISCONNECTING_ST},
/* BTA_CSIP_GATT_OPEN_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_DISCONNECTING_ST},
/* BTA_CSIP_GATT_CLOSE_EVT */ {BTA_CSIP_GATT_CLOSE_ACT, BTA_CSIP_IDLE_ST},
/* BTA_CSIP_GATT_OPEN_FAIL_ACT */ {BTA_CSIP_IGNORE, BTA_CSIP_DISCONNECTING_ST},
/* BTA_CSIP_OPEN_CMPL_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_DISCONNECTING_ST},
/* BTA_CSIP_START_ENC_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_DISCONNECTING_ST},
/* BTA_CSIP_ENC_CMPL_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_DISCONNECTING_ST},
};
/* type for state table */
typedef const uint8_t (*tBTA_CSIP_ST_TBL)[BTA_CSIP_NUM_COLS];
/* state table */
tBTA_CSIP_ST_TBL bta_csip_st_tbl[] = {bta_csip_st_idle, bta_csip_st_w4_conn,
bta_csip_st_w4_sec, bta_csip_st_connected,
bta_csip_st_disconnecting};
/*******************************************************************************
*
* Function bta_csip_sm_execute
*
* Description API to execute state operation.
*
* Returns void
*
******************************************************************************/
void bta_csip_sm_execute(tBTA_CSIP_DEV_CB* p_cb, uint16_t event,
tBTA_CSIP_REQ_DATA* p_data) {
tBTA_CSIP_ST_TBL state_table;
uint8_t action;
if (!p_cb) {
APPL_TRACE_ERROR("%s: Device not found. Return.", __func__);
return;
}
state_table = bta_csip_st_tbl[p_cb->state];
event &= 0xff;
p_cb->state = state_table[event][BTA_CSIP_NEXT_STATE];
APPL_TRACE_DEBUG("%s: Next State = %d(%s) event = %04x(%s)", __func__,
p_cb->state, bta_csip_state_code(p_cb->state), event,
bta_csip_evt_code(event));
action = state_table[event][BTA_CSIP_ACTION];
APPL_TRACE_DEBUG("%s: action = %d", __func__, action);
if (action != BTA_CSIP_IGNORE) {
(*bta_csip_action[action])(p_cb, p_data);
}
}
/*******************************************************************************
*
* Function bta_csip_hdl_event
*
* Description CSIP client main event handling function.
*
* Returns void
*
******************************************************************************/
bool bta_csip_hdl_event(BT_HDR* p_msg) {
tBTA_CSIP_DEV_CB* dev_cb = NULL;
APPL_TRACE_DEBUG("%s: Event: %04x", __func__, p_msg->event);
switch (p_msg->event) {
case BTA_CSIP_API_ENABLE_EVT:
bta_csip_api_enable(((tBTA_CSIP_ENABLE *)p_msg)->p_cback);
break;
case BTA_CSIP_API_DISABLE_EVT:
bta_csip_api_disable();
break;
case BTA_CSIP_DISC_CMPL_EVT:
bta_csip_gatt_disc_cmpl_act((tBTA_CSIP_DISC_SET *)p_msg);
break;
case BTA_CSIP_SET_LOCK_VALUE_EVT:
bta_csip_process_set_lock_act(((tBTA_CSIP_LOCK_PARAMS*)p_msg)->lock_req);
break;
default:
if (p_msg->event == BTA_CSIP_API_OPEN_EVT) {
RawAddress bd_addr = ((tBTA_CSIP_API_CONN *)p_msg)->bd_addr;
dev_cb = bta_csip_find_dev_cb_by_bda(bd_addr);
if (!dev_cb) {
dev_cb = bta_csip_create_dev_cb_for_bda(bd_addr);
APPL_TRACE_DEBUG("%s: Created Device CB for device: %s",
__func__, bd_addr.ToString().c_str());
}
} else if (p_msg->event == BTA_CSIP_API_CLOSE_EVT) {
dev_cb = bta_csip_find_dev_cb_by_bda(((tBTA_CSIP_API_CONN *)p_msg)->bd_addr);
}
bta_csip_sm_execute(dev_cb, p_msg->event, (tBTA_CSIP_REQ_DATA*)p_msg);
}
return (true);
}
/*******************************************************************************
*
* Function bta_csip_evt_code
*
* Description returns event name in string format
*
* Returns string representation of event code
*
******************************************************************************/
static const char* bta_csip_evt_code(uint16_t evt_code) {
evt_code = (BTA_ID_GROUP << 8) | evt_code;
switch (evt_code) {
case BTA_CSIP_API_OPEN_EVT:
return "BTA_CSIP_API_OPEN_EVT";
case BTA_CSIP_API_CLOSE_EVT:
return "BTA_CSIP_API_CLOSE_EVT";
case BTA_CSIP_GATT_OPEN_EVT:
return "BTA_CSIP_GATT_OPEN_EVT";
case BTA_CSIP_GATT_CLOSE_EVT:
return "BTA_CSIP_GATT_CLOSE_EVT";
case BTA_CSIP_OPEN_FAIL_EVT:
return "BTA_CSIP_OPEN_FAIL_EVT";
case BTA_CSIP_OPEN_CMPL_EVT:
return "BTA_CSIP_OPEN_CMPL_EVT";
case BTA_CSIP_START_ENC_EVT:
return "BTA_CSIP_START_ENC_EVT";
case BTA_CSIP_ENC_CMPL_EVT:
return "BTA_CSIP_ENC_CMPL_EVT";
case BTA_CSIP_API_ENABLE_EVT:
return "BTA_CSIP_API_ENABLE_EVT";
case BTA_CSIP_API_DISABLE_EVT:
return "BTA_CSIP_API_DISABLE_EVT";
case BTA_CSIP_SET_LOCK_VALUE_EVT:
return "BTA_CSIP_SET_LOCK_VALUE_EVT";
default:
return "Unknown CSIP event code";
}
}
/*******************************************************************************
*
* Function bta_csip_state_code
*
* Description returns state name in string format
*
* Returns string representation of connection state
*
******************************************************************************/
static const char* bta_csip_state_code(tBTA_CSIP_STATE state) {
switch (state) {
case BTA_CSIP_IDLE_ST:
return "BTA_CSIP_IDLE_ST";
case BTA_CSIP_W4_CONN_ST:
return "BTA_CSIP_W4_CONN_ST";
case BTA_CSIP_W4_SEC:
return "BTA_CSIP_W4_SEC";
case BTA_CSIP_CONN_ST:
return "BTA_CSIP_CONN_ST";
case BTA_CSIP_DISCONNECTING_ST:
return "BTA_CSIP_DISCONNECTING_ST";
default:
return "Incorrect State";
}
}