/** **************************************************************************************** * @brief Handles reception of the @ref ACCEL_VALUE_REQ message. * The handler compares the new values with current ones and notifies them if they changed. * @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 accel_value_req_handler(ke_msg_id_t const msgid, struct accel_value_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { uint16_t len; uint16_t* axis_en; uint8_t* axis_val; // Check if acceleration changed on each axis and notify it if required for (int i = 0; i < ACCEL_MAX; i++) { attmdb_att_get_value(ACCEL_DIR_VAL_HANDLE(i), &(len), (uint8_t**)&(axis_val)); attmdb_att_get_value(ACCEL_DIR_EN_HANDLE(i), &(len), (uint8_t**)&(axis_en)); if ((*axis_en) && (param->accel[i] != *axis_val)) { // Update the value in the attribute database attmdb_att_set_value(ACCEL_DIR_VAL_HANDLE(i), sizeof(uint8_t), (uint8_t*) &(param->accel[i])); // Send notification prf_server_send_event((prf_env_struct *)&accel_env, false, ACCEL_DIR_VAL_HANDLE(i)); } } return (KE_MSG_CONSUMED); }
void wechat_disable(void) { att_size_t length; uint8_t *alert_lvl; // Disable service in database attmdb_svc_set_permission(wechat_env.wechat_shdl, PERM_RIGHT_DISABLE); struct wechat_disable_ind *ind = KE_MSG_ALLOC(WECHAT_DISABLE_IND, wechat_env.con_info.appid, TASK_WECHAT, wechat_disable_ind); //Get value stored in DB attmdb_att_get_value(wechat_env.wechat_shdl + WECHAT_1_IDX_VAL, &length, &alert_lvl); // Fill in the parameter structure ind->conhdl = gapc_get_conhdl(wechat_env.con_info.conidx); // Send the message ke_msg_send(ind); // Go to idle state ke_state_set(TASK_WECHAT, WECHAT_IDLE); }
void htpt_disable(uint16_t conhdl) { att_size_t att_length; uint8_t *att_value; //Disable HTS in database attmdb_svc_set_permission(htpt_env.shdl, PERM_RIGHT_DISABLE); //Send current configuration to APP struct htpt_disable_ind* ind = KE_MSG_ALLOC(HTPT_DISABLE_IND, htpt_env.con_info.appid, TASK_HTPT, htpt_disable_ind); ind->conhdl = conhdl; //Temperature Measurement Char. - Indications Configuration if (HTPT_IS_INDNTF_ENABLED(HTPT_MASK_TEMP_MEAS_CFG)) { ind->temp_meas_ind_en = PRF_CLI_START_IND; } //Intermediate Measurement Char. - Indications Configuration if (HTPT_IS_CHAR_SUPPORTED(HTPT_INTERM_TEMP_CHAR)) { if (HTPT_IS_INDNTF_ENABLED(HTPT_MASK_INTM_MEAS_CFG)) { ind->interm_temp_ntf_en = PRF_CLI_START_NTF; } } //Measurement Interval Char. - Value if (HTPT_IS_CHAR_SUPPORTED(HTPT_MEAS_INTV_CHAR)) { //Measurement Interval Char. - Indications Configuration if (HTPT_IS_FEATURE_SUPPORTED(HTPT_MEAS_INTV_IND_SUP)) { if (HTPT_IS_INDNTF_ENABLED(HTPT_MASK_MEAS_INTV_CFG)) { ind->meas_intv_ind_en = PRF_CLI_START_IND; } } attmdb_att_get_value(htpt_env.shdl + htpt_env.att_tbl[HTPT_MEAS_INTV_CHAR] + 1, &att_length, &att_value); memcpy(&(ind->meas_intv), att_value, sizeof(uint16_t)); } ke_msg_send(ind); //Reset indications/notifications bit field htpt_env.features &= ~HTPT_CFG_NTFIND_MASK; //Go to idle state ke_state_set(TASK_HTPT, HTPT_IDLE); }
int streamdatad_send_data_packets_req_handler(ke_msg_id_t const msgid, struct streamdatad_send_data_packets_req const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { uint16_t next_packet; uint16_t nr_packets; uint16_t* packet_buffer_enabled; uint16_t len = 0; if (!streamdatad_env.stream_enabled) return KE_MSG_CONSUMED; next_packet = 0; nr_packets = param->nr_packets; nb_buf_av = l2cm_get_nb_buffer_available(); for (int li = 0; (li < STREAMDATAD_MAX) && (nr_packets > 0) && (nb_buf_av > 0); li++) { packet_buffer_enabled = NULL; attmdb_att_get_value(STREAMDATAD_DIR_EN_HANDLE(streamdatad_env.next_attribute_idx), &(len), (uint8_t**)&(packet_buffer_enabled)); if ((packet_buffer_enabled && (*packet_buffer_enabled))) { // Update the value in the attribute database attmdb_att_set_value(STREAMDATAD_DIR_VAL_HANDLE(streamdatad_env.next_attribute_idx), sizeof(uint8_t) * STREAMDATAD_PACKET_SIZE, (uint8_t*) &(param->packets[next_packet][0])); // Send notification prf_server_send_event((prf_env_struct *)&(streamdatad_env.con_info), false, STREAMDATAD_DIR_VAL_HANDLE(streamdatad_env.next_attribute_idx)); } else { len = 2; } //set_pxact_gpio(); next_packet++; nr_packets--; nb_buf_av--; streamdatad_env.next_attribute_idx++; if (streamdatad_env.next_attribute_idx >= STREAMDATAD_MAX) { streamdatad_env.next_attribute_idx = 0; break; // the for loop } // else notification at this index was not enabled; } //set_pxact_gpio(); return (KE_MSG_CONSUMED); }
void app_param_update_func(void) { #if 1 int temp=4; uint8_t *temp_v; attmdb_att_get_value(ACCEL_HANDLE(ACCEL_IDX_ACCEL_X_EN), &(temp), &(temp_v)); if(temp_v[1] > 1) accel_con_interval = temp_v[1]-1; if(accel_con_interval < 2 || accel_con_interval > 500) return; // Send a param update request struct gapc_param_update_cmd *cmd = KE_MSG_ALLOC(GAPC_PARAM_UPDATE_CMD, KE_BUILD_ID(TASK_GAPC, app_env.conidx), TASK_APP, gapc_param_update_cmd); // Fill up parameters cmd->operation = GAPC_UPDATE_PARAMS; #if 0 cmd->params.intv_min = 70; // 10ms (8*1.25ms) cmd->params.intv_max = 80; // 20ms (16*1.25ms) cmd->params.latency = 0; //GZ cmd->params.time_out = 100; cmd->params.time_out = 320; #endif cmd->params.intv_min = (accel_con_interval-1)*10/1.25; cmd->params.intv_max = (accel_con_interval)*10/1.25; cmd->params.latency = 0; if(accel_con_interval < 30) cmd->params.time_out = accel_con_interval*32; else cmd->params.time_out = 10000; // Send message ke_msg_send(cmd); //GZ tmp rwip_env.sleep_enable = false; // Go to Param update state ke_state_set(TASK_APP, APP_PARAM_UPD); #endif return; }
void bass_disable(uint16_t conhdl) { #ifndef USE_ONE_BAS_INSTANCE // Counter uint8_t i; #endif // Information get in the DB att_size_t att_length; uint8_t *att_value; // Send current configuration to the application struct bass_disable_ind *ind = KE_MSG_ALLOC(BASS_DISABLE_IND, bass_env.con_info.appid, TASK_BASS, bass_disable_ind); ind->conhdl = conhdl; #ifndef USE_ONE_BAS_INSTANCE for (i = 0; i < bass_env.bas_nb; i++) #else const int i = 0; #endif { if((bass_env.features[i] & BASS_FLAG_NTF_CFG_BIT) == BASS_FLAG_NTF_CFG_BIT) { ind->batt_level_ntf_cfg[i] = PRF_CLI_START_NTF; // Reset ntf cfg bit in features bass_env.features[i] &= ~BASS_FLAG_NTF_CFG_BIT; } else { ind->batt_level_ntf_cfg[i] = PRF_CLI_STOP_NTFIND; } // Get Battery Level value attmdb_att_get_value(bass_env.shdl[i] + BAS_IDX_BATT_LVL_VAL, &att_length, &att_value); ind->batt_lvl[i] = *att_value; } ke_msg_send(ind); // Go to idle state ke_state_set(TASK_BASS, BASS_IDLE); }
void streamdatad_streamonoff(void) { uint16_t len = 0; uint8_t* streamdatad_en = NULL; attmdb_att_get_value(STREAMDATAD_HANDLE(STREAMDATAD_IDX_ENABLE_VAL), &(len), &(streamdatad_en)); // Indicate to the application the state of the profile int on = ((len == 2) && (streamdatad_en && (*streamdatad_en))) ? 1 : 0; if (on) { // Allocate the start indication message struct streamdatad_start_ind *ind = KE_MSG_ALLOC(STREAMDATAD_START_IND, streamdatad_env.appid, TASK_STREAMDATAD, streamdatad_start_ind); streamdatad_env.stream_enabled = (*streamdatad_en); ind->status = PRF_ERR_OK; // Send the message ke_msg_send(ind); } else { streamdatad_env.next_attribute_idx = 0; streamdatad_env.stream_enabled = 0; // Send the stop indication ke_msg_send_basic(STREAMDATAD_STOP_IND, streamdatad_env.appid, TASK_STREAMDATAD); } uint16_t enable_val = streamdatad_en?(*streamdatad_en):0; // Enable or disable all data notifications streamdatad_env.nr_enabled_attributes = 0; int lastattr = enable_val?((STREAMDATAD_MAX>MAX_TRANSMIT_BUFFER_PACKETS)?MAX_TRANSMIT_BUFFER_PACKETS:STREAMDATAD_MAX):STREAMDATAD_MAX; attmdb_att_set_value(STREAMDATAD_IDX_ENABLE_EN, sizeof(uint16_t),(uint8_t*) &(enable_val)); for (int i = 0; i < lastattr; i++) { attmdb_att_set_value(STREAMDATAD_DIR_EN_HANDLE(i), sizeof(uint16_t),(uint8_t*) &(enable_val)); streamdatad_env.nr_enabled_attributes++; } if (!enable_val) streamdatad_env.nr_enabled_attributes = 0; }
int streamdatad_send_data_packet(uint8_t *data) { uint16_t* packet_buffer_enabled; int retval = 0; uint16_t len = 0; packet_buffer_enabled = NULL; attmdb_att_get_value(STREAMDATAD_DIR_EN_HANDLE(streamdatad_env.next_attribute_idx), &(len), (uint8_t**)&(packet_buffer_enabled)); if ((packet_buffer_enabled && (*packet_buffer_enabled))) { // Update the value in the attribute database attmdb_att_set_value(STREAMDATAD_DIR_VAL_HANDLE(streamdatad_env.next_attribute_idx), sizeof(uint8_t) * STREAMDATAD_PACKET_SIZE, data); // Send notification prf_server_send_event((prf_env_struct *)&(streamdatad_env.con_info), false, STREAMDATAD_DIR_VAL_HANDLE(streamdatad_env.next_attribute_idx)); retval = 1; } streamdatad_env.next_attribute_idx++; if (streamdatad_env.next_attribute_idx >= STREAMDATAD_MAX) streamdatad_env.next_attribute_idx = 0; return retval; }
void app_custom_connection(struct gapc_connection_req_ind const *param) { #if BLE_ACCEL int temp=4; uint8_t *temp_v; app_accel_adv_stopped(); if (!param->con_latency) { // Not completely verified, but this improves the stability of the connection. struct gapc_param_update_req_ind * req = KE_MSG_ALLOC(GAPC_PARAM_UPDATE_REQ_IND, TASK_GAPC, TASK_APP, gapc_param_update_req_ind); // Fill in the parameter structure //req->conhdl = param->conn_info.conhdl; //GZ req->conn_par.intv_min = param->conn_info.con_interval; //GZ req->conn_par.intv_max = param->conn_info.con_interval; attmdb_att_get_value(ACCEL_HANDLE(ACCEL_IDX_ACCEL_X_EN), &(temp), &(temp_v)); if(temp_v[1] > 1) accel_con_interval = temp_v[1]; req->params.intv_min = (accel_con_interval-1)*10/1.25; req->params.intv_max = (accel_con_interval)*10/1.25; req->params.latency = param->con_latency; if(param->sup_to * 8 / 1.25 <= 3200) req->params.time_out = param->sup_to * 8 / 1.25; else req->params.time_out = 3200/1.25; #if BLE_HID_DEVICE puts("Send GAP_PARAM_UPDATE_REQ"); #endif ke_msg_send(req); } #endif }
/** **************************************************************************************** * @brief Handles reception of the @ref GL2C_CODE_ATT_WR_CMD_IND message. * The handler compares the new values with current ones and notifies them if they changed. * @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 *meas_intv_range; uint16_t meas_intv_rge[2]; uint16_t value = 0x0000; uint8_t status = PRF_ERR_OK; uint8_t char_code = 0; if (KE_IDX_GET(src_id) == htpt_env.con_info.conidx) { //Extract value before check memcpy(&value, &(param->value), sizeof(uint16_t)); //Measurement Interval Char. - Value if (param->handle == (htpt_env.shdl + htpt_env.att_tbl[HTPT_MEAS_INTV_CHAR] + 1)) { /* * Get Measurement Interval range in database * Valid Range descriptor exists because measurement interval is writable */ attmdb_att_get_value(param->handle + htpt_get_valid_rge_offset(), &meas_intv_rge[0], &meas_intv_range); memcpy(&meas_intv_rge[0], meas_intv_range, sizeof(uint16_t)); memcpy(&meas_intv_rge[1], meas_intv_range + 2, sizeof(uint16_t)); //Check if value to write is in allowed range if (((value >= meas_intv_rge[0]) && (value <= meas_intv_rge[1])) || (value == 0)) { //Send APP the indication with the new value struct htpt_meas_intv_chg_ind * ind = KE_MSG_ALLOC(HTPT_MEAS_INTV_CHG_IND, htpt_env.con_info.appid, TASK_HTPT, htpt_meas_intv_chg_ind); memcpy(&ind->intv, &value, sizeof(uint16_t)); ke_msg_send(ind); } else { status = HTPT_OUT_OF_RANGE_ERR_CODE; } } else { //Temperature Measurement Char. - Client Char. Configuration if (param->handle == (htpt_env.shdl + HTS_IDX_TEMP_MEAS_IND_CFG)) { char_code = HTPT_TEMP_MEAS_CHAR; if (value == PRF_CLI_STOP_NTFIND) { htpt_env.features &= ~HTPT_MASK_TEMP_MEAS_CFG; } else if (value == PRF_CLI_START_IND) { htpt_env.features |= HTPT_MASK_TEMP_MEAS_CFG; } else { //Invalid value status = HTPT_OUT_OF_RANGE_ERR_CODE; } } //Measurement Interval Char. - Client Char. Configuration else if (param->handle == (htpt_env.shdl + htpt_env.att_tbl[HTPT_MEAS_INTV_CHAR] + 2)) { char_code = HTPT_MEAS_INTV_CHAR; if (value == PRF_CLI_STOP_NTFIND) { htpt_env.features &= ~HTPT_MASK_MEAS_INTV_CFG; } else if (value == PRF_CLI_START_IND) { htpt_env.features |= HTPT_MASK_MEAS_INTV_CFG; } else { //Invalid value status = HTPT_OUT_OF_RANGE_ERR_CODE; } } //Intermediate Measurement Char. - Client Char. Configuration else if (param->handle == (htpt_env.shdl + htpt_env.att_tbl[HTPT_INTERM_TEMP_CHAR] + 2)) { char_code = HTPT_INTERM_TEMP_CHAR; if (value == PRF_CLI_STOP_NTFIND) { htpt_env.features &= ~HTPT_MASK_INTM_MEAS_CFG; } else if (value == PRF_CLI_START_NTF) { htpt_env.features |= HTPT_MASK_INTM_MEAS_CFG; } else { //Invalid value status = HTPT_OUT_OF_RANGE_ERR_CODE; } } if (status == PRF_ERR_OK) { if(param->last) { //Inform APP of configuration change struct htpt_cfg_indntf_ind * ind = KE_MSG_ALLOC(HTPT_CFG_INDNTF_IND, htpt_env.con_info.appid, TASK_HTPT, htpt_cfg_indntf_ind); ind->conhdl = gapc_get_conhdl(htpt_env.con_info.conidx); ind->char_code = char_code; memcpy(&ind->cfg_val, &value, sizeof(uint16_t)); ke_msg_send(ind); } } } if (status == PRF_ERR_OK) { //Update the attribute value attmdb_att_set_value(param->handle, sizeof(uint16_t), (uint8_t *)&value); } //Send write response atts_write_rsp_send(htpt_env.con_info.conidx, param->handle, status); } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref GL2C_CODE_ATT_WR_CMD_IND message. * The handler will analyse what has been set and decide alert level * @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 char_code = UDSS_ERR_CHAR; uint8_t status = PRF_APP_ERROR; if (KE_IDX_GET(src_id) == udss_env.con_info.conidx) { // uint8_t att_idx = GLPS_IDX(param->handle); status = PRF_ERR_OK; if (param->handle == udss_env.shdl + UDS_IDX_USER_HEIGHT_VAL) { char_code = UDSS_USER_HEIGHT_CHAR; //Set User Height to specified value attmdb_att_set_value(udss_env.shdl + UDS_IDX_USER_HEIGHT_VAL, sizeof(uint8_t), (uint8_t *)¶m->value[0]); } else if (param->handle == udss_env.shdl + UDS_IDX_USER_AGE_VAL) { char_code = UDSS_USER_AGE_CHAR; //Set User Age to specified value attmdb_att_set_value(udss_env.shdl + UDS_IDX_USER_AGE_VAL, sizeof(uint8_t), (uint8_t *)¶m->value[0]); } else if (param->handle == udss_env.shdl + UDS_IDX_USER_DATE_OF_BIRTH_VAL) { char_code = UDSS_USER_DATE_OF_BIRTH_CHAR; //Set User Date of Birth to specified value attmdb_att_set_value(udss_env.shdl + UDS_IDX_USER_DATE_OF_BIRTH_VAL, sizeof(struct date), (uint8_t *)¶m->value[0]); } else if (param->handle == udss_env.shdl + UDS_IDX_USER_DB_CHANGE_INCR_VAL) { char_code = UDSS_USER_DB_CHANGE_INCR_CHAR; //Set User DB Change Increment to specified value attmdb_att_set_value(udss_env.shdl + UDS_IDX_USER_DB_CHANGE_INCR_VAL, sizeof(uint8_t), (uint8_t *)¶m->value[0]); } else if (param->handle == udss_env.shdl + UDS_IDX_USER_CTRL_POINT_VAL) { uint8_t reqstatus; uint8_t* value; uint16_t length; struct uds_ucp_req ucp_req; // Update the attribute value (note several write could be required since // attribute length > (ATT_MTU-3) attmdb_att_update_value(param->handle, param->length, param->offset, (uint8_t*)&(param->value[0])); // retrieve full data. attmdb_att_get_value(param->handle, &length, &value); // unpack user control point value reqstatus = udss_unpack_ucp_req(value, length, &ucp_req); // check unpacked status switch(reqstatus) { case PRF_APP_ERROR: { /* Do nothing, ignore request since it's not complete and maybe * requires several peer write to be performed. */ } break; case PRF_ERR_OK: { // check wich request shall be send to api task switch(ucp_req.op_code) { case UDS_REQ_REG_NEW_USER: case UDS_REQ_CONSENT: case UDS_REQ_DEL_USER_DATA: { //forward request operation to application struct udss_ucp_req_ind * req = KE_MSG_ALLOC(UDSS_UCP_REQ_IND, udss_env.con_info.appid, TASK_UDSS, udss_ucp_req_ind); // UCP on going. // UDSS_SET(UCP_ON_GOING); req->conhdl = gapc_get_conhdl(udss_env.con_info.conidx); req->ucp_req = ucp_req; ke_msg_send(req); } break; // case UDS_REQ_ABORT_OP: // { // // nothing to abort, send an error message. // struct uds_ucp_rsp ucp_rsp; // ucp_rsp.op_code = UDS_REQ_RSP_CODE; // ucp_rsp.operand.rsp.op_code_req = // ucp_req.op_code; // ucp_rsp.operand.rsp.status = UDS_RSP_ABORT_UNSUCCESSFUL; // // send user control response indication // udss_send_ucp_rsp(&(ucp_rsp), // TASK_UDSS); // } // break; default: { // nothing to do since it's handled during unpack } break; } } break; default: { /* There is an error in user control request, inform peer * device that request is incorrect. */ struct uds_ucp_rsp ucp_rsp; ucp_rsp.op_code = UDS_REQ_RSP_CODE; ucp_rsp.req_op_code = ucp_req.op_code; ucp_rsp.rsp_val = reqstatus; // send user control response indication udss_send_ucp_rsp(&(ucp_rsp), TASK_UDSS); } break; } } // not expected request else { status = ATT_ERR_WRITE_NOT_PERMITTED; } } if(param->response) { // Send Write Response atts_write_rsp_send(udss_env.con_info.conidx, param->handle, status); } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref GL2C_CODE_ATT_WR_CMD_IND message. * The handler compares the new values with current ones and notifies them if they changed. * @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) { // Update the attribute value attmdb_att_update_value(param->handle, param->length, param->offset, (uint8_t*)&(param->value[0])); switch (ACCEL_IDX(param->handle)) { case ACCEL_IDX_ENABLE_VAL: { uint16_t len; uint8_t* accel_en; uint8_t* axis_en; uint8_t* range; if(*(uint8_t*)&(param->value[0]) > 1) accel_threshold = *(uint8_t*)&(param->value[0]) - 2; // set_accel_thr(); attmdb_att_get_value(ACCEL_HANDLE(ACCEL_IDX_ENABLE_VAL), &(len), &(accel_en)); // Indicate to the application the state of the profile if (accel_en) { // Allocate the start indication message struct accel_start_ind *ind = KE_MSG_ALLOC(ACCEL_START_IND, accel_env.con_info.appid, dest_id, accel_start_ind); // Fill in the parameter structure for (int i = 0; i < ACCEL_MAX; i++) { attmdb_att_get_value(ACCEL_DIR_VAL_HANDLE(i), &(len), &(axis_en)); ind->accel_en[i] = *axis_en; } attmdb_att_get_value(ACCEL_HANDLE(ACCEL_IDX_RANGE_VAL), &(len), &(range)); ind->range = *range; // Send the message ke_msg_send(ind); } else { // Send the stop indication ke_msg_send_basic(ACCEL_STOP_IND, accel_env.con_info.appid, TASK_ACCEL); } } break; case ACCEL_IDX_ACCEL_DISPLAY1_VAL: case ACCEL_IDX_ACCEL_DISPLAY2_VAL: if(*(uint8_t*)&(param->value[0]) == 0xFF) { if(param->length > 1 && *(uint8_t*)&(param->value[1]) > 1) accel_con_interval = *(uint8_t*)&(param->value[1]); if(param->length > 2 && *(uint8_t*)&(param->value[2]) > 1) accel_mode = *(uint8_t*)&(param->value[2])-2; if(param->length > 3 && *(uint8_t*)&(param->value[3]) > 1) accel_latency = *(uint8_t*)&(param->value[3])-2; if(param->length > 4 && *(uint8_t*)&(param->value[4]) > 1) accel_window = *(uint8_t*)&(param->value[4]); } { uint8_t line; uint16_t len; uint8_t* display; struct accel_write_line_ind *ind = KE_MSG_ALLOC(ACCEL_WRITE_LINE_IND, accel_env.con_info.appid, TASK_ACCEL, accel_write_line_ind); line = (param->handle == ACCEL_HANDLE(ACCEL_IDX_ACCEL_DISPLAY1_VAL))?0:1; attmdb_att_get_value(param->handle, &(len), &(display)); // Fill in the parameter structure memcpy(ind->text, display, len); ind->line = line; // Send the message ke_msg_send(ind); } atts_write_rsp_send(accel_env.con_info.conidx, param->handle, PRF_ERR_OK); break; case ACCEL_IDX_ACCEL_X_VAL: case ACCEL_IDX_ACCEL_X_EN: if(*(uint8_t*)&(param->value[0]) > 1) accel_adv_interval1 = *(uint8_t*)&(param->value[0]); atts_write_rsp_send(accel_env.con_info.conidx, param->handle, PRF_ERR_OK); break; case ACCEL_IDX_ACCEL_Y_VAL: case ACCEL_IDX_ACCEL_Y_EN: if(*(uint8_t*)&(param->value[0]) > 1) accel_adv_interval2 = *(uint8_t*)&(param->value[0]); if(*(uint8_t*)&(param->value[0]) == 255) accel_adv_interval2 = 0; atts_write_rsp_send(accel_env.con_info.conidx, param->handle, PRF_ERR_OK); break; case ACCEL_IDX_ACCEL_Z_VAL: case ACCEL_IDX_ACCEL_Z_EN: if(*(uint8_t*)&(param->value[0]) > 1) accel_adv_interval3 = *(uint8_t*)&(param->value[0]); if(*(uint8_t*)&(param->value[0]) == 255) accel_adv_interval3 = 0; atts_write_rsp_send(accel_env.con_info.conidx, param->handle, PRF_ERR_OK); break; default: atts_write_rsp_send(accel_env.con_info.conidx, param->handle, PRF_ERR_OK); break; } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref GL2C_CODE_ATT_WR_CMD_IND message. * The handler will * @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) { uint16_t value = 0x0000; uint8_t char_code = HPS_ERR_CHAR; uint8_t status = PRF_APP_ERROR; if (KE_IDX_GET(src_id) == hpss_env.con_info.conidx) { if (param->handle == hpss_env.hps_shdl + HPS_IDX_URI_VAL) { char_code = HPS_URI_CHAR; } else if (param->handle == hpss_env.hps_shdl + HPS_IDX_HEADER_VAL) { char_code = HPS_HEADER_CHAR; } else if (param->handle == hpss_env.hps_shdl + HPS_IDX_BODY_VAL) { char_code = HPS_BODY_CHAR; } else if (param->handle == hpss_env.hps_shdl + HPS_IDX_CNTL_PT_VAL) { char_code = HPS_CNTL_PT_CHAR; } //this case is processed seperately else if (param->handle == hpss_env.hps_shdl + HPS_IDX_STATUS_CODE_CFG) { //Extract value before check memcpy(&value, &(param->value), sizeof(uint16_t)); if ((value == PRF_CLI_STOP_NTFIND) || (value == PRF_CLI_START_NTF)) { status = PRF_ERR_OK; if (value == PRF_CLI_STOP_NTFIND) { hpss_env.features &= ~HPSS_STATUS_CODE_NTF_CFG; } else //PRF_CLI_START_NTF { hpss_env.features |= HPSS_STATUS_CODE_NTF_CFG; } } else { status = PRF_APP_ERROR; } if (status == PRF_ERR_OK) { //Update the attribute value attmdb_att_set_value(param->handle, sizeof(uint16_t), (uint8_t *)&value); if(param->last) { //Inform APP of configuration change struct hpss_cfg_indntf_ind * ind = KE_MSG_ALLOC(HPSS_CFG_INDNTF_IND, hpss_env.con_info.appid, TASK_HPSS, hpss_cfg_indntf_ind); ind->conhdl = gapc_get_conhdl(hpss_env.con_info.conidx); memcpy(&ind->cfg_val, &value, sizeof(uint16_t)); ke_msg_send(ind); } } //If HPS, send write response if (param->response != 0x00) { // Send Write Response atts_write_rsp_send(hpss_env.con_info.conidx, param->handle, status); } return (KE_MSG_CONSUMED); } if (char_code != HPS_ERR_CHAR) { //Save value in DB attmdb_att_set_value(param->handle, sizeof(uint8_t), (uint8_t *)¶m->value[0]); status = PRF_ERR_OK; switch(char_code) { case HPS_URI_CHAR: if ((param->length + param->offset) <= HPS_URI_MAX_LEN) { // First part of the uri value if (param->offset == 0) { // Set value in the database attmdb_att_set_value(param->handle, param->length, (uint8_t *)¶m->value[0]); } else { // Complete the value stored in the database attmdb_att_update_value(param->handle, param->length, param->offset, (uint8_t *)¶m->value[0]); } if(param->last) { uint16_t len = 0; uint8_t *data = NULL; // Get complete uri value and length attmdb_att_get_value(param->handle, &len, &data); // Inform APP. Allocate the URI value change indication struct hpss_uri_ind *ind = KE_MSG_ALLOC(HPSS_URI_IND, hpss_env.con_info.appid, TASK_HPSS, hpss_uri_ind); // Fill in the parameter structure ind->conhdl = gapc_get_conhdl(hpss_env.con_info.conidx); ind->char_code = HPS_URI_CHAR; ind->len = len; memcpy(&ind->uri, data, len); ke_msg_send(ind); } } break; case HPS_HEADER_CHAR: if ((param->length + param->offset) <= HPS_HEADER_MAX_LEN) { // First part of the uri value if (param->offset == 0) { // Set value in the database attmdb_att_set_value(param->handle, param->length, (uint8_t *)¶m->value[0]); } else { // Complete the value stored in the database attmdb_att_update_value(param->handle, param->length, param->offset, (uint8_t *)¶m->value[0]); } if(param->last) { uint16_t len = 0; uint8_t *data = NULL; // Get complete uri value and length attmdb_att_get_value(param->handle, &len, &data); // Inform APP. Allocate the URI value change indication struct hpss_header_ind *ind = KE_MSG_ALLOC(HPSS_HEADER_IND, hpss_env.con_info.appid, TASK_HPSS, hpss_header_ind); // Fill in the parameter structure ind->conhdl = gapc_get_conhdl(hpss_env.con_info.conidx); ind->char_code = HPS_HEADER_CHAR; ind->len = len; memcpy(&ind->header, data, len); ke_msg_send(ind); } } break; case HPS_BODY_CHAR: if ((param->length + param->offset) <= HPS_BODY_MAX_LEN) { // First part of the uri value if (param->offset == 0) { // Set value in the database attmdb_att_set_value(param->handle, param->length, (uint8_t *)¶m->value[0]); } else { // Complete the value stored in the database attmdb_att_update_value(param->handle, param->length, param->offset, (uint8_t *)¶m->value[0]); } if(param->last) { uint16_t len = 0; uint8_t *data = NULL; // Get complete uri value and length attmdb_att_get_value(param->handle, &len, &data); // Inform APP. Allocate the URI value change indication struct hpss_body_ind *ind = KE_MSG_ALLOC(HPSS_BODY_IND, hpss_env.con_info.appid, TASK_HPSS, hpss_body_ind); // Fill in the parameter structure ind->conhdl = gapc_get_conhdl(hpss_env.con_info.conidx); ind->char_code = HPS_BODY_CHAR; ind->len = len; memcpy(&ind->body, data, len); ke_msg_send(ind); } } break; case HPS_CNTL_PT_CHAR: if ((param->length + param->offset) <= HPS_CNTL_PT_MAX_LEN) { // First part of the uri value if (param->offset == 0) { // Set value in the database attmdb_att_set_value(param->handle, param->length, (uint8_t *)¶m->value[0]); } else { // Complete the value stored in the database attmdb_att_update_value(param->handle, param->length, param->offset, (uint8_t *)¶m->value[0]); } if(param->last) { uint16_t len = 0; uint8_t *data = NULL; // Get complete uri value and length attmdb_att_get_value(param->handle, &len, &data); // Inform APP. Allocate the URI value change indication struct hpss_cntl_pt_ind *ind = KE_MSG_ALLOC(HPSS_CNTL_PT_IND, hpss_env.con_info.appid, TASK_HPSS, hpss_cntl_pt_ind); // Fill in the parameter structure ind->conhdl = gapc_get_conhdl(hpss_env.con_info.conidx); ind->char_code = HPS_CNTL_PT_CHAR; ind->len = len; memcpy(&ind->cntl_pt, data, len); ke_msg_send(ind); } } break; default: break; } //If HPS, send write response if (param->response != 0x00) { // Send Write Response atts_write_rsp_send(hpss_env.con_info.conidx, param->handle, status); } } } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Handles reception of the @ref GL2C_CODE_ATT_WR_CMD_IND message. * The handler compares the new values with current ones and notifies them if they changed. * @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 status = ATT_ERR_INSUFF_AUTHOR; // check connection if (KE_IDX_GET(src_id) == glps_env.con_info.conidx) { uint8_t att_idx = GLPS_IDX(param->handle); status = PRF_ERR_OK; // check if it's a client configuration char if(glps_att_db[att_idx].uuid == ATT_DESC_CLIENT_CHAR_CFG) { uint16_t cli_cfg; uint8_t evt_mask = GLPS_IND_NTF_EVT(att_idx); // get client configuration cli_cfg = co_read16(&(param->value)); // stop indication/notification if(cli_cfg == PRF_CLI_STOP_NTFIND) { glps_env.evt_cfg &= ~evt_mask; } // start indication/notification (check that char value accept it) else if((((glps_att_db[att_idx-1].perm & PERM(IND, ENABLE)) != 0) && cli_cfg == PRF_CLI_START_IND) ||(((glps_att_db[att_idx-1].perm & PERM(NTF, ENABLE)) != 0) && cli_cfg == PRF_CLI_START_NTF)) { glps_env.evt_cfg |= evt_mask; } // improper value else { status = GLP_ERR_IMPROPER_CLI_CHAR_CFG; } if (status == PRF_ERR_OK) { //Inform APP of configuration change struct glps_cfg_indntf_ind * ind = KE_MSG_ALLOC(GLPS_CFG_INDNTF_IND, glps_env.con_info.appid, TASK_GLPS, glps_cfg_indntf_ind); //Update the attribute value attmdb_att_set_value(param->handle, sizeof(uint16_t), (uint8_t *)&cli_cfg); ind->conhdl = gapc_get_conhdl(glps_env.con_info.conidx); ind->evt_cfg = glps_env.evt_cfg; ke_msg_send(ind); } } else if (glps_att_db[att_idx].uuid == ATT_CHAR_REC_ACCESS_CTRL_PT) { uint8_t reqstatus; uint8_t* value; uint16_t length; struct glp_racp_req racp_req; if((glps_env.evt_cfg & GLPS_RACP_IND_CFG) == 0) { // do nothing since indication not enabled for this characteristic status = GLP_ERR_IMPROPER_CLI_CHAR_CFG; } // If a request is on going else if(GLPS_IS(RACP_ON_GOING)) { // if it's an abort command, execute it. if((param->offset == 0) && (param->value[0] == GLP_REQ_ABORT_OP)) { //forward abort operation to application struct glps_racp_req_ind * req = KE_MSG_ALLOC(GLPS_RACP_REQ_IND, glps_env.con_info.appid, TASK_GLPS, glps_racp_req_ind); req->conhdl = gapc_get_conhdl(glps_env.con_info.conidx); req->racp_req.op_code = GLP_REQ_ABORT_OP; req->racp_req.filter.operator = 0; ke_msg_send(req); } else { // do nothing since a procedure already in progress status = GLP_ERR_PROC_ALREADY_IN_PROGRESS; } } else { // Update the attribute value (note several write could be required since // attribute length > (ATT_MTU-3) attmdb_att_update_value(param->handle, param->length, param->offset, (uint8_t*)&(param->value[0])); // retrieve full data. attmdb_att_get_value(param->handle, &length, &value); // unpack record access control point value reqstatus = glps_unpack_racp_req(value, length, &racp_req); // check unpacked status switch(reqstatus) { case PRF_APP_ERROR: { /* Do nothing, ignore request since it's not complete and maybe * requires several peer write to be performed. */ } break; case PRF_ERR_OK: { // check wich request shall be send to api task switch(racp_req.op_code) { case GLP_REQ_REP_STRD_RECS: case GLP_REQ_DEL_STRD_RECS: case GLP_REQ_REP_NUM_OF_STRD_RECS: { //forward request operation to application struct glps_racp_req_ind * req = KE_MSG_ALLOC(GLPS_RACP_REQ_IND, glps_env.con_info.appid, TASK_GLPS, glps_racp_req_ind); // RACP on going. GLPS_SET(RACP_ON_GOING); req->conhdl = gapc_get_conhdl(glps_env.con_info.conidx); req->racp_req = racp_req; ke_msg_send(req); } break; case GLP_REQ_ABORT_OP: { // nothing to abort, send an error message. struct glp_racp_rsp racp_rsp; racp_rsp.op_code = GLP_REQ_RSP_CODE; racp_rsp.operand.rsp.op_code_req = racp_req.op_code; racp_rsp.operand.rsp.status = GLP_RSP_ABORT_UNSUCCESSFUL; // send record access control response indication glps_send_racp_rsp(&(racp_rsp), TASK_GLPS); } break; default: { // nothing to do since it's handled during unpack } break; } } break; default: { /* There is an error in record access control request, inform peer * device that request is incorrect. */ struct glp_racp_rsp racp_rsp; racp_rsp.op_code = GLP_REQ_RSP_CODE; racp_rsp.operand.rsp.op_code_req = racp_req.op_code; racp_rsp.operand.rsp.status = reqstatus; // send record access control response indication glps_send_racp_rsp(&(racp_rsp), TASK_GLPS); } break; } } } // not expected request else { status = ATT_ERR_WRITE_NOT_PERMITTED; } } if(param->response) { //Send write response atts_write_rsp_send(glps_env.con_info.conidx, param->handle, status); } return (KE_MSG_CONSUMED); }