void anps_send_ntf_status_update_ind(struct anps_idx_env_tag *idx_env, uint8_t alert_type) { // Send the message to the application struct anps_ntf_status_update_ind *ind = KE_MSG_ALLOC(ANPS_NTF_STATUS_UPDATE_IND, idx_env->con_info.appid, idx_env->con_info.prf_id, anps_ntf_status_update_ind); ind->conhdl = idx_env->con_info.conhdl; ind->alert_type = alert_type; ind->ntf_ccc_cfg = ANPS_IS_ALERT_ENABLED(idx_env, alert_type) ? PRF_CLI_START_NTF : PRF_CLI_STOP_NTFIND; if (alert_type == ANP_NEW_ALERT) { ind->cat_ntf_cfg.cat_id_mask_0 = (uint8_t)(idx_env->ntf_new_alert_cfg & 0x00FF); ind->cat_ntf_cfg.cat_id_mask_1 = (uint8_t)((idx_env->ntf_new_alert_cfg & 0xFF00) >> 8); }
/** **************************************************************************************** * @brief Handles reception of the @ref GATTC_WRITE_CMD_IND message. * @param[in] msgid Id of the message received (probably unused). * @param[in] param Pointer to the parameters of the message. * @param[in] dest_id ID of the receiving task instance (probably unused). * @param[in] src_id ID of the sending task instance. * @return If the message was consumed or not. **************************************************************************************** */ static int gattc_write_cmd_ind_handler(ke_msg_id_t const msgid, struct gattc_write_cmd_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); // Get the address of the environment struct anps_idx_env_tag *anps_idx_env = PRF_CLIENT_GET_ENV(KE_BUILD_ID(dest_id, conidx), anps_idx); // Check if the connection exists if (anps_idx_env != NULL) { // Status uint8_t status = PRF_ERR_OK; /* * --------------------------------------------------------------------------------------------- * New Alert Client Characteristic Configuration Descriptor Value - Write * --------------------------------------------------------------------------------------------- */ /* * --------------------------------------------------------------------------------------------- * Unread Status Alert Client Characteristic Configuration Descriptor Value - Write * --------------------------------------------------------------------------------------------- */ if ((param->handle == (anps_env.ans_shdl + ANS_IDX_NEW_ALERT_CFG)) || (param->handle == (anps_env.ans_shdl + ANS_IDX_UNREAD_ALERT_STATUS_CFG))) { // Received configuration value uint16_t ntf_cfg = co_read16p(¶m->value[0]); if (ntf_cfg <= PRF_CLI_START_NTF) { // Alert type uint8_t alert_type = (param->handle == (anps_env.ans_shdl + ANS_IDX_NEW_ALERT_CFG)) ? ANP_NEW_ALERT : ANP_UNREAD_ALERT; // Set the value of the Alert Status Client Characteristic Configuration Descriptor (Readable) attmdb_att_set_value(param->handle, sizeof(uint16_t), (uint8_t *)&ntf_cfg); // Update the status in the environment if (ntf_cfg == PRF_CLI_START_NTF) { ANPS_ENABLE_ALERT(anps_idx_env, alert_type); } else { ANPS_DISABLE_ALERT(anps_idx_env, alert_type); } // Inform the HL that the notification configuration status has been written anps_send_ntf_status_update_ind(anps_idx_env, alert_type); } else { status = PRF_APP_ERROR; } } /* * --------------------------------------------------------------------------------------------- * Alert Notification Control Point Characteristic Value - Write * --------------------------------------------------------------------------------------------- */ else if (param->handle == (anps_env.ans_shdl + ANS_IDX_ALERT_NTF_CTNL_PT_VAL)) { do { // Check the command ID value if (param->value[0] >= CMD_ID_NB) { status = ANP_CMD_NOT_SUPPORTED; break; } // Check the category ID value if ((param->value[1] >= CAT_ID_NB) && (param->value[1] != CAT_ID_ALL_SUPPORTED_CAT)) { status = ANP_CAT_NOT_SUPPORTED; break; } if (param->value[1] < CAT_ID_NB) { // New Alert if ((param->value[0] % 2) == 0) { // Check if the category is supported if (!ANPS_IS_NEW_ALERT_CATEGORY_SUPPORTED(param->value[1])) { status = ANP_CAT_NOT_SUPPORTED; break; } } // Unread Alert Status else { // Check if the category is supported if (!ANPS_IS_UNREAD_ALERT_CATEGORY_SUPPORTED(param->value[1])) { status = ANP_CAT_NOT_SUPPORTED; break; } } } // React according to the received command id value switch (param->value[0]) { // Enable New Alert Notification case (CMD_ID_EN_NEW_IN_ALERT_NTF): { if (param->value[1] != CAT_ID_ALL_SUPPORTED_CAT) { // Enable sending of new alert notification for the specified category ANPS_ENABLE_NEW_ALERT_CATEGORY(param->value[1], anps_idx_env); } else { // Enable sending of new alert notification for all supported category anps_idx_env->ntf_new_alert_cfg |= anps_env.supp_new_alert_cat; } anps_send_ntf_status_update_ind(anps_idx_env, ANP_NEW_ALERT); } break; // Enable Unread Alert Status Notification case (CMD_ID_EN_UNREAD_CAT_STATUS_NTF): { if (param->value[1] != CAT_ID_ALL_SUPPORTED_CAT) { // Enable sending of unread alert notification for the specified category ANPS_ENABLE_UNREAD_ALERT_CATEGORY(param->value[1], anps_idx_env); } else { // Enable sending of unread alert notification for all supported category anps_idx_env->ntf_unread_alert_cfg |= anps_env.supp_unread_alert_cat; } anps_send_ntf_status_update_ind(anps_idx_env, ANP_UNREAD_ALERT); } break; // Disable New Alert Notification case (CMD_ID_DIS_NEW_IN_ALERT_NTF): { if (param->value[1] != CAT_ID_ALL_SUPPORTED_CAT) { // Disable sending of new alert notification for the specified category ANPS_DISABLE_NEW_ALERT_CATEGORY(param->value[1], anps_idx_env); } else { // Disable sending of new alert notification for all supported category anps_idx_env->ntf_new_alert_cfg &= ~anps_env.supp_new_alert_cat; } anps_send_ntf_status_update_ind(anps_idx_env, ANP_NEW_ALERT); } break; // Disable Unread Alert Status Notification case (CMD_ID_DIS_UNREAD_CAT_STATUS_NTF): { if (param->value[1] != CAT_ID_ALL_SUPPORTED_CAT) { // Disable sending of unread alert notification for the specified category ANPS_DISABLE_UNREAD_ALERT_CATEGORY(param->value[1], anps_idx_env); } else { // Enable sending of unread alert notification for all supported category anps_idx_env->ntf_unread_alert_cfg &= ~anps_env.supp_unread_alert_cat; } anps_send_ntf_status_update_ind(anps_idx_env, ANP_UNREAD_ALERT); } break; // Notify New Alert immediately case (CMD_ID_NTF_NEW_IN_ALERT_IMM): { // Check if sending of notification is enabled if (ANPS_IS_ALERT_ENABLED(anps_idx_env, ANP_NEW_ALERT)) { if (param->value[1] == CAT_ID_ALL_SUPPORTED_CAT) { // Check if at least one category can be notified if (anps_idx_env->ntf_new_alert_cfg != 0) { anps_send_ntf_immediate_req_ind(anps_idx_env, ANP_NEW_ALERT, CAT_ID_ALL_SUPPORTED_CAT); } } else { // Check if sending of notifications has been enabled for the specified category. if (ANPS_IS_NEW_ALERT_CATEGORY_ENABLED(param->value[1], anps_idx_env)) { anps_send_ntf_immediate_req_ind(anps_idx_env, ANP_NEW_ALERT, param->value[1]); } } } } break; // Notify Unread Alert Status immediately case (CMD_ID_NTF_UNREAD_CAT_STATUS_IMM): { if (ANPS_IS_ALERT_ENABLED(anps_idx_env, ANP_UNREAD_ALERT)) { // Check if sending of notification is enabled if (ANPS_IS_ALERT_ENABLED(anps_idx_env, ANP_UNREAD_ALERT)) { if (param->value[1] == CAT_ID_ALL_SUPPORTED_CAT) { // Check if at least one category can be notified if (anps_idx_env->ntf_unread_alert_cfg != 0) { anps_send_ntf_immediate_req_ind(anps_idx_env, ANP_UNREAD_ALERT, CAT_ID_ALL_SUPPORTED_CAT); } } else { // Check if sending of notifications has been enabled for the specified category. if (ANPS_IS_UNREAD_ALERT_CATEGORY_ENABLED(param->value[1], anps_idx_env)) { anps_send_ntf_immediate_req_ind(anps_idx_env, ANP_UNREAD_ALERT, param->value[1]); } } } } } break; default: { ASSERT_ERR(0); } break; } } while (0); } else { ASSERT_ERR(0); } // Send write response atts_write_rsp_send(anps_idx_env->con_info.conidx, param->handle, status); } // else ignore the message return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref ANPS_NTF_ALERT_CMD 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. * @param[in] src_id ID of the sending task instance. * @return If the message was consumed or not. **************************************************************************************** */ static int anps_ntf_alert_cmd_handler(ke_msg_id_t const msgid, struct anps_ntf_alert_cmd const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Message Status uint8_t msg_status = KE_MSG_CONSUMED; // Task environment struct anps_idx_env_tag *anps_idx_env = PRF_CLIENT_GET_ENV(dest_id, anps_idx); if (anps_idx_env != NULL) { // Status uint8_t status = PRF_ERR_OK; // Category ID uint8_t cat_id; // Is the category supported ? bool cat_supported; // Handle uint16_t handle; do { // Check the provided connection handle value if (anps_idx_env->con_info.conidx != gapc_get_conidx(param->conhdl)) { status = PRF_ERR_INVALID_PARAM; break; } if (ke_state_get(dest_id) == ANPS_BUSY) { // The message will be handled once the current operation is over msg_status = KE_MSG_NO_FREE; break; } ASSERT_ERR(ke_state_get(dest_id) == ANPS_CONNECTED); // Check the operation code, get the category ID. if (param->operation == ANPS_UPD_NEW_ALERT_OP_CODE) { // Check the length of the string info value if (param->value.new_alert.info_str_len > ANS_NEW_ALERT_STRING_INFO_MAX_LEN) { status = PRF_ERR_INVALID_PARAM; break; } // Get the category ID cat_id = param->value.new_alert.cat_id; // Check if the category is supported cat_supported = ANPS_IS_NEW_ALERT_CATEGORY_SUPPORTED(cat_id); } else if (param->operation == ANPS_UPD_UNREAD_ALERT_STATUS_OP_CODE) { // Get the category ID cat_id = param->value.unread_alert_status.cat_id; // Check if the category is supported cat_supported = ANPS_IS_UNREAD_ALERT_CATEGORY_SUPPORTED(cat_id); } else { status = PRF_ERR_INVALID_PARAM; break; } // Check the category ID if ((cat_id >= CAT_ID_NB) || (!cat_supported)) { status = PRF_ERR_INVALID_PARAM; break; } if (param->operation == ANPS_UPD_NEW_ALERT_OP_CODE) { // Check if sending of notification is enabled for the provided category if (ANPS_IS_NEW_ALERT_CATEGORY_ENABLED(cat_id, anps_idx_env) && ANPS_IS_ALERT_ENABLED(anps_idx_env, ANP_NEW_ALERT)) { handle = anps_env.ans_shdl + ANS_IDX_NEW_ALERT_VAL; // Notification can be sent, set the value in the database attmdb_att_set_value(handle, 2 + param->value.new_alert.info_str_len, (uint8_t *)¶m->value.new_alert.cat_id); } else { status = PRF_ERR_NTF_DISABLED; break; } } else { if (ANPS_IS_UNREAD_ALERT_CATEGORY_ENABLED(cat_id, anps_idx_env) && ANPS_IS_ALERT_ENABLED(anps_idx_env, ANP_UNREAD_ALERT)) { handle = anps_env.ans_shdl + ANS_IDX_UNREAD_ALERT_STATUS_VAL; attmdb_att_set_value(handle, sizeof(struct anp_unread_alert), (uint8_t *)¶m->value.unread_alert_status); } else { status = PRF_ERR_NTF_DISABLED; break; } } // Configure the environment anps_idx_env->operation = param->operation; // The notification can be sent, send the notification prf_server_send_event((prf_env_struct *)anps_idx_env, false, handle); // Go to Busy state ke_state_set(dest_id, ANPS_BUSY); } while (0); if (status != PRF_ERR_OK) { // Send response to application anps_send_cmp_evt(anps_idx_env->con_info.prf_id, anps_idx_env->con_info.appid, gapc_get_conhdl(anps_idx_env->con_info.conidx), param->operation, status); } } else { // Send response to application anps_send_cmp_evt(dest_id, src_id, param->conhdl, param->operation, PRF_ERR_REQ_DISALLOWED); } return (int)msg_status; }