/** **************************************************************************************** * @brief Handles reception of the @ref SCPPC_SCAN_INTV_WD_WR_REQ 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 scppc_scan_intv_wd_wr_req_handler(ke_msg_id_t const msgid, struct scppc_scan_intv_wd_wr_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Get the address of the environment struct scppc_env_tag *scppc_env = PRF_CLIENT_GET_ENV(dest_id, scppc); if (param->conhdl == scppc_env->con_info.conhdl) { if (scppc_env->scps.chars[SCPPC_CHAR_SCAN_INTV_WD].char_hdl != ATT_INVALID_SEARCH_HANDLE) { if (src_id == scppc_env->con_info.appid) { // Save the last written value co_write16p(&scppc_env->scan_intv_wd.le_scan_intv, param->scan_intv_wd.le_scan_intv); co_write16p(&scppc_env->scan_intv_wd.le_scan_window, param->scan_intv_wd.le_scan_window); } // Send GATT Write Request prf_gatt_write(&scppc_env->con_info, scppc_env->scps.chars[SCPPC_CHAR_SCAN_INTV_WD].val_hdl, (uint8_t *)¶m->scan_intv_wd, sizeof(struct scan_intv_wd), GATT_WRITE_NO_RESPONSE); } //send app error indication for inexistent handle for this characteristic else { scppc_error_ind_send(scppc_env, PRF_ERR_INEXISTENT_HDL); } } else { scppc_error_ind_send(scppc_env, PRF_ERR_INVALID_PARAM); } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref HOGPBH_BOOT_KB_OUT_REPORT_WR_REQ 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 hogpbh_boot_report_wr_req_handler(ke_msg_id_t const msgid, struct hogpbh_boot_report_wr_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Descriptor handle uint16_t val_hdl = ATT_INVALID_SEARCH_HANDLE; // Status uint8_t status = PRF_ERR_OK; // Write Type uint8_t wr_type = GATT_WRITE_CHAR; // Get the address of the environment struct hogpbh_env_tag *hogpbh_env = PRF_CLIENT_GET_ENV(dest_id, hogpbh); // Save the Characteristic Code hogpbh_env->last_char_code = param->char_code; // Check Connection Handle and HIDS Instance Nb if((param->conhdl == hogpbh_env->con_info.conhdl) && (param->hids_nb < hogpbh_env->hids_nb) && (param->report_length <= HOGPBH_BOOT_REPORT_MAX_LEN)) { switch (param->char_code) { case (HOGPBH_CHAR_BOOT_KB_OUT_REPORT): // Write Without Response is available for the Boot Keyboard Ouput Report if (param->wr_type == GATT_WRITE_NO_RESPONSE) { wr_type = param->wr_type; } break; case (HOGPBH_CHAR_BOOT_KB_IN_REPORT): case (HOGPBH_CHAR_BOOT_MOUSE_IN_REPORT): // Check if the characteristic is writable if ((hogpbh_env->hids[param->hids_nb].chars[param->char_code].prop & ATT_CHAR_PROP_WR) != ATT_CHAR_PROP_WR) { status = PRF_ERR_NOT_WRITABLE; } break; default: status = PRF_ERR_INVALID_PARAM; break; } if (status == PRF_ERR_OK) { val_hdl = hogpbh_env->hids[param->hids_nb].chars[param->char_code].val_hdl; // Check if the handle value exists if (val_hdl != ATT_INVALID_SEARCH_HANDLE) { prf_gatt_write(&hogpbh_env->con_info, val_hdl, (uint8_t *)¶m->report[0], param->report_length, wr_type); } else { status = PRF_ERR_INEXISTENT_HDL; } } } else { status = PRF_ERR_INVALID_PARAM; } if (status != PRF_ERR_OK) { hogpbh_char_req_rsp_send(hogpbh_env, HOGPBH_WR_CHAR_RSP, status); } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref CSCPC_CFG_NTFIND_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 cscpc_ctnl_pt_cfg_cmd_handler(ke_msg_id_t const msgid, struct cscpc_ctnl_pt_cfg_cmd *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Message status uint8_t msg_status = KE_MSG_CONSUMED; // Get the address of the environment struct cscpc_env_tag *cscpc_env = PRF_CLIENT_GET_ENV(dest_id, cscpc); if (cscpc_env != NULL) { // Status uint8_t status = PRF_ERR_OK; do { // State is Connected or Busy ASSERT_ERR(ke_state_get(dest_id) > CSCPC_IDLE); // Check the provided connection handle if (param->conhdl != cscpc_env->con_info.conhdl) { status = PRF_ERR_INVALID_PARAM; break; } if (ke_state_get(dest_id) == CSCPC_BUSY) { // Another procedure is pending, keep the command for later msg_status = KE_MSG_SAVED; // Status is PRF_ERR_OK, no message will be sent to the application break; } // Check if the characteristic has been found if (cscpc_env->cscs.descs[CSCPC_DESC_SC_CTNL_PT_CL_CFG].desc_hdl != ATT_INVALID_SEARCH_HANDLE) { // Packed request uint8_t req[CSCP_SC_CNTL_PT_REQ_MAX_LEN]; // Request Length uint8_t req_len = CSCP_SC_CNTL_PT_REQ_MIN_LEN; // Set the operation code req[0] = param->sc_ctnl_pt.op_code; // Fulfill the message according to the operation code switch (param->sc_ctnl_pt.op_code) { case (CSCP_CTNL_PT_OP_SET_CUMUL_VAL): { // Set the cumulative value co_write32p(&req[1], param->sc_ctnl_pt.value.cumul_val); // Update length req_len += 4; } break; case (CSCP_CTNL_PT_OP_UPD_LOC): { // Set the sensor location req[1] = param->sc_ctnl_pt.value.sensor_loc; // Update length req_len++; } break; case (CSCP_CTNL_PT_OP_RESERVED): case (CSCP_CTNL_PT_OP_START_CALIB): case (CSCP_CTNL_PT_OP_REQ_SUPP_LOC): { // Nothing more to do } break; default: { status = PRF_ERR_INVALID_PARAM; } break; } if (status == PRF_ERR_OK) { // Set the operation code param->operation = CSCPC_CTNL_PT_CFG_WR_OP_CODE; // Store the command structure cscpc_env->operation = param; // Store the command information msg_status = KE_MSG_NO_FREE; // Go to the Busy state ke_state_set(dest_id, CSCPC_BUSY); // Send the write request prf_gatt_write(&(cscpc_env->con_info), cscpc_env->cscs.chars[CSCP_CSCS_SC_CTNL_PT_CHAR].val_hdl, (uint8_t *)&req[0], req_len, GATT_WRITE_CHAR); } } else { status = PRF_ERR_INEXISTENT_HDL; } } while (0); if (status != PRF_ERR_OK) { // Send a complete event status to the application cscpc_send_cmp_evt(cscpc_env, CSCPC_CTNL_PT_CFG_WR_OP_CODE, status); } } else { // No connection cscpc_send_no_conn_cmp_evt(dest_id, src_id, param->conhdl, CSCPC_CTNL_PT_CFG_WR_OP_CODE); } return (int)msg_status; }
/** **************************************************************************************** * @brief Handles reception of the @ref ANPC_WRITE_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 anpc_write_cmd_handler(ke_msg_id_t const msgid, struct anpc_write_cmd *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Message status uint8_t msg_status = KE_MSG_CONSUMED; // Get the address of the environment struct anpc_env_tag *anpc_env = PRF_CLIENT_GET_ENV(dest_id, anpc); if (anpc_env != NULL) { // Status uint8_t status = PRF_ERR_OK; // State is Connected or Busy ASSERT_ERR(ke_state_get(dest_id) != ANPC_IDLE); // Check the provided connection handle if (gapc_get_conidx(param->conhdl) == anpc_env->con_info.conidx) { // Check the current state if (ke_state_get(dest_id) == ANPC_BUSY) { msg_status = KE_MSG_SAVED; } else // state = ANPC_CONNECTED { // Attribute handle uint16_t handle = ATT_INVALID_SEARCH_HANDLE; // Length uint8_t length; ASSERT_ERR(anpc_env->operation == NULL); switch (param->write_code) { // Write Alert Notification Control Point Characteristic Value case (ANPC_WR_ALERT_NTF_CTNL_PT): { // Check the Category ID and the Command ID if ((param->value.ctnl_pt.cmd_id < CMD_ID_NB) && ((param->value.ctnl_pt.cat_id < CAT_ID_NB) || (param->value.ctnl_pt.cat_id == CAT_ID_ALL_SUPPORTED_CAT))) { handle = anpc_env->ans.chars[ANPC_CHAR_ALERT_NTF_CTNL_PT].val_hdl; length = sizeof(struct anp_ctnl_pt); } else { status = PRF_ERR_INVALID_PARAM; } } break; // Write New Alert Characteristic Client Char. Cfg. Descriptor Value case (ANPC_RD_WR_NEW_ALERT_CFG): { if (param->value.new_alert_ntf_cfg <= PRF_CLI_START_NTF) { handle = anpc_env->ans.descs[ANPC_DESC_NEW_ALERT_CL_CFG].desc_hdl; length = sizeof(uint16_t); } else { status = PRF_ERR_INVALID_PARAM; } } break; // Write Unread Alert Status Characteristic Client Char. Cfg. Descriptor Value case (ANPC_RD_WR_UNREAD_ALERT_STATUS_CFG): { if (param->value.unread_alert_status_ntf_cfg <= PRF_CLI_START_NTF) { handle = anpc_env->ans.descs[ANPC_DESC_UNREAD_ALERT_STATUS_CL_CFG].desc_hdl; length = sizeof(uint16_t); } else { status = PRF_ERR_INVALID_PARAM; } } break; default: { status = PRF_ERR_INVALID_PARAM; } break; } if (status == PRF_ERR_OK) { // Check if handle is viable if (handle != ATT_INVALID_SEARCH_HANDLE) { // Send the write request prf_gatt_write(&(anpc_env->con_info), handle, (uint8_t *)¶m->value, length, GATTC_WRITE); // Force the operation value param->operation = ANPC_WRITE_OP_CODE; // Store the command structure anpc_env->operation = param; msg_status = KE_MSG_NO_FREE; // Go to the Busy state ke_state_set(dest_id, ANPC_BUSY); } else { status = PRF_ERR_INEXISTENT_HDL; } } } } else { status = PRF_ERR_INVALID_PARAM; } if (status != PRF_ERR_OK) { anpc_send_cmp_evt(anpc_env, ANPC_WRITE_OP_CODE, status); } } else { anpc_send_no_conn_cmp_evt(dest_id, src_id, param->conhdl, ANPC_WRITE_OP_CODE); } return (int)msg_status; }