pinebuds/services/ble_app/app_main/app_task.c

1236 lines
40 KiB
C

/***************************************************************************
*
* Copyright 2015-2019 BES.
* All rights reserved. All unpublished rights reserved.
*
* No part of this work may be used or reproduced in any form or by any
* means, or stored in a database or retrieval system, without prior written
* permission of BES.
*
* Use of this work is governed by a license granted by BES.
* This work contains confidential and proprietary information of
* BES. which is protected by copyright, trade secret,
* trademark and other intellectual property rights.
*
****************************************************************************/
/**
****************************************************************************************
* @addtogroup APPTASK
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "rwip_config.h" // SW configuration
#if (BLE_APP_PRESENT)
#include "app_task.h" // Application Manager Task API
#include "app.h" // Application Manager Definition
#include "gapc_task.h" // GAP Controller Task API
#include "gapm_task.h" // GAP Manager Task API
#include "arch.h" // Platform Definitions
#include <string.h>
#include "ke_timer.h" // Kernel timer
#include "gattc_task.h"
#include "app_ble_include.h"
#include "../l2cm/l2cm_int.h"
#include "co_utils.h"
#if (BLE_APP_SEC)
#include "app_sec.h" // Security Module Definition
#endif //(BLE_APP_SEC)
#if (BLE_APP_HT)
#include "app_ht.h" // Health Thermometer Module Definition
#include "htpt_task.h"
#endif //(BLE_APP_HT)
#if (BLE_APP_DIS)
#include "app_dis.h" // Device Information Module Definition
#include "diss_task.h"
#endif //(BLE_APP_DIS)
#if (BLE_APP_BATT)
#include "app_batt.h" // Battery Module Definition
#include "bass_task.h"
#endif //(BLE_APP_BATT)
#if (BLE_APP_HID)
#include "app_hid.h" // HID Module Definition
#include "hogpd_task.h"
#endif //(BLE_APP_HID)
#if (BLE_APP_HR)
#include "app_hrps.h"
#endif
#if (BLE_APP_VOICEPATH)
#include "app_voicepath_ble.h" // Voice Path Module Definition
#endif // (BLE_APP_VOICEPATH)
#if (BLE_APP_DATAPATH_SERVER)
#include "app_datapath_server.h" // Data Path Server Module Definition
#include "datapathps_task.h"
#endif // (BLE_APP_DATAPATH_SERVER)
#if (BLE_APP_AI_VOICE)
#include "app_ai_ble.h" // ama Voice Module Definition
#endif // (BLE_APP_AI_VOICE)
#if (BLE_APP_OTA)
#include "app_ota.h" // OTA Module Definition
#include "ota_task.h"
#endif // (BLE_APP_OTA)
#if (BLE_APP_TOTA)
#include "app_tota_ble.h" // TOTA Module Definition
#include "tota_task.h"
#endif // (BLE_APP_TOTA)
#if (BLE_APP_ANCC)
#include "app_ancc.h" // ANC Module Definition
#include "app_ancc_task.h"
#include "ancc_task.h"
#endif // (BLE_APP_ANCC)
#if (BLE_APP_AMS)
#include "app_amsc.h" // AMS Module Definition
#include "app_amsc_task.h"
#include "amsc_task.h"
#endif // (BLE_APP_AMS)
#if (BLE_APP_GFPS)
#include "app_gfps.h" // google fast pair service provider
#include "gfps_provider_task.h"
#endif // (BLE_APP_GFPS)
#ifdef BLE_APP_AM0
#include "am0_app.h" // Audio Mode 0 Application
#endif //defined(BLE_APP_AM0)
#if (DISPLAY_SUPPORT)
#include "app_display.h" // Application Display Definition
#endif //(DISPLAY_SUPPORT)
#include "bt_drv_interface.h"
#include "ble_app_dbg.h"
#include "nvrecord_ble.h"
#include "app_fp_rfcomm.h"
#if (BLE_APP_TILE)
#include "tile_target_ble.h"
#include "tile_gatt_server.h"
#endif
/*
* LOCAL FUNCTION DEFINITIONS
****************************************************************************************
*/
#define APP_CONN_PARAM_INTERVEL_MIN (20)
uint8_t ble_stack_ready = 0;
extern bool app_factorymode_get(void);
static uint8_t appm_get_handler(const struct ke_state_handler *handler_list,
ke_msg_id_t msgid,
void *param,
ke_task_id_t src_id)
{
// Counter
uint8_t counter;
// Get the message handler function by parsing the message table
for (counter = handler_list->msg_cnt; 0 < counter; counter--)
{
struct ke_msg_handler handler = (struct ke_msg_handler)(*(handler_list->msg_table + counter - 1));
if ((handler.id == msgid) ||
(handler.id == KE_MSG_DEFAULT_HANDLER))
{
// If handler is NULL, message should not have been received in this state
ASSERT_ERR(handler.func);
return (uint8_t)(handler.func(msgid, param, TASK_APP, src_id));
}
}
// If we are here no handler has been found, drop the message
return (KE_MSG_CONSUMED);
}
/*
* MESSAGE HANDLERS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief
*
* @param[in] msgid Id of the message received.
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance (TASK_GAP).
* @param[in] src_id ID of the sending task instance.
*
* @return If the message was consumed or not.
****************************************************************************************
*/
static int app_adv_timeout_handler(ke_msg_id_t const msgid,
void const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
#if (BLE_APP_HID)
#else
// Stop advertising
appm_stop_advertising();
#endif
return (KE_MSG_CONSUMED);
}
/**
****************************************************************************************
* @brief Handles ready indication from the GAP. - Reset the stack
*
* @param[in] msgid Id of the message received.
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance (TASK_GAP).
* @param[in] src_id ID of the sending task instance.
*
* @return If the message was consumed or not.
****************************************************************************************
*/
static int gapm_device_ready_ind_handler(ke_msg_id_t const msgid,
void const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
if (ble_stack_ready)
{
return KE_MSG_CONSUMED;
}
#ifdef __FACTORY_MODE_SUPPORT__
if (app_factorymode_get())
{
return (KE_MSG_CONSUMED);
}
#endif
BLE_APP_FUNC_ENTER();
// Application has not been initialized
ASSERT_ERR(ke_state_get(dest_id) == APPM_INIT);
ble_stack_ready = 1;
// Reset the stack
struct gapm_reset_cmd* cmd = KE_MSG_ALLOC(GAPM_RESET_CMD,
TASK_GAPM, TASK_APP,
gapm_reset_cmd);
cmd->operation = GAPM_RESET;
ke_msg_send(cmd);
BLE_APP_FUNC_LEAVE();
return (KE_MSG_CONSUMED);
}
/**
****************************************************************************************
* @brief Handles GAP manager command complete events.
*
* @param[in] msgid Id of the message received.
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance (TASK_GAP).
* @param[in] src_id ID of the sending task instance.
*
* @return If the message was consumed or not.
****************************************************************************************
*/
static int gapm_cmp_evt_handler(ke_msg_id_t const msgid,
struct gapm_cmp_evt const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
BLE_APP_FUNC_ENTER();
BLE_APP_DBG("param->operation: %d status is %d app_env.next_svc is %d",
param->operation, param->status, app_env.next_svc);
switch(param->operation)
{
// Reset completed
case (GAPM_RESET):
{
if(param->status == GAP_ERR_NO_ERROR)
{
#if (BLE_APP_HID)
app_hid_start_mouse();
#endif //(BLE_APP_HID)
// Set Device configuration
struct gapm_set_dev_config_cmd* cmd = KE_MSG_ALLOC(GAPM_SET_DEV_CONFIG_CMD,
TASK_GAPM, TASK_APP,
gapm_set_dev_config_cmd);
// Set the operation
cmd->operation = GAPM_SET_DEV_CONFIG;
// Set the device role - Peripheral
cmd->role = GAP_ROLE_ALL;
// Set Data length parameters
cmd->sugg_max_tx_octets = APP_MAX_TX_OCTETS;
cmd->sugg_max_tx_time = APP_MAX_TX_TIME;
cmd->pairing_mode = GAPM_PAIRING_LEGACY;
#ifdef CFG_SEC_CON
cmd->pairing_mode |= GAPM_PAIRING_SEC_CON;
#endif
cmd->max_mtu = 512;
cmd->att_cfg = 0;
cmd->att_cfg |= GAPM_MASK_ATT_SVC_CHG_EN;
#if (BLE_APP_HID)
// Enable Slave Preferred Connection Parameters present
cmd->att_cfg |= GAPM_MASK_ATT_SLV_PREF_CON_PAR_EN;
#endif //(BLE_APP_HID)
#ifdef BLE_APP_AM0
cmd->addr_type = GAPM_CFG_ADDR_HOST_PRIVACY;
cmd->audio_cfg = GAPM_MASK_AUDIO_AM0_SUP;
#endif // BLE_APP_AM0
// load IRK
memcpy(cmd->irk.key, app_env.loc_irk, KEY_LEN);
// Send message
ke_msg_send(cmd);
}
else
{
ASSERT_ERR(0);
}
}
break;
case (GAPM_PROFILE_TASK_ADD):
{
// ASSERT_INFO(param->status == GAP_ERR_NO_ERROR, param->operation, param->status);
// Add the next requested service
if (!appm_add_svc())
{
// Go to the ready state
ke_state_set(TASK_APP, APPM_READY);
// No more service to add
app_ble_system_ready();
}
}
break;
// Device Configuration updated
case (GAPM_SET_DEV_CONFIG):
{
ASSERT_INFO(param->status == GAP_ERR_NO_ERROR, param->operation, param->status);
// Go to the create db state
ke_state_set(TASK_APP, APPM_CREATE_DB);
// Add the first required service in the database
// and wait for the PROFILE_ADDED_IND
appm_add_svc();
}
break;
case (GAPM_ADV_NON_CONN):
case (GAPM_ADV_UNDIRECT):
#if !(BLE_APP_HID)
case (GAPM_ADV_DIRECT):
#endif// !(BLE_APP_HID)
case (GAPM_ADV_DIRECT_LDC):
{
LOG_I("adv evt cmp status 0x%x", param->status);
ASSERT(GAP_ERR_ADV_DATA_INVALID != param->status,
"The BLE adv data or scan rsp data is invalid! Better check their length.");
if (GAP_ERR_CANCELED == param->status)
{
app_advertising_stopped();
}
else if (GAP_ERR_NO_ERROR == param->status)
{
if (ke_state_get(TASK_APP) == APPM_ADVERTISING)
{
app_advertising_started();
}
else
{
app_advertising_stopped();
}
}
else
{
app_advertising_starting_failed();
}
break;
}
case GAPM_UPDATE_ADVERTISE_DATA:
{
app_adv_data_updated();
break;
}
case GAPM_SCAN_ACTIVE:
case GAPM_SCAN_PASSIVE:
{
LOG_I("scan evt cmp status %d", param->status);
if (GAP_ERR_CANCELED == param->status)
{
app_scanning_stopped();
}
else if (GAP_ERR_NO_ERROR == param->status)
{
app_scanning_started();
}
else
{
app_scanning_starting_failed();
}
}
break;
case GAPM_CONNECTION_DIRECT:
case GAPM_CONNECTION_AUTO:
case GAPM_CONNECTION_SELECTIVE:
case GAPM_CONNECTION_NAME_REQUEST:
case GAPM_CONNECTION_GENERAL:
{
BLE_GAP_DBG("connecting cmp status %d", param->status);
if (GAP_ERR_CANCELED == param->status)
{
app_connecting_stopped();
}
else if (GAP_ERR_NO_ERROR == param->status)
{
app_connecting_started();
}
else
{
app_connecting_failed();
}
}
break;
#if (BLE_APP_HID)
case (GAPM_ADV_DIRECT):
{
if (param->status == GAP_ERR_TIMEOUT)
{
ke_state_set(TASK_APP, APPM_READY);
}
} break;
#endif //(BLE_APP_HID)
case GAPM_RESOLV_ADDR:
{
LOG_I("Resolve result %d", param->status);
if (GAP_ERR_NOT_FOUND == param->status)
{
appm_random_ble_addr_solved(false, NULL);
}
break;
}
default:
{
// Drop the message
}
break;
}
BLE_APP_FUNC_LEAVE();
return (KE_MSG_CONSUMED);
}
static int gapc_get_dev_info_req_ind_handler(ke_msg_id_t const msgid,
struct gapc_get_dev_info_req_ind const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
switch(param->req)
{
case GAPC_DEV_NAME:
{
struct gapc_get_dev_info_cfm * cfm = KE_MSG_ALLOC_DYN(GAPC_GET_DEV_INFO_CFM,
src_id, dest_id,
gapc_get_dev_info_cfm, APP_DEVICE_NAME_MAX_LEN);
cfm->req = param->req;
cfm->info.name.length = appm_get_dev_name(cfm->info.name.value);
// Send message
ke_msg_send(cfm);
} break;
case GAPC_DEV_APPEARANCE:
{
// Allocate message
struct gapc_get_dev_info_cfm *cfm = KE_MSG_ALLOC(GAPC_GET_DEV_INFO_CFM,
src_id, dest_id,
gapc_get_dev_info_cfm);
cfm->req = param->req;
// Set the device appearance
#if (BLE_APP_HT)
// Generic Thermometer - TODO: Use a flag
cfm->info.appearance = 728;
#elif (BLE_APP_HID)
// HID Mouse
cfm->info.appearance = 962;
#else
// No appearance
cfm->info.appearance = 0;
#endif
// Send message
ke_msg_send(cfm);
} break;
case GAPC_DEV_SLV_PREF_PARAMS:
{
// Allocate message
struct gapc_get_dev_info_cfm *cfm = KE_MSG_ALLOC(GAPC_GET_DEV_INFO_CFM,
src_id, dest_id,
gapc_get_dev_info_cfm);
cfm->req = param->req;
// Slave preferred Connection interval Min
cfm->info.slv_params.con_intv_min = 8;
// Slave preferred Connection interval Max
cfm->info.slv_params.con_intv_max = 10;
// Slave preferred Connection latency
cfm->info.slv_params.slave_latency = 0;
// Slave preferred Link supervision timeout
cfm->info.slv_params.conn_timeout = 200; // 2s (500*10ms)
// Send message
ke_msg_send(cfm);
} break;
default: /* Do Nothing */ break;
}
return (KE_MSG_CONSUMED);
}
/**
****************************************************************************************
* @brief Handles GAPC_SET_DEV_INFO_REQ_IND message.
*
* @param[in] msgid Id of the message received.
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance (TASK_GAP).
* @param[in] src_id ID of the sending task instance.
*
* @return If the message was consumed or not.
****************************************************************************************
*/
static int gapc_set_dev_info_req_ind_handler(ke_msg_id_t const msgid,
struct gapc_set_dev_info_req_ind const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
// Set Device configuration
struct gapc_set_dev_info_cfm* cfm = KE_MSG_ALLOC(GAPC_SET_DEV_INFO_CFM, src_id, dest_id,
gapc_set_dev_info_cfm);
// Reject to change parameters
cfm->status = GAP_ERR_REJECTED;
cfm->req = param->req;
// Send message
ke_msg_send(cfm);
return (KE_MSG_CONSUMED);
}
static void POSSIBLY_UNUSED gapc_refresh_remote_dev_feature(uint8_t conidx)
{
// Send a GAPC_GET_INFO_CMD in order to read the device name characteristic value
struct gapc_get_info_cmd *p_cmd = KE_MSG_ALLOC(GAPC_GET_INFO_CMD,
KE_BUILD_ID(TASK_GAPC, conidx), TASK_GAPM,
gapc_get_info_cmd);
// request peer device name.
p_cmd->operation = GAPC_GET_PEER_FEATURES;
// send command
ke_msg_send(p_cmd);
}
static void POSSIBLY_UNUSED gpac_exchange_data_packet_length(uint8_t conidx)
{
#if defined(CHIP_BEST2300) || defined(CHIP_BEST2300P)
return;
#endif
struct gapc_set_le_pkt_size_cmd *set_le_pakt_size_req = KE_MSG_ALLOC(GAPC_SET_LE_PKT_SIZE_CMD,
KE_BUILD_ID(TASK_GAPC, conidx),
TASK_APP,
gapc_set_le_pkt_size_cmd);
set_le_pakt_size_req->operation = GAPC_SET_LE_PKT_SIZE;
set_le_pakt_size_req->tx_octets = APP_MAX_TX_OCTETS;
set_le_pakt_size_req->tx_time = APP_MAX_TX_TIME;
// Send message
ke_msg_send(set_le_pakt_size_req);
}
static int gapc_peer_features_ind_handler(ke_msg_id_t const msgid,
struct gapc_peer_features_ind* param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
LOG_I("Peer dev feature is:");
DUMP8("0x%02x ", param->features, GAP_LE_FEATS_LEN);
uint8_t conidx = KE_IDX_GET(src_id);
if (param->features[0] & GAPC_EXT_DATA_LEN_MASK)
{
gpac_exchange_data_packet_length(conidx);
}
return (KE_MSG_CONSUMED);
}
void app_exchange_remote_feature(uint8_t conidx)
{
APP_BLE_CONN_CONTEXT_T *pContext = &(app_env.context[conidx]);
LOG_I("connectStatus:%d, isFeatureExchanged:%d, isGotSolvedBdAddr:%d",
pContext->connectStatus,
pContext->isFeatureExchanged,
pContext->isGotSolvedBdAddr);
if ((BLE_CONNECTED == pContext->connectStatus) && !pContext->isFeatureExchanged)
{
if (pContext->isGotSolvedBdAddr)
{
gapc_refresh_remote_dev_feature(conidx);
pContext->isFeatureExchanged = true;
}
}
}
/**
****************************************************************************************
* @brief Handles connection complete event from the GAP. Enable all required profiles
*
* @param[in] msgid Id of the message received.
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance (TASK_GAP).
* @param[in] src_id ID of the sending task instance.
*
* @return If the message was consumed or not.
****************************************************************************************
*/
static int gapc_connection_req_ind_handler(ke_msg_id_t const msgid,
struct gapc_connection_req_ind* param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
uint8_t conidx = KE_IDX_GET(src_id);
APP_BLE_CONN_CONTEXT_T* pContext = &(app_env.context[conidx]);
pContext->connectStatus = BLE_CONNECTED;
APP_BLE_NEGOTIATED_CONN_PARAM_T connParam;
connParam.con_interval = param->con_interval;
connParam.sup_to= param->sup_to;
connParam.con_latency = param->con_latency;
app_ble_save_negotiated_conn_param(conidx, &connParam);
ke_state_set(dest_id, APPM_CONNECTED);
app_env.conn_cnt++;
if (app_is_resolving_ble_bd_addr())
{
LOG_I("A ongoing ble addr solving is in progress, refuse the new connection.");
appm_disconnect(conidx);
return KE_MSG_CONSUMED;
}
LOG_I("[CONNECT]device info:");
LOG_I("peer addr:");
DUMP8("%02x ", param->peer_addr.addr, 6);
LOG_I("peer addr type:%d", param->peer_addr_type);
LOG_I("connection index:%d, isGotSolvedBdAddr:%d", conidx, pContext->isGotSolvedBdAddr);
LOG_I("conn interval:%d, timeout:%d", param->con_interval, param->sup_to);
BLE_APP_FUNC_ENTER();
// Check if the received Connection Handle was valid
if (conidx != GAP_INVALID_CONIDX)
{
pContext->peerAddrType = param->peer_addr_type;
memcpy(pContext->bdAddr, param->peer_addr.addr, BD_ADDR_LEN);
// Retrieve the connection info from the parameters
pContext->conhdl = param->conhdl;
if (BLE_RANDOM_ADDR == pContext->peerAddrType)
{
pContext->isGotSolvedBdAddr = false;
}
else
{
pContext->isGotSolvedBdAddr = true;
}
// Clear the advertising timeout timer
if (ke_timer_active(APP_ADV_TIMEOUT_TIMER, TASK_APP))
{
ke_timer_clear(APP_ADV_TIMEOUT_TIMER, TASK_APP);
}
#if (BLE_APP_SEC)
app_sec_reset_env_on_connection();
#endif
// Send connection confirmation
struct gapc_connection_cfm *cfm = KE_MSG_ALLOC(GAPC_CONNECTION_CFM,
KE_BUILD_ID(TASK_GAPC, conidx), TASK_APP,
gapc_connection_cfm);
#if (BLE_APP_SEC)
cfm->auth = app_sec_get_bond_status() ? BLE_AUTHENTICATION_LEVEL : GAP_AUTH_REQ_NO_MITM_NO_BOND;
#else // !(BLE_APP_SEC)
cfm->auth = GAP_AUTH_REQ_NO_MITM_NO_BOND;
#endif // (BLE_APP_SEC)
// Send the message
ke_msg_send(cfm);
// We are now in connected State
ke_state_set(dest_id, APPM_CONNECTED);
app_exchange_remote_feature(conidx);
app_ble_connected_evt_handler(conidx, param->peer_addr.addr);
}
#if (BLE_APP_TILE)
app_tile_connected_evt_handler(conidx, param);
#endif
app_env.context[conidx].connInterval = param->con_interval;
app_ble_update_conn_param_mode(BLE_CONN_PARAM_MODE_DEFAULT, true);
BLE_APP_FUNC_LEAVE();
return (KE_MSG_CONSUMED);
}
/**
****************************************************************************************
* @brief Handles GAP controller command complete events.
*
* @param[in] msgid Id of the message received.
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance (TASK_GAP).
* @param[in] src_id ID of the sending task instance.
*
* @return If the message was consumed or not.
****************************************************************************************
*/
static int gapc_cmp_evt_handler(ke_msg_id_t const msgid,
struct gapc_cmp_evt const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
switch(param->operation)
{
case (GAPC_UPDATE_PARAMS):
{
if (param->status != GAP_ERR_NO_ERROR)
{
// appm_disconnect();
}
} break;
default:
{
} break;
}
return (KE_MSG_CONSUMED);
}
/**
****************************************************************************************
* @brief Handles disconnection complete event from the GAP.
*
* @param[in] msgid Id of the message received.
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance (TASK_GAP).
* @param[in] src_id ID of the sending task instance.
*
* @return If the message was consumed or not.
****************************************************************************************
*/
static int gapc_disconnect_ind_handler(ke_msg_id_t const msgid,
struct gapc_disconnect_ind const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
LOG_I("[DISCONNECT] device info:");
uint8_t conidx = KE_IDX_GET(src_id);
LOG_I("connection index:%d, reason:0x%x", conidx, param->reason);
app_env.context[conidx].isBdAddrResolvingInProgress = false;
app_env.context[conidx].isGotSolvedBdAddr = false;
app_env.context[conidx].connectStatus = BLE_DISCONNECTED;
app_env.context[conidx].isFeatureExchanged = false;
app_env.context[conidx].connInterval = 0;
l2cm_buffer_reset(conidx);
// Go to the ready state
ke_state_set(TASK_APP, APPM_READY);
app_env.conn_cnt--;
#if (BLE_VOICEPATH)
app_voicepath_disconnected_evt_handler(conidx);
#endif
#if (BLE_DATAPATH_SERVER)
app_datapath_server_disconnected_evt_handler(conidx);
#endif
#if (BLE_OTA)
app_ota_disconnected_evt_handler(conidx);
#endif
#if (BLE_APP_TOTA)
app_tota_disconnected_evt_handler(conidx);
#endif
#if(BLE_APP_GFPS)
app_gfps_disconnected_evt_handler(conidx);
#endif
#if (BLE_AI_VOICE)
app_ai_disconnected_evt_handler(conidx);
#endif
#if (BLE_APP_TILE)
app_tile_disconnected_evt_handler(conidx);
#endif
app_ble_disconnected_evt_handler(conidx);
app_ble_reset_conn_param_mode(conidx);
return (KE_MSG_CONSUMED);
}
static int gapm_profile_added_ind_handler(ke_msg_id_t const msgid,
struct gapm_profile_added_ind *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
LOG_I("prf_task_id %d is added.", param->prf_task_id);
return KE_MSG_CONSUMED;
}
/**
****************************************************************************************
* @brief Handles reception of all messages sent from the lower layers to the application
* @param[in] msgid Id of the message received.
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance
* @param[in] src_id ID of the sending task instance.
*
* @return If the message was consumed or not.
****************************************************************************************
*/
static int appm_msg_handler(ke_msg_id_t const msgid,
void *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
// Retrieve identifier of the task from received message
ke_task_id_t src_task_id = MSG_T(msgid);
// Message policy
uint8_t msg_pol = KE_MSG_CONSUMED;
switch (src_task_id)
{
case (TASK_ID_GAPC):
{
#if (BLE_APP_SEC)
if ((msgid >= GAPC_BOND_CMD) &&
(msgid <= GAPC_SECURITY_IND))
{
// Call the Security Module
msg_pol = appm_get_handler(&app_sec_table_handler, msgid, param, src_id);
}
#endif //(BLE_APP_SEC)
// else drop the message
} break;
case (TASK_ID_GATTC):
{
// Service Changed - Drop
} break;
#if (BLE_APP_HT)
case (TASK_ID_HTPT):
{
// Call the Health Thermometer Module
msg_pol = appm_get_handler(&app_ht_table_handler, msgid, param, src_id);
} break;
#endif //(BLE_APP_HT)
#if (BLE_APP_DIS)
case (TASK_ID_DISS):
{
// Call the Device Information Module
msg_pol = appm_get_handler(&app_dis_table_handler, msgid, param, src_id);
} break;
#endif //(BLE_APP_DIS)
#if (BLE_APP_HID)
case (TASK_ID_HOGPD):
{
// Call the HID Module
msg_pol = appm_get_handler(&app_hid_table_handler, msgid, param, src_id);
} break;
#endif //(BLE_APP_HID)
#if (BLE_APP_BATT)
case (TASK_ID_BASS):
{
// Call the Battery Module
msg_pol = appm_get_handler(&app_batt_table_handler, msgid, param, src_id);
} break;
#endif //(BLE_APP_BATT)
#if defined(BLE_APP_AM0)
case (TASK_ID_AM0):
{
// Call the Audio Mode 0 Module
msg_pol = appm_get_handler(&am0_app_table_handler, msgid, param, src_id);
} break;
case (TASK_ID_AM0_HAS):
{
// Call the Audio Mode 0 Module
msg_pol = appm_get_handler(&am0_app_has_table_handler, msgid, param, src_id);
} break;
#endif // defined(BLE_APP_AM0)
#if (BLE_APP_HR)
case (TASK_ID_HRPS):
{
// Call the HRPS Module
msg_pol = appm_get_handler(&app_hrps_table_handler, msgid, param, src_id);
} break;
#endif
#if (BLE_APP_VOICEPATH)
case (TASK_ID_VOICEPATH):
{
// Call the Voice Path Module
msg_pol = appm_get_handler(app_voicepath_ble_get_msg_handler_table(), msgid, param, src_id);
} break;
#endif //(BLE_APP_VOICEPATH)
#if (BLE_APP_DATAPATH_SERVER)
case (TASK_ID_DATAPATHPS):
{
// Call the Data Path Module
msg_pol = appm_get_handler(&app_datapath_server_table_handler, msgid, param, src_id);
} break;
#endif //(BLE_APP_DATAPATH_SERVER)
#if (BLE_APP_TILE)
case (TASK_ID_TILE):
{
// Call the TILE Module
msg_pol = appm_get_handler(&app_tile_table_handler, msgid, param, src_id);
}
break;
#endif
#if (BLE_APP_AI_VOICE)
case (TASK_ID_AI):
{
// Call the AI Voice
msg_pol = appm_get_handler(app_ai_table_handler, msgid, param, src_id);
} break;
#endif //(BLE_APP_AI_VOICE)
#if (BLE_APP_OTA)
case (TASK_ID_OTA):
{
// Call the OTA
msg_pol = appm_get_handler(&app_ota_table_handler, msgid, param, src_id);
} break;
#endif //(BLE_APP_OTA)
#if (BLE_APP_TOTA)
case (TASK_ID_TOTA):
{
// Call the TOTA
msg_pol = appm_get_handler(&app_tota_table_handler, msgid, param, src_id);
} break;
#endif //(BLE_APP_TOTA)
#if (BLE_APP_ANCC)
case (TASK_ID_ANCC):
{
// Call the ANCC
msg_pol = appm_get_handler(&app_ancc_table_handler, msgid, param, src_id);
} break;
#endif //(BLE_APP_ANCC)
#if (BLE_APP_AMS)
case (TASK_ID_AMSC):
{
// Call the AMS
msg_pol = appm_get_handler(&app_amsc_table_handler, msgid, param, src_id);
} break;
#endif //(BLE_APP_AMS)
#if (BLE_APP_GFPS)
case (TASK_ID_GFPSP):
{
msg_pol = appm_get_handler(&app_gfps_table_handler, msgid, param, src_id);
} break;
#endif
default:
{
#if (BLE_APP_HT)
if (msgid == APP_HT_MEAS_INTV_TIMER)
{
msg_pol = appm_get_handler(&app_ht_table_handler, msgid, param, src_id);
}
#endif //(BLE_APP_HT)
#if (BLE_APP_HID)
if (msgid == APP_HID_MOUSE_TIMEOUT_TIMER)
{
msg_pol = appm_get_handler(&app_hid_table_handler, msgid, param, src_id);
}
#endif //(BLE_APP_HID)
} break;
}
return (msg_pol);
}
static int gapm_adv_report_ind_handler(ke_msg_id_t const msgid,
struct gapm_adv_report_ind *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
app_adv_reported_scanned(param);
return KE_MSG_CONSUMED;
}
static int gapm_addr_solved_ind_handler(ke_msg_id_t const msgid,
struct gapm_addr_solved_ind *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
/// Indicate that resolvable random address has been solved
appm_random_ble_addr_solved(true, param->irk.key);
return KE_MSG_CONSUMED;
}
__STATIC int gattc_mtu_changed_ind_handler(ke_msg_id_t const msgid,
struct gattc_mtu_changed_ind const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
uint8_t conidx = KE_IDX_GET(src_id);
LOG_I("MTU has been negotiated as %d conidx %d", param->mtu, conidx);
#if (BLE_APP_DATAPATH_SERVER)
app_datapath_server_mtu_exchanged_handler(conidx, param->mtu);
#endif
#if (BLE_VOICEPATH)
app_voicepath_mtu_exchanged_handler(conidx, param->mtu);
#endif
#if (BLE_OTA)
app_ota_mtu_exchanged_handler(conidx, param->mtu);
#endif
#if (BLE_APP_TOTA)
app_tota_mtu_exchanged_handler(conidx, param->mtu);
#endif
#if (BLE_AI_VOICE)
app_ai_mtu_exchanged_handler(conidx, param->mtu);
#endif
return (KE_MSG_CONSUMED);
}
#define APP_CONN_PARAM_INTERVEL_MAX (30)
__STATIC int gapc_conn_param_update_req_ind_handler(ke_msg_id_t const msgid,
struct gapc_param_update_req_ind const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
bool accept = true;
ble_evnet_t event;
LOG_I("Receive the conn param update request: min %d max %d latency %d timeout %d",
param->intv_min,
param->intv_max,
param->latency,
param->time_out);
struct gapc_param_update_cfm* cfm = KE_MSG_ALLOC(GAPC_PARAM_UPDATE_CFM, src_id, dest_id,
gapc_param_update_cfm);
event.evt_type = BLE_CONN_PARAM_UPDATE_REQ_EVENT;
event.p.conn_param_update_req_handled.intv_min = param->intv_min;
event.p.conn_param_update_req_handled.intv_max = param->intv_max;
event.p.conn_param_update_req_handled.latency = param->latency;
event.p.conn_param_update_req_handled.time_out = param->time_out;
app_ble_core_global_handle(&event, &accept);
LOG_I("%s ret %d ", __func__, accept);
cfm->accept = accept;
#ifdef GFPS_ENABLED
// if fastpair doesn't have the requirement of finishing
// pairing in a really short period, just comment out this
// code block to avoid audio glitch if this event happens during music
// playback and interval is smaller than 15ms
if (param->intv_min < (uint16_t)(15/1.25))
{
LOG_I("accept");
cfm->accept = true;
fp_update_ble_connect_param_start(KE_IDX_GET(src_id));
}
else
{
fp_update_ble_connect_param_stop(KE_IDX_GET(src_id));
}
#endif
ke_msg_send(cfm);
return (KE_MSG_CONSUMED);
}
static int gapc_conn_param_updated_handler(ke_msg_id_t const msgid,
struct gapc_param_updated_ind* param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
uint8_t conidx = KE_IDX_GET(src_id);
LOG_I("Conidx %d conn parameter is updated as interval %d timeout %d",
conidx,
param->con_interval,
param->sup_to);
APP_BLE_NEGOTIATED_CONN_PARAM_T connParam;
connParam.con_interval = param->con_interval;
connParam.sup_to= param->sup_to;
connParam.con_latency = param->con_latency;
app_ble_save_negotiated_conn_param(conidx, &connParam);
#if (BLE_VOICEPATH)
app_voicepath_ble_conn_parameter_updated(conidx, param->con_interval, param->con_latency);
#endif
#if BLE_APP_TILE
app_tile_ble_conn_parameter_updated(conidx, param);
#endif
app_env.context[conidx].connInterval = param->con_interval;
if (param->con_interval >= 32)
{
if (app_ble_is_parameter_mode_enabled(conidx, BLE_CONN_PARAM_MODE_OTA))
{
app_ble_parameter_mode_clear(conidx, BLE_CONN_PARAM_MODE_OTA);
app_ble_update_conn_param_mode(BLE_CONN_PARAM_MODE_OTA_SLOWER, true);
}
else if (app_ble_is_parameter_mode_enabled(conidx, BLE_CONN_PARAM_MODE_AI_STREAM_ON))
{
app_ble_parameter_mode_clear(conidx, BLE_CONN_PARAM_MODE_AI_STREAM_ON);
app_ble_update_conn_param_mode(BLE_CONN_PARAM_MODE_AI_STREAM_ON, true);
}
}
return (KE_MSG_CONSUMED);
}
static int gapm_dev_addr_ind_handler(ke_msg_id_t const msgid,
struct gapm_dev_bdaddr_ind *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
ble_evnet_t event;
// Indicate that a new random BD address set in lower layers
LOG_I("New dev addr:");
DUMP8("%02x ", param->addr.addr.addr, 6);
#ifdef GFPS_ENABLED
app_fp_msg_send_updated_ble_addr();
app_gfps_update_random_salt();
#endif
event.evt_type = BLE_SET_RANDOM_BD_ADDR_EVENT;
event.p.set_random_bd_addr_handled.new_bdaddr = param->addr.addr.addr;
app_ble_core_global_handle(&event, NULL);
return KE_MSG_CONSUMED;
}
/*
* GLOBAL VARIABLES DEFINITION
****************************************************************************************
*/
/* Default State handlers definition. */
KE_MSG_HANDLER_TAB(appm)
{
// Note: first message is latest message checked by kernel so default is put on top.
{KE_MSG_DEFAULT_HANDLER, (ke_msg_func_t)appm_msg_handler},
{APP_ADV_TIMEOUT_TIMER, (ke_msg_func_t)app_adv_timeout_handler},
{GAPM_DEVICE_READY_IND, (ke_msg_func_t)gapm_device_ready_ind_handler},
{GAPM_CMP_EVT, (ke_msg_func_t)gapm_cmp_evt_handler},
{GAPC_GET_DEV_INFO_REQ_IND, (ke_msg_func_t)gapc_get_dev_info_req_ind_handler},
{GAPC_SET_DEV_INFO_REQ_IND, (ke_msg_func_t)gapc_set_dev_info_req_ind_handler},
{GAPC_CONNECTION_REQ_IND, (ke_msg_func_t)gapc_connection_req_ind_handler},
{GAPC_CMP_EVT, (ke_msg_func_t)gapc_cmp_evt_handler},
{GAPC_DISCONNECT_IND, (ke_msg_func_t)gapc_disconnect_ind_handler},
{GAPM_PROFILE_ADDED_IND, (ke_msg_func_t)gapm_profile_added_ind_handler},
{GATTC_MTU_CHANGED_IND, (ke_msg_func_t)gattc_mtu_changed_ind_handler},
{GAPC_PARAM_UPDATE_REQ_IND, (ke_msg_func_t)gapc_conn_param_update_req_ind_handler},
{GAPC_PARAM_UPDATED_IND, (ke_msg_func_t)gapc_conn_param_updated_handler},
{GAPM_ADV_REPORT_IND, (ke_msg_func_t)gapm_adv_report_ind_handler},
{GAPC_PEER_FEATURES_IND, (ke_msg_func_t)gapc_peer_features_ind_handler},
{GAPM_ADDR_SOLVED_IND, (ke_msg_func_t)gapm_addr_solved_ind_handler},
{GAPM_DEV_BDADDR_IND, (ke_msg_func_t)gapm_dev_addr_ind_handler},
};
/* Defines the place holder for the states of all the task instances. */
ke_state_t appm_state[APP_IDX_MAX];
const struct ke_task_desc TASK_DESC_APP = {appm_msg_handler_tab, appm_state, APP_IDX_MAX, ARRAY_LEN(appm_msg_handler_tab)};
#endif //(BLE_APP_PRESENT)
/// @} APPTASK