/** **************************************************************************************** * @brief Handles reception of the @ref GATTC_EVENT_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_event_ind_handler(ke_msg_id_t const msgid, struct gattc_event_ind 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 (KE_IDX_GET(src_id) == scppc_env->con_info.conidx) { //Scan Refresh if (param->handle == scppc_env->scps.chars[SCPPC_CHAR_SCAN_REFRESH].val_hdl) { if (param->value[0] == SCPP_SERVER_REQUIRES_REFRESH) { // Rewrite the most recent settings written on the server struct scppc_scan_intv_wd_wr_req * req = KE_MSG_ALLOC(SCPPC_SCAN_INTV_WD_WR_REQ, dest_id, dest_id, scppc_scan_intv_wd_wr_req); req->conhdl = gapc_get_conhdl(scppc_env->con_info.conidx); co_write16p(&req->scan_intv_wd.le_scan_intv, scppc_env->scan_intv_wd.le_scan_intv); co_write16p(&req->scan_intv_wd.le_scan_window, scppc_env->scan_intv_wd.le_scan_window); ke_msg_send(req); } } } return (KE_MSG_CONSUMED); }
void prf_pack_char_pres_fmt(uint8_t *packed_val, const struct prf_char_pres_fmt* char_pres_fmt) { *packed_val = char_pres_fmt->format; *(packed_val + 1) = char_pres_fmt->exponent; co_write16p(packed_val + 2, char_pres_fmt->unit); *(packed_val + 4) = char_pres_fmt->name_space; co_write16p(packed_val + 5, char_pres_fmt->description); }
uint8_t hogpd_ntf_cfg_ind_send(uint16_t ntf_cfg, uint16_t handle, uint8_t cfg_code, uint8_t hids_nb, uint8_t report_nb) { // Status uint8_t status = PRF_APP_ERROR; // Mask uint8_t mask = 0x00; // Pointer to the flag saving the notification configuration uint8_t *flag = &hogpd_env.features[hids_nb].svc_features; // Check if provided value is correct if ((ntf_cfg == PRF_CLI_STOP_NTFIND) || (ntf_cfg == PRF_CLI_START_NTF)) { // Set value in the database attsdb_att_set_value(handle, sizeof(uint16_t), (uint8_t *)&ntf_cfg); if (cfg_code == HOGPD_BOOT_KB_IN_REPORT_CFG) { mask = HOGPD_BOOT_KB_IN_NTF_CFG_MASK; } else if (cfg_code == HOGPD_BOOT_MOUSE_IN_REPORT_CFG) { mask = HOGPD_BOOT_MOUSE_IN_NTF_CFG_MASK; } else if (cfg_code == HOGPD_REPORT_CFG) { mask = HOGPD_REPORT_NTF_CFG_MASK; flag = &hogpd_env.features[hids_nb].report_char_cfg[report_nb]; } // Save new status in the environment if (ntf_cfg == PRF_CLI_START_NTF) { *flag |= mask; } else { *flag &= ~mask; } // Inform APP of configuration change struct hogpd_ntf_cfg_ind * ind = KE_MSG_ALLOC(HOGPD_NTF_CFG_IND, hogpd_env.con_info.appid, TASK_HOGPD, hogpd_ntf_cfg_ind); co_write16p(&ind->conhdl, hogpd_env.con_info.conhdl); co_write16p(&ind->ntf_en, ntf_cfg); ind->hids_nb = hids_nb; ind->report_nb = report_nb; ind->cfg_code = cfg_code; ke_msg_send(ind); status = PRF_ERR_OK; } return status; }
void prf_gatt_write_ntf_ind(struct prf_con_info* con_info, uint16_t handle, uint16_t ntf_ind_cfg) { uint8_t value[2]; // put value in air format co_write16p((&value[0]), ntf_ind_cfg); // write value over GATT prf_gatt_write(con_info, handle, value, 2, GATTC_WRITE); }
uint8_t prf_pack_date_time(uint8_t *packed_date, const struct prf_date_time* date_time) { co_write16p(packed_date, date_time->year); *(packed_date + 2) = date_time->month; *(packed_date + 3) = date_time->day; *(packed_date + 4) = date_time->hour; *(packed_date + 5) = date_time->min; *(packed_date + 6) = date_time->sec; return 7; }
/** **************************************************************************************** * @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 == gapc_get_conhdl(scppc_env->con_info.conidx)) { 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), GATTC_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); }
void prf_disc_char_all_send(struct prf_con_info *con_info, struct prf_svc *svc) { struct gattc_disc_cmd * char_req = KE_MSG_ALLOC_DYN(GATTC_DISC_CMD, KE_BUILD_ID(TASK_GATTC, con_info->conidx), con_info->prf_id, gattc_disc_cmd, ATT_UUID_16_LEN); char_req->req_type = GATTC_DISC_ALL_CHAR; char_req->start_hdl = svc->shdl; char_req->end_hdl = svc->ehdl; // UUID info - Don't care char_req->uuid_len = ATT_UUID_16_LEN; //set the first two bytes to the value array, LSB to MSB:Health Thermometer Service UUID first co_write16p(&(char_req->uuid[0]), ATT_INVALID_UUID); //send the message to GATT, which will send back the response when it gets it ke_msg_send(char_req); }
void prf_disc_incl_svc_send(struct prf_con_info* con_info, struct prf_svc *svc) { // Send GATT discover included services struct gattc_disc_cmd * svc_req = KE_MSG_ALLOC_DYN(GATTC_DISC_CMD, KE_BUILD_ID(TASK_GATTC, con_info->conidx), con_info->prf_id, gattc_disc_cmd, ATT_UUID_16_LEN); //gatt request type: by UUID svc_req->req_type = GATTC_DISC_INCLUDED_SVC; //start handle; svc_req->start_hdl = svc->shdl; //end handle svc_req->end_hdl = svc->ehdl; // UUID info - Don't care svc_req->uuid_len = ATT_UUID_16_LEN; //set the first two bytes to the value array, LSB to MSB:Health Thermometer Service UUID first co_write16p(&(svc_req->uuid[0]), ATT_INVALID_UUID); // Send the message to GATT, which will send back the response when it gets it ke_msg_send(svc_req); }
void prf_disc_svc_send(struct prf_con_info* con_info, uint16_t uuid) { //send GATT discover primary services by UUID request: find by type request struct gattc_disc_cmd * svc_req = KE_MSG_ALLOC_DYN(GATTC_DISC_CMD, KE_BUILD_ID(TASK_GATTC, con_info->conidx), con_info->prf_id, gattc_disc_cmd, ATT_UUID_16_LEN); //gatt request type: by UUID svc_req->req_type = GATTC_DISC_BY_UUID_SVC; //start handle; svc_req->start_hdl = ATT_1ST_REQ_START_HDL; //end handle svc_req->end_hdl = ATT_1ST_REQ_END_HDL; // UUID search svc_req->uuid_len = ATT_UUID_16_LEN; //set the first two bytes to the value array, LSB to MSB:Health Thermometer Service UUID first co_write16p(&(svc_req->uuid[0]), uuid); //send the message to GATT, which will send back the response when it gets it ke_msg_send(svc_req); }
void prf_disc_char_desc_send(struct prf_con_info* con_info, struct prf_char_inf * charact) { // Check if there is at least one descriptor to find if ((charact->val_hdl + 1) <= (charact->char_hdl + charact->char_ehdl_off - 1)) { // Ask for handles of a certain uuid struct gattc_disc_cmd * dsc_req = KE_MSG_ALLOC_DYN(GATTC_DISC_CMD, KE_BUILD_ID(TASK_GATTC, con_info->conidx), con_info->prf_id, gattc_disc_cmd, ATT_UUID_16_LEN); dsc_req->req_type = GATTC_DISC_DESC_CHAR; dsc_req->start_hdl = charact->val_hdl + 1; dsc_req->end_hdl = charact->char_hdl + charact->char_ehdl_off - 1; // UUID info - Don't care dsc_req->uuid_len = ATT_UUID_16_LEN; //set the first two bytes to the value array, LSB to MSB:Health Thermometer Service UUID first co_write16p(&(dsc_req->uuid[0]), ATT_INVALID_UUID); //send the message to GATT;there should be only one handle response every time ke_msg_send(dsc_req); } else { // TODO [FBE] to be changed if SDP task implemented // Send a GATT complete event message struct gattc_cmp_evt *evt = KE_MSG_ALLOC(GATTC_CMP_EVT, con_info->prf_id, KE_BUILD_ID(TASK_GATTC , con_info->conidx), gattc_cmp_evt); evt->status = PRF_ERR_OK; // Send the message ke_msg_send(evt); } }
/* **************************************************************************************** * @brief Gatt Read Characteristic request. *//** * * @param[in] req_type GATT request type: * - GATT_READ_CHAR * - GATT_READ_BY_UUID_CHAR * - GATT_READ_LONG_CHAR * - GATT_READ_MULT_LONG_CHAR * - GATT_READ_DESC * - GATT_READ_LONG_DESC * @param[in] conhdl Connection handle. * @param[in] valhdl Value handle. * @response GATT_READ_CHAR_RESP or GATT_READ_CHAR_MULTI_RESP * @description * * This API is used by the application to send a GATT_READ_CHAR_REQ mssage. * Upon reception of this message, GATT will checks whether the parameters are correct, * if not correct then the GATT_CMP_EVT message with error code GATT_INVALID_PARAM_ERR * will be generically built and sent to Application directly. If parameter is correct, * the GATT_READ_CHAR_RESP message will be received. * **************************************************************************************** */ void app_gatt_read_char_req(uint8_t req_type, uint16_t conhdl, uint16_t valhdl) { struct gatt_read_char_req *msg = KE_MSG_ALLOC(GATT_READ_CHAR_REQ, TASK_GATT, TASK_APP, gatt_read_char_req); //Connection handle msg->conhdl = conhdl; //GATT request type msg->req_type = req_type; //Read offset msg->offset = 0; //Start handle range msg->start_hdl = 0x0001; //End handle range msg->end_hdl = GATT_MAX_ATTR_HDL; //Number of UUID msg->nb_uuid = 0x01; //Handle of char value msg->uuid[0].expect_resp_size = ATT_UUID_16_LEN; msg->uuid[0].value_size = ATT_UUID_16_LEN; co_write16p(&msg->uuid[0].value[0], valhdl); ke_msg_send(msg); }
/** **************************************************************************************** * @brief Handles reception of the @ref SCPPC_ENABLE_REQ message. * The handler enables the Scan Parameters Profile Client Role. * @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_enable_req_handler(ke_msg_id_t const msgid, struct scppc_enable_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Status uint8_t status; // Scan Parameters Profile Client Role Task Environment struct scppc_env_tag *scppc_env; // Connection Information struct prf_con_info con_info; // Fill the Connection Information structure con_info.conidx = gapc_get_conidx(param->conhdl); con_info.prf_id = dest_id; con_info.appid = src_id; // Add an environment for the provided device status = PRF_CLIENT_ENABLE(con_info, param, scppc); if (status == PRF_ERR_FEATURE_NOT_SUPPORTED) { // The message has been forwarded to another task id. return (KE_MSG_NO_FREE); } else if (status == PRF_ERR_OK) { scppc_env = PRF_CLIENT_GET_ENV(dest_id, scppc); // Save Scan Interval Window value memcpy(&scppc_env->scan_intv_wd, ¶m->scan_intv_wd, sizeof(struct scan_intv_wd)); // Config connection, start discovering if(param->con_type == PRF_CON_DISCOVERY) { //start discovering SCPS on peer prf_disc_svc_send(&(scppc_env->con_info), ATT_SVC_SCAN_PARAMETERS); scppc_env->last_uuid_req = ATT_SVC_SCAN_PARAMETERS; // Go to DISCOVERING state ke_state_set(dest_id, SCPPC_DISCOVERING); } // Normal connection, get saved att details else { scppc_env->scps = param->scps; if (scppc_env->scps.chars[SCPPC_CHAR_SCAN_REFRESH].char_hdl != ATT_INVALID_HANDLE) { /* If connected to a bonded Scan Server, the Scan Client shall enable notifications of the * Scan Refresh characteristic using the Client Characteristic Configuration descriptor. */ struct scppc_scan_refresh_ntf_cfg_req *req = KE_MSG_ALLOC(SCPPC_SCAN_REFRESH_NTF_CFG_REQ, dest_id, dest_id, scppc_scan_refresh_ntf_cfg_req); req->conhdl = gapc_get_conhdl(scppc_env->con_info.conidx); req->ntf_cfg = PRF_CLI_START_NTF; // send the message ke_msg_send(req); } else { // Write Scan Interval Windows value struct scppc_scan_intv_wd_wr_req * req = KE_MSG_ALLOC(SCPPC_SCAN_INTV_WD_WR_REQ, dest_id, dest_id, scppc_scan_intv_wd_wr_req); req->conhdl = gapc_get_conhdl(scppc_env->con_info.conidx); co_write16p(&req->scan_intv_wd.le_scan_intv, scppc_env->scan_intv_wd.le_scan_intv); co_write16p(&req->scan_intv_wd.le_scan_window, scppc_env->scan_intv_wd.le_scan_window); ke_msg_send(req); } scppc_enable_cfm_send(scppc_env, &con_info, PRF_ERR_OK); } } else { // An error has been raised during the process, scps is NULL and won't be handled scppc_enable_cfm_send(NULL, &con_info, status); } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref GATTC_CMP_EVT message. * This generic event is received for different requests, so need to keep track. * @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_cmp_evt_handler(ke_msg_id_t const msgid, struct gattc_cmp_evt const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { uint8_t state = ke_state_get(dest_id); // Get the address of the environment struct scppc_env_tag *scppc_env = PRF_CLIENT_GET_ENV(dest_id, scppc); uint8_t status = PRF_ERR_OK; if(state == SCPPC_DISCOVERING) { if ((param->status == ATT_ERR_ATTRIBUTE_NOT_FOUND) || (param->status == ATT_ERR_NO_ERROR)) { // Service start/end handles has been received if(scppc_env->last_uuid_req == ATT_SVC_SCAN_PARAMETERS) { // check if service handles are not ok if(scppc_env->scps.svc.shdl== ATT_INVALID_HANDLE) { // stop discovery procedure. scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, PRF_ERR_STOP_DISC_CHAR_MISSING); } // Too many services found only one such service should exist else if(scppc_env->nb_svc > 1) { scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, PRF_ERR_MULTIPLE_SVC); } else { // Discover all SCPS characteristics prf_disc_char_all_send(&(scppc_env->con_info), &(scppc_env->scps.svc)); scppc_env->last_uuid_req = ATT_DECL_CHARACTERISTIC; } } else if(scppc_env->last_uuid_req == ATT_DECL_CHARACTERISTIC) { status = prf_check_svc_char_validity(SCPPC_CHAR_MAX, scppc_env->scps.chars, scppc_scps_char); if(status == PRF_ERR_OK) { //If Scan Refresh Char. is present, discover its descriptor if (scppc_env->scps.chars[SCPPC_CHAR_SCAN_REFRESH].char_hdl != ATT_INVALID_HANDLE) { scppc_env->last_uuid_req = ATT_INVALID_HANDLE; scppc_env->last_char_code = scppc_scps_char_desc[SCPPC_DESC_SCAN_REFRESH_CFG].char_code; // Discover Scan Refresh Char. Descriptor - Mandatory prf_disc_char_desc_send(&(scppc_env->con_info), &(scppc_env->scps.chars[scppc_env->last_char_code])); } else { scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, status); } } else { // Stop discovery procedure. scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, status); } } else { status = prf_check_svc_char_desc_validity(SCPPC_DESC_MAX, scppc_env->scps.descs, scppc_scps_char_desc, scppc_env->scps.chars); scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, status); } if (status == PRF_ERR_OK) { // Write Scan Interval Windows value struct scppc_scan_intv_wd_wr_req * req = KE_MSG_ALLOC(SCPPC_SCAN_INTV_WD_WR_REQ, dest_id, dest_id, scppc_scan_intv_wd_wr_req); req->conhdl = gapc_get_conhdl(scppc_env->con_info.conidx); co_write16p(&req->scan_intv_wd.le_scan_intv, scppc_env->scan_intv_wd.le_scan_intv); co_write16p(&req->scan_intv_wd.le_scan_window, scppc_env->scan_intv_wd.le_scan_window); ke_msg_send(req); } } } else if (state == SCPPC_CONNECTED) { switch(param->req_type) { case GATTC_WRITE: { struct scppc_wr_char_rsp *wr_cfm = KE_MSG_ALLOC(SCPPC_WR_CHAR_RSP, scppc_env->con_info.appid, dest_id, scppc_wr_char_rsp); wr_cfm->conhdl = gapc_get_conhdl(scppc_env->con_info.conidx); //it will be a GATT status code wr_cfm->status = param->status; // send the message ke_msg_send(wr_cfm); } break; case GATTC_READ: { if(param->status != GATT_ERR_NO_ERROR) { // an error occurs while reading peer device attribute scppc_error_ind_send(scppc_env, param->status); } } break; default: break; } } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref GATT_READ_CHAR_RESP 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 gatt_rd_char_rsp_handler(ke_msg_id_t const msgid, struct gatt_read_char_resp const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { // Get the address of the environment struct cscpc_env_tag *cscpc_env = PRF_CLIENT_GET_ENV(dest_id, cscpc); if (cscpc_env != NULL) { ASSERT_ERR(cscpc_env->operation != NULL); ASSERT_ERR(((struct cscpc_cmd *)cscpc_env->operation)->operation == CSCPC_READ_OP_CODE); if (param->status == GATT_NO_ERROR) { // Send the read value to the HL struct cscpc_value_ind *ind = KE_MSG_ALLOC(CSCPC_VALUE_IND, cscpc_env->con_info.appid, cscpc_env->con_info.prf_id, cscpc_value_ind); ind->conhdl = cscpc_env->con_info.conhdl; switch (((struct cscpc_read_cmd *)cscpc_env->operation)->read_code) { // Read CSC Feature Characteristic value case (CSCPC_RD_CSC_FEAT): { co_write16p(&ind->value.sensor_feat, param->data.data[0]); // Mask the reserved bits ind->value.sensor_feat &= CSCP_FEAT_ALL_SUPP; } break; // Read Sensor Location Characteristic value case (CSCPC_RD_SENSOR_LOC): { ind->value.sensor_loc = (param->data.data[0] < CSCP_LOC_MAX) ? param->data.data[0] : CSCP_LOC_OTHER; } break; // Read Client Characteristic Configuration Descriptor value case (CSCPC_RD_WR_CSC_MEAS_CFG): case (CSCPC_RD_WR_SC_CTNL_PT_CFG): { co_write16p(&ind->value.ntf_cfg, param->data.data[0]); } break; default: { ASSERT_ERR(0); } break; } ind->att_code = ((struct cscpc_read_cmd *)cscpc_env->operation)->read_code; // Send the message to the application ke_msg_send(ind); } // Send a complete event status to the application cscpc_send_cmp_evt(cscpc_env, CSCPC_READ_OP_CODE, param->status); } // else drop the message return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref GATT_CMP_EVT message. * This generic event is received for different requests, so need to keep track. * @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 gatt_cmp_evt_handler(ke_msg_id_t const msgid, struct gatt_cmp_evt 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); uint8_t status = PRF_ERR_OK; if ((param->status == ATT_ERR_ATTRIBUTE_NOT_FOUND) || (param->status == ATT_ERR_NO_ERROR)) { // Service start/end handles has been received if(scppc_env->last_uuid_req == ATT_SVC_SCAN_PARAMETERS) { // check if service handles are not ok if(scppc_env->scps.svc.shdl== ATT_INVALID_HANDLE) { // stop discovery procedure. scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, PRF_ERR_STOP_DISC_CHAR_MISSING); } // Too many services found only one such service should exist else if(scppc_env->nb_svc > 1) { scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, PRF_ERR_MULTIPLE_SVC); } else { // Discover all SCPS characteristics prf_disc_char_all_send(&(scppc_env->con_info), &(scppc_env->scps.svc)); scppc_env->last_uuid_req = ATT_DECL_CHARACTERISTIC; } } else if(scppc_env->last_uuid_req == ATT_DECL_CHARACTERISTIC) { status = prf_check_svc_char_validity(SCPPC_CHAR_MAX, scppc_env->scps.chars, scppc_scps_char); if(status == PRF_ERR_OK) { //If Scan Refresh Char. is present, discover its descriptor if (scppc_env->scps.chars[SCPPC_CHAR_SCAN_REFRESH].char_hdl != ATT_INVALID_HANDLE) { scppc_env->last_uuid_req = ATT_INVALID_HANDLE; scppc_env->last_char_code = scppc_scps_char_desc[SCPPC_DESC_SCAN_REFRESH_CFG].char_code; // Discover Scan Refresh Char. Descriptor - Mandatory prf_disc_char_desc_send(&(scppc_env->con_info), &(scppc_env->scps.chars[scppc_env->last_char_code])); } else { scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, status); } } else { // Stop discovery procedure. scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, status); } } else { status = prf_check_svc_char_desc_validity(SCPPC_DESC_MAX, scppc_env->scps.descs, scppc_scps_char_desc, scppc_env->scps.chars); scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, status); } if (status == PRF_ERR_OK) { // Write Scan Interval Windows value struct scppc_scan_intv_wd_wr_req * req = KE_MSG_ALLOC(SCPPC_SCAN_INTV_WD_WR_REQ, dest_id, dest_id, scppc_scan_intv_wd_wr_req); req->conhdl = scppc_env->con_info.conhdl; co_write16p(&req->scan_intv_wd.le_scan_intv, scppc_env->scan_intv_wd.le_scan_intv); co_write16p(&req->scan_intv_wd.le_scan_window, scppc_env->scan_intv_wd.le_scan_window); ke_msg_send(req); } } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref GL2C_CODE_ATT_WR_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) { // Counter uint8_t i; // Status uint8_t status = PRF_APP_ERROR; // Written value uint16_t ntf_cfg; // Look for the BAS instance for (i = 0; ((i < bass_env.bas_nb) && (status == PRF_APP_ERROR)); i++) { if (param->handle == bass_env.shdl[i] + BAS_IDX_BATT_LVL_NTF_CFG) { // Go out of the loop status = PRF_ERR_OK; } } //Revert Last incrementation i--; // If the attribute has been found, status is PRF_ERR_OK if (status == PRF_ERR_OK) { // Extract value before check ntf_cfg = co_read16p(¶m->value[0]); // Only update configuration if value for stop or notification enable if ((ntf_cfg == PRF_CLI_STOP_NTFIND) || (ntf_cfg == PRF_CLI_START_NTF)) { // Set NTF Cfg value in the DB attmdb_att_set_value(bass_env.shdl[i] + BAS_IDX_BATT_LVL_NTF_CFG, sizeof(uint16_t), (uint8_t *)&ntf_cfg); // Conserve information in environment if (ntf_cfg == PRF_CLI_START_NTF) { // Ntf cfg bit set to 1 bass_env.features[i] |= BASS_FLAG_NTF_CFG_BIT; } else { // Ntf cfg bit set to 0 bass_env.features[i] &= ~BASS_FLAG_NTF_CFG_BIT; } if(param->last) { // Inform APP of configuration change struct bass_batt_level_ntf_cfg_ind * ind = KE_MSG_ALLOC(BASS_BATT_LEVEL_NTF_CFG_IND, bass_env.con_info.appid, TASK_BASS, bass_batt_level_ntf_cfg_ind); ind->conhdl = gapc_get_conhdl(bass_env.con_info.conidx); co_write16p(&ind->ntf_cfg, ntf_cfg); ind->bas_instance = i; ke_msg_send(ind); } } else { status = PRF_APP_ERROR; } // Send write response atts_write_rsp_send(bass_env.con_info.conidx, param->handle, status); } return (KE_MSG_CONSUMED); }