Exemple #1
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GATT_READ_CHAR_RESP message.
 * Generic event received after every simple read command sent to peer server.
 * @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_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 qppc_env_tag *qppc_env = PRF_CLIENT_GET_ENV(dest_id, qppc);

    struct qppc_rd_char_rsp * rsp = KE_MSG_ALLOC_DYN(QPPC_RD_CHAR_RSP,
                                                     qppc_env->con_info.appid, dest_id,
                                                     qppc_rd_char_rsp, param->data.len);

    rsp->conhdl = qppc_env->con_info.conhdl;
    rsp->status = param->status;
    rsp->char_code = qppc_env->last_char_code;
    rsp->data.len = param->data.len;
    rsp->data.each_len = param->data.each_len;
    memcpy(&rsp->data.data[0], &param->data.data[0], param->data.len);

    ke_msg_send(rsp);

    return (KE_MSG_CONSUMED);
}
Exemple #2
0
void rscps_send_cmp_evt(uint8_t src_id, uint8_t dest_id, uint16_t conhdl,
                        uint8_t operation, uint8_t status)
{
    // Go back to the Connected state if the state is busy
    if (ke_state_get(src_id) == RSCPS_BUSY)
    {
        ke_state_set(src_id, RSCPS_CONNECTED);
    }

    // Set the operation code
    rscps_env.operation = RSCPS_RESERVED_OP_CODE;

    // Send the message
    struct rscps_cmp_evt *evt = KE_MSG_ALLOC(RSCPS_CMP_EVT,
                                             dest_id, src_id,
                                             rscps_cmp_evt);

    evt->conhdl     = conhdl;
    evt->operation  = operation;
    evt->status     = status;

    ke_msg_send(evt);
}
Exemple #3
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GATTC_READ_IND message.
 * Generic event received after every simple read command sent to peer server.
 * @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_read_ind_handler(ke_msg_id_t const msgid,
                                    struct gattc_read_ind const *param,
                                    ke_task_id_t const dest_id,
                                    ke_task_id_t const src_id)
{
    // Get the address of the environment
    struct glpc_env_tag *glpc_env = PRF_CLIENT_GET_ENV(dest_id, glpc);

    struct glpc_read_features_rsp * rsp = KE_MSG_ALLOC(GLPC_READ_FEATURES_RSP,
                                                       glpc_env->con_info.appid, dest_id,
                                                       glpc_read_features_rsp);
    // set connection handle
    rsp->conhdl = gapc_get_conhdl(glpc_env->con_info.conidx);
    // set error status
    rsp->status = ATT_ERR_NO_ERROR;

    // unpack feature information
    rsp->features = co_read16p(param->value);

    ke_msg_send(rsp);

    return (KE_MSG_CONSUMED);
}
Exemple #4
0
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);
}
Exemple #5
0
/**
 ****************************************************************************************
 * @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.
 ****************************************************************************************
 */
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 (ke_state_get(dest_id) == APP_DISABLED)
    {
        // reset the lower layers.
        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);
    }
    else
    {
        // APP_DISABLED state is used to wait the GAP_READY_EVT message
        ASSERT_ERR(0);
    }

    return (KE_MSG_CONSUMED);
}
Exemple #6
0
/**
 ****************************************************************************************
 * @brief Handles reception of encrypt request command
 *
 * @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.
 ****************************************************************************************
 */
int gapc_encrypt_req_ind_handler(ke_msg_id_t const msgid,
        struct gapc_encrypt_req_ind *param,
        ke_task_id_t const dest_id,
        ke_task_id_t const src_id)
{
    struct gapc_encrypt_cfm* cfm = KE_MSG_ALLOC(GAPC_ENCRYPT_CFM, src_id, dest_id, gapc_encrypt_cfm);
    
    if (!app_validate_encrypt_req_func(param))
    {
        cfm->found = false;
    }
    else
    {
        if(((app_sec_env.auth & GAP_AUTH_BOND) != 0)
            && (memcmp(&(app_sec_env.rand_nb), &(param->rand_nb), RAND_NB_LEN) == 0)
            && (app_sec_env.ediv == param->ediv))
        {
            cfm->found = true;
            cfm->key_size = app_sec_env.key_size;
            memcpy(&(cfm->ltk), &(app_sec_env.ltk), KEY_LEN);
            // update connection auth
            app_connect_confirm(app_sec_env.auth);
            app_sec_encrypt_complete_func();
        }
        else
        {
            cfm->found = false;
        }
    }
    
    ke_msg_send(cfm);
    
    if (cfm->found == false)
        app_disconnect();

    return (KE_MSG_CONSUMED);
}
/**
 ****************************************************************************************
 * @brief Handles read command characteristic event indication from device_config profile
 *
 * @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.
 ****************************************************************************************
 */
int app_device_read_request_ind_handler(ke_msg_id_t const msgid,
                                      struct device_config_read_request_ind const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    uint8_t status = 0;
    
    // Allocate message
   struct device_config_read_response_cmd *cmd = KE_MSG_ALLOC(DEVICE_READ_RESPONSE_CMD,
                                              TASK_DEVICE_CONFIG, TASK_APP,
                                              device_config_read_response_cmd);

    if (param->param_id >=  app_device_config_env.params_num)
    {
        status = 1;
    }
    
    if (!status)
    {
        
        cmd->size = app_device_config_env.params[param->param_id].size;
        memcpy(cmd->val, app_device_config_env.params[param->param_id].p_data, cmd->size );
        
    }
    else
    {
        cmd->size = 0;
    }
    
    cmd->param_id = param->param_id;
    cmd->conhdl = app_env.conhdl;    
    cmd->status = status;
    
    ke_msg_send(cmd);
    
    return (KE_MSG_CONSUMED);
}
Exemple #8
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GL2C_CODE_ATT_WR_CMD_IND message.
 * The message is redirected from TASK_SVC because at profile enable, the ATT handle is
 * register for TASK_FINDT. In the handler, an ATT Write Response/Error Response should
 * be sent for ATT protocol, but Alert Level Characteristic only supports WNR so no
 * response PDU is needed.
 * @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 alert_lvl = 0x0000;

    if (KE_IDX_GET(src_id) == findt_env.con_info.conidx)
    {
        if(param->handle == findt_env.shdl + FINDT_IAS_IDX_ALERT_LVL_VAL)
        {
            alert_lvl = param->value[0];

            //Check if Alert Level is valid
            if ((param->value[0] <= FINDT_ALERT_HIGH))
            {
                //Update the attribute value
                attmdb_att_set_value(param->handle, sizeof(uint8_t), (uint8_t *)&alert_lvl);
                if(param->last)
                {
                    // Allocate the alert value change indication
                    struct findt_alert_ind *ind = KE_MSG_ALLOC(FINDT_ALERT_IND, findt_env.con_info.appid,
                                                               TASK_FINDT, findt_alert_ind);
                    // Fill in the parameter structure
                    ind->conhdl    = gapc_get_conhdl(findt_env.con_info.conidx);
                    ind->alert_lvl = alert_lvl;

                    // Send the message
                    ke_msg_send(ind);
                }
                // It was a Write Without Response so no RSP needed.
            }
        }
    }

    return (KE_MSG_CONSUMED);
}
/**
 ****************************************************************************************
 * @brief Handles start indication from the Proximity Reporter profile.
 *
 * @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.
 ****************************************************************************************
 */
int accel_create_db_cfm_handler(ke_msg_id_t const msgid,
                                      struct accel_create_db_cfm const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    // If state is not idle, ignore the message
    if (ke_state_get(dest_id) == APP_DB_INIT)
    {
							
				app_accel_init();
        
        // Inform the Application Manager
        struct app_module_init_cmp_evt *cfm = KE_MSG_ALLOC(APP_MODULE_INIT_CMP_EVT,
                                                           TASK_APP, TASK_APP,
                                                           app_module_init_cmp_evt);

        cfm->status = CO_ERROR_NO_ERROR;    //param->status;

        ke_msg_send(cfm);
			
    }

    return (KE_MSG_CONSUMED);
}
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 HPSS_CREATE_DB_REQ message.
 * The handler adds HPS into the database.
 * @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 hpss_create_db_req_handler(ke_msg_id_t const msgid,
                                      struct hpss_create_db_req const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    //Database Creation Status
    uint8_t status;

    //Save Profile ID
    hpss_env.con_info.prf_id = TASK_HPSS;

    /*---------------------------------------------------*
     * HTTP Proxy Service Creation
     *---------------------------------------------------*/

    //Add Service Into Database
    status = attm_svc_create_db(&hpss_env.hps_shdl, NULL, HPS_IDX_NB, NULL,
                                dest_id, &hpss_att_db[0]);
    //Disable HPS
    attmdb_svc_set_permission(hpss_env.hps_shdl, PERM(SVC, DISABLE));

    //Go to Idle State
    if (status == ATT_ERR_NO_ERROR)
    {
        //If we are here, database has been fulfilled with success, go to idle state
        ke_state_set(TASK_HPSS, HPSS_IDLE);
    }

    //Send CFM to application
    struct hpss_create_db_cfm * cfm = KE_MSG_ALLOC(HPSS_CREATE_DB_CFM, src_id,
                                      TASK_HPSS, hpss_create_db_cfm);
    cfm->status = status;
    ke_msg_send(cfm);

    return (KE_MSG_CONSUMED);
}
Exemple #12
0
void app_hrps_enable(void)
{
    // Allocate the message
    struct hrps_enable_req * req = KE_MSG_ALLOC(HRPS_ENABLE_REQ, TASK_HRPS, TASK_APP,
                                                 hrps_enable_req);
		//结构体填充部分需要后续改善
    // Fill in the parameter structure
    ///Connection handle
    req->conhdl = app_env.conhdl;
    /// security level: b0= nothing, b1=unauthenticated, b2=authenticated, b3=authorized;
    /// b1 or b2 and b3 can go together
    req->sec_lvl = PERM(SVC, ENABLE);
    ///Type of connection - will someday depend on button press length; can be CFG or DISCOVERY
    req->con_type = PRF_CON_NORMAL;// PRF_CON_DISCOVERY;

    /// Heart Rate Notification configuration
    req->hr_meas_ntf_en = 1;//PRF_CLI_START_NTF;//PRF_CLI_STOP_NTFIND

    ///Body Sensor Location
    req->body_sensor_loc = 1;

    // Send the message
    ke_msg_send(req);
}
Exemple #13
0
void disc_enable_cfm_send(struct disc_env_tag *disc_env, struct prf_con_info *con_info, uint8_t status)
{
    // Send APP the details of the discovered attributes on DISS
    struct disc_enable_cfm * rsp = KE_MSG_ALLOC(DISC_ENABLE_CFM,
                                                con_info->appid, con_info->prf_id,
                                                disc_enable_cfm);

    rsp->conhdl = gapc_get_conhdl(con_info->conidx);
    rsp->status = status;

    if (status == PRF_ERR_OK)
    {
        rsp->dis = disc_env->dis;

        // Go to connected state
        ke_state_set(con_info->prf_id, DISC_CONNECTED);
    }
    else
    {
        PRF_CLIENT_ENABLE_ERROR(disc_envs, con_info->prf_id, DISC);
    }

    ke_msg_send(rsp);
}
Exemple #14
0
/*
 ****************************************************************************************
 * @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);
}
Exemple #15
0
static int diss_create_db_req_handler(ke_msg_id_t const msgid,
                                      struct diss_create_db_req const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    //Service content flag
    uint32_t cfg_flag;
    //DB Creation Statis
    uint8_t status = ATT_ERR_NO_ERROR;

    //Save profile id
    diss_env.con_info.prf_id = TASK_DISS;

    //Compute Attribute Table and save it in environment
    cfg_flag = diss_compute_cfg_flag(param->features);

    status = attm_svc_create_db(&diss_env.shdl, (uint8_t *)&cfg_flag, DIS_IDX_NB, &diss_env.att_tbl[0],
                                dest_id, &diss_att_db[0]);

    if (status == ATT_ERR_NO_ERROR)
    {
        //Disable service
        status = attmdb_svc_set_permission(diss_env.shdl, PERM(SVC, DISABLE));

        //If we are here, database has been fulfilled with success, go to idle test
        ke_state_set(TASK_DISS, DISS_IDLE);
    }

    //Send response to application
    struct diss_create_db_cfm * cfm = KE_MSG_ALLOC(DISS_CREATE_DB_CFM, src_id, TASK_DISS,
                                                   diss_create_db_cfm);
    cfm->status = status;
    ke_msg_send(cfm);

    return (KE_MSG_CONSUMED);
}
Exemple #16
0
/**
 ****************************************************************************************
 * @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);
}
Exemple #17
0
/**
 ****************************************************************************************
 * @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, &param->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);
}
Exemple #18
0
/**
 ****************************************************************************************
 * @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.
 ****************************************************************************************
 */
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)
{	
    switch(param->operation)
    {
        // reset completed
        case GAPM_RESET:
        {
            if(param->status != GAP_ERR_NO_ERROR)
            {
                ASSERT_ERR(0); // unexpected error
            }
            else
            {

                // 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);

                app_configuration_func(dest_id, cmd);

                ke_msg_send(cmd);
            }
        }
        break;

        // device configuration updated
        case GAPM_SET_DEV_CONFIG:
        {
            if(param->status != GAP_ERR_NO_ERROR)
            {
                ASSERT_ERR(0); // unexpected error
            }
            else
            {
              app_set_dev_config_complete_func();
            }
        }
        break;

        // Advertising finished
        case GAPM_ADV_UNDIRECT:
        {
            app_adv_undirect_complete(param->status);
        }
        break;
        
        // Directed advertising finished
        case GAPM_ADV_DIRECT:
        {
            app_adv_direct_complete(param->status);  
        }
        break;
				
        case GAPM_SCAN_PASSIVE:
		case GAPM_SCAN_ACTIVE:
        {
            if (param->status == GAP_ERR_CANCELED)
            {
                app_connect();
            }						
            else 
            {
                app_scanning();
            }
        }				
        break;
        /* end */
				
        case GAPM_CANCEL:
        {
            if(param->status != GAP_ERR_NO_ERROR)
            {
                ASSERT_ERR(0); // unexpected error
            }
        }
		case GAPM_CONNECTION_DIRECT:
            if (param->status == GAP_ERR_CANCELED)
            {
				app_connect_failed_func();
            }
				break;
        default:
        {
            ASSERT_ERR(0); // unexpected error
        }
        break;
    }
		
    return (KE_MSG_CONSUMED);
}
Exemple #19
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GATT_READ_CHAR_RESP message.
 * Generic event received after every simple read command sent to peer server.
 * @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_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)
{
    uint8_t error_status = param->status;
    // Get the address of the environment
    struct hogpbh_env_tag *hogpbh_env = PRF_CLIENT_GET_ENV(dest_id, hogpbh);

    if (error_status == PRF_ERR_OK)
    {
        switch (hogpbh_env->last_char_code)
        {
            // Boot Keyboard Input Report Read Response
            case (HOGPBH_CHAR_BOOT_KB_IN_REPORT):
            // Boot Mouse Input Report Read Response
            case (HOGPBH_CHAR_BOOT_MOUSE_IN_REPORT):
            // Boot Mouse Input Report Read Response
            case (HOGPBH_CHAR_BOOT_KB_OUT_REPORT):
            {
                // Check report length
                if (param->data.len <= HOGPBH_BOOT_REPORT_MAX_LEN)
                {
                    struct hogpbh_boot_report_ind *ind = KE_MSG_ALLOC_DYN(HOGPBH_BOOT_REPORT_IND,
                                                                          hogpbh_env->con_info.appid, dest_id,
                                                                          hogpbh_boot_report_ind,
                                                                          param->data.len);

                    ind->conhdl         = hogpbh_env->con_info.conhdl;
                    ind->ind_type       = HOGPBH_IND_RD_RSP;
                    ind->hids_nb        = hogpbh_env->last_svc_inst_req;
                    ind->char_code      = hogpbh_env->last_char_code;
                    ind->report_length  = param->data.len;
                    memcpy(&ind->report[0], &param->data.data[0], param->data.len);

                    ke_msg_send(ind);
                }
                else
                {
                    error_status = PRF_ERR_UNEXPECTED_LEN;
                }

                break;
            }

            //Protocol Mode Read Response
            case (HOGPBH_CHAR_PROTO_MODE):
            {
                struct hogpbh_proto_mode_rd_rsp *rsp = KE_MSG_ALLOC(HOGPBH_PROTO_MODE_RD_RSP,
                                                                    hogpbh_env->con_info.appid, dest_id,
                                                                    hogpbh_proto_mode_rd_rsp);

                rsp->conhdl     = hogpbh_env->con_info.conhdl;
                rsp->hids_nb    = hogpbh_env->last_svc_inst_req;
                memcpy(&rsp->proto_mode, &param->data.data[0], sizeof(uint8_t));

                ke_msg_send(rsp);

                break;
            }

            //Client Characteristic Configuration
            case (HOGPBH_RD_WR_HIDS_BOOT_KB_IN_REPORT_CFG):
            case (HOGPBH_RD_WR_HIDS_BOOT_MOUSE_IN_REPORT_CFG):
            {
                struct hogpbh_cfg_ntf_rd_rsp *rsp = KE_MSG_ALLOC(HOGPBH_CFG_NTF_RD_RSP,
                                                                 hogpbh_env->con_info.appid, dest_id,
                                                                 hogpbh_cfg_ntf_rd_rsp);

                rsp->conhdl     = hogpbh_env->con_info.conhdl;
                rsp->desc_code  = hogpbh_env->last_char_code;
                rsp->hids_nb    = hogpbh_env->last_svc_inst_req;
                memcpy(&rsp->cfg_val, &param->data.data[0], sizeof(uint16_t));

                ke_msg_send(rsp);

                break;
            }

            default:
                break;
        }
    }

    if (error_status != PRF_ERR_OK)
    {
        hogpbh_char_req_rsp_send(hogpbh_env, HOGPBH_RD_CHAR_ERR_RSP, error_status);
    }

    return (KE_MSG_CONSUMED);
}
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GATT_HANDLE_VALUE_NTF 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 gatt_handle_value_ntf_handler(ke_msg_id_t const msgid,
                                        struct gatt_handle_value_notif 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)
    {
        // Offset
        uint8_t offset = CSCP_CSC_MEAS_MIN_LEN;

        // CSC Measurement value has been received
        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);

        // Connection Handle
        ind->conhdl   = param->conhdl;
        // Attribute code
        ind->att_code = CSCPC_NTF_CSC_MEAS;

        /*----------------------------------------------------
         * Unpack Measurement --------------------------------
         *----------------------------------------------------*/

        // Flags
        ind->value.csc_meas.flags = param->value[0];

        // Cumulative Wheel Revolutions
        // Last Wheel Event Time
        if ((param->value[0] & CSCP_MEAS_WHEEL_REV_DATA_PRESENT) == CSCP_MEAS_WHEEL_REV_DATA_PRESENT)
        {
            // Cumulative Wheel Revolutions
            ind->value.csc_meas.cumul_wheel_rev = co_read32p(&param->value[offset]);
            offset += 4;

            // Last Wheel Event Time
            ind->value.csc_meas.last_wheel_evt_time = co_read16p(&param->value[offset]);
            offset += 2;
        }

        // Cumulative Crank Revolutions
        // Last Crank Event Time
        if ((param->value[0] & CSCP_MEAS_CRANK_REV_DATA_PRESENT) == CSCP_MEAS_CRANK_REV_DATA_PRESENT)
        {
            // Cumulative Crank Revolutions
            ind->value.csc_meas.cumul_crank_rev = co_read16p(&param->value[offset]);
            offset += 2;

            // Last Crank Event Time
            ind->value.csc_meas.last_crank_evt_time = co_read16p(&param->value[offset]);
        }

        ke_msg_send(ind);
    }
    // else ignore the message

    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);
}
Exemple #22
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GLPS_ENABLE_REQ message.
 * The handler enables the Glucose Sensor Profile and initialize readable values.
 * @param[in] msgid Id of the message received (probably unused).off
 * @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 glps_enable_req_handler(ke_msg_id_t const msgid,
                                   struct glps_enable_req const *param,
                                   ke_task_id_t const dest_id,
                                   ke_task_id_t const src_id)
{
    uint8_t status = PRF_ERR_REQ_DISALLOWED;

    if(!GLPS_IS(ENABLE))
    {
        // Check if the provided connection exist
        if (gap_get_rec_idx(param->conhdl) != GAP_INVALID_CONIDX)
        {
            status = PRF_ERR_OK;

            GLPS_SET(ENABLE);

            //Value used to initialize all readable value in DB
            uint16_t indntf_cfg = PRF_CLI_STOP_NTFIND;

            // Save the application task id
            glps_env.con_info.appid = src_id;
            // Save the connection handle associated to the profile
            glps_env.con_info.conhdl = param->conhdl;

            // No RACP at service start.
            GLPS_CLEAR(RACP_ON_GOING);
            GLPS_CLEAR(SENDING_MEAS);

            // Configure Glucose Measuremment IND Cfg in DB
            if(param->con_type == PRF_CON_NORMAL)
            {
                glps_env.evt_cfg = param->evt_cfg;
            }
            else
            {
                glps_env.evt_cfg = 0;
            }

            if((glps_env.evt_cfg & GLPS_MEAS_NTF_CFG) != 0)
            {
                indntf_cfg = PRF_CLI_START_NTF;
            }

            //Set Glucose measurement notification configuration
            attsdb_att_set_value(GLPS_HANDLE(GLS_IDX_MEAS_NTF_CFG), sizeof(uint16_t),
                                 (uint8_t *)&indntf_cfg);

            // Configure Intermediate Cuff Pressure NTF Cfg in DB

            //Configure Glucose measurement context notification
            if (GLPS_IS(MEAS_CTX_SUPPORTED))
            {
                indntf_cfg = PRF_CLI_STOP_NTFIND;

                if((glps_env.evt_cfg & GLPS_MEAS_CTX_NTF_CFG) != 0)
                {
                    indntf_cfg = PRF_CLI_START_NTF;
                }

                //Set Glucose measurement context notification configuration
                attsdb_att_set_value(GLPS_HANDLE(GLS_IDX_MEAS_CTX_NTF_CFG), sizeof(uint16_t),
                                     (uint8_t *)&indntf_cfg);
            }

            indntf_cfg = PRF_CLI_STOP_NTFIND;

            if((glps_env.evt_cfg & GLPS_RACP_IND_CFG) != 0)
            {
                indntf_cfg = PRF_CLI_START_IND;
            }

            //Set record access control point indication configuration
            attsdb_att_set_value(GLPS_HANDLE(GLS_IDX_REC_ACCESS_CTRL_IND_CFG), sizeof(uint16_t),
                                 (uint8_t *)&indntf_cfg);


            //Set Glucose sensor features
            attsdb_att_set_value(GLPS_HANDLE(GLS_IDX_FEATURE_VAL), sizeof(uint16_t),
                                 (uint8_t *)&param->features);

            // Enable Service + Set Security Level
            attsdb_svc_set_permission(glps_env.shdl, param->sec_lvl);

            // Go to connected state
            ke_state_set(TASK_GLPS, GLPS_CONNECTED);
        }
    }

    // send completed information to APP task that contains error status
    struct glps_enable_cfm * cmp_evt = KE_MSG_ALLOC(GLPS_ENABLE_CFM, src_id,
                                                    TASK_GLPS, glps_enable_cfm);

    cmp_evt->conhdl     = param->conhdl;
    cmp_evt->status     = status;

    ke_msg_send(cmp_evt);

    return (KE_MSG_CONSUMED);
}
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref SAMPLE128_CREATE_DB_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 sample128_create_db_req_handler(ke_msg_id_t const msgid,
                                       struct sample128_create_db_req const *param,
                                       ke_task_id_t const dest_id,
                                       ke_task_id_t const src_id)
{
    //Database Creation Status
    uint8_t status;
    uint8_t nb_att_16;
    uint8_t nb_att_128;
    uint8_t nb_att_32;
    uint16_t att_decl_svc = ATT_DECL_PRIMARY_SERVICE;
    uint16_t att_decl_char = ATT_DECL_CHARACTERISTIC;
    uint16_t att_decl_cfg = ATT_DESC_CLIENT_CHAR_CFG;
    uint16_t val_hdl;
    uint16_t char_hdl; 

    //Save Profile ID
    sample128_env.con_info.prf_id = TASK_SAMPLE128;

    /*---------------------------------------------------*
     * Link Loss Service Creation
     *---------------------------------------------------*/

        //Add Service Into Database
        nb_att_16 = 4; // 2 UUID16 atts
        nb_att_32 = 0;// No UUID32 att
        nb_att_128 = 2; //1 UUID128 att
        status = attmdb_add_service(&(sample128_env.sample128_shdl), TASK_SAMPLE128,
                                             nb_att_16, nb_att_32, nb_att_128, 58); //total attributte size = 36, 16 (svc)  + 19 (desc_char) + 1 (att)

        if (status == ATT_ERR_NO_ERROR)
        {
            //add svc attribute
            status = attmdb_add_attribute(sample128_env.sample128_shdl, ATT_UUID_128_LEN, //Data size = 16 (ATT_UUID_128_LEN)
                                               ATT_UUID_16_LEN, (uint8_t*)&att_decl_svc, PERM(RD, ENABLE),
                                               &(sample128_env.sample128_shdl));
            
            
            
            status = attmdb_att_set_value(sample128_env.sample128_shdl, ATT_UUID_128_LEN, (uint8_t *)sample128_svc.uuid);
            
            
//char 1     
            //add char attribute
            status = attmdb_add_attribute(sample128_env.sample128_shdl, ATT_UUID_128_LEN + 3, //Data size = 19 (ATT_UUID_128_LEN + 3)
                                               ATT_UUID_16_LEN, (uint8_t*) &att_decl_char, PERM(RD, ENABLE),
                                               &(char_hdl));
            
            
            
            //add val attribute
            status = attmdb_add_attribute(sample128_env.sample128_shdl, sizeof(uint8_t), //Data size = 1
                                               ATT_UUID_128_LEN, (uint8_t*)&sample128_1_val.uuid, PERM(RD, ENABLE) | PERM(WR, ENABLE),
                                               &(val_hdl));
            
            memcpy(sample128_1_char.attr_hdl, &val_hdl, sizeof(uint16_t));
            
            status = attmdb_att_set_value(char_hdl, sizeof(sample128_1_char), (uint8_t *)&sample128_1_char);
            

//////char 2
            //add char attribute
            status = attmdb_add_attribute(sample128_env.sample128_shdl, ATT_UUID_128_LEN + 3, //Data size = 19 (ATT_UUID_128_LEN + 3)
                                               ATT_UUID_16_LEN, (uint8_t*) &att_decl_char, PERM(RD, ENABLE),
                                               &(char_hdl));
                        
            //add val attribute
            status = attmdb_add_attribute(sample128_env.sample128_shdl, sizeof(uint8_t), //Data size = 1
                                               ATT_UUID_128_LEN, (uint8_t*)&sample128_2_val.uuid, PERM(RD, ENABLE) | PERM(NTF, ENABLE),
                                               &(val_hdl));
            
            memcpy(sample128_2_char.attr_hdl, &val_hdl, sizeof(uint16_t));
            
            status = attmdb_att_set_value(char_hdl, sizeof(sample128_2_char), (uint8_t *)&sample128_2_char);

            //add cfg attribute
            status = attmdb_add_attribute(sample128_env.sample128_shdl, sizeof(uint16_t), 
                                               ATT_UUID_16_LEN, (uint8_t*) &att_decl_cfg, PERM(RD, ENABLE) | PERM(WR, ENABLE),
                                               &(val_hdl));

            //Disable sample128 service
            attmdb_svc_set_permission(sample128_env.sample128_shdl, PERM(SVC, DISABLE));

            //Go to Idle State
    
            //If we are here, database has been fulfilled with success, go to idle state
            ke_state_set(TASK_SAMPLE128, SAMPLE128_IDLE);
        }
        
        //Send CFM to application
        struct sample128_create_db_cfm * cfm = KE_MSG_ALLOC(SAMPLE128_CREATE_DB_CFM, src_id,
                                                    TASK_SAMPLE128, sample128_create_db_cfm);
        cfm->status = status;
        ke_msg_send(cfm);
    

    return (KE_MSG_CONSUMED);
}
Exemple #24
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GATT_WRITE_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 gatt_write_cmd_ind_handler(ke_msg_id_t const msgid,
                                      struct gatt_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 (param->conhdl == glps_env.con_info.conhdl)
    {
        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
                attsdb_att_set_value(param->handle, sizeof(uint16_t), (uint8_t *)&cli_cfg);
                ind->conhdl = glps_env.con_info.conhdl;
                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* value;
            uint16_t length;
            struct glp_racp_req racp_req;

            // If a request is on going
            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 = glps_env.con_info.conhdl;
                    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)
                attsdb_att_update_value(param->handle, param->length, param->offset,
                        (uint8_t*)&(param->value[0]));

                // retrieve full data.
                attsdb_att_get_value(param->handle, &length, &value);

                // unpack record access control point value
                status = glps_unpack_racp_req(value, length, &racp_req);

                // check unpacked status
                switch(status)
                {
                    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:
                            {
                                if((glps_env.evt_cfg & GLPS_RACP_IND_CFG) != 0)
                                {
                                    //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 = glps_env.con_info.conhdl;
                                    req->racp_req = racp_req;
    
                                    ke_msg_send(req);
                                }
                                else
                                {
                                    status = PRF_CCCD_IMPR_CONFIGURED;
                                }
                            }
                            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 = status;

                        // 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(param->conhdl, param->handle, status);
    }

    return (KE_MSG_CONSUMED);
}
Exemple #25
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GLPS_MEAS_SEND_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 glps_meas_send_req_handler(ke_msg_id_t const msgid,
                                      struct glps_send_meas_with_ctx_req const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    uint8_t status = PRF_ERR_OK;

    if(param->conhdl == glps_env.con_info.conhdl)
    {
        // device already sending a measurement
        if(GLPS_IS(SENDING_MEAS))
        {
            //Cannot send another measurement in parallel
            status = (PRF_ERR_REQ_DISALLOWED);
        }
        else
        {
            // inform that device is sending a measurement
            GLPS_SET(SENDING_MEAS);


            // check if context is supported
            if((msgid == GLPS_SEND_MEAS_WITH_CTX_REQ) && !(GLPS_IS(MEAS_CTX_SUPPORTED)))
            {
                // Context not supported
                status = (PRF_ERR_FEATURE_NOT_SUPPORTED);
            }
            // check if notifications enabled
            else if(((glps_env.evt_cfg & GLPS_MEAS_NTF_CFG) == 0)
                    || (((glps_env.evt_cfg & GLPS_MEAS_CTX_NTF_CFG) == 0)
                        && (msgid == GLPS_SEND_MEAS_WITH_CTX_REQ)))
            {
                // Not allowed to send measurement if Notifications not enabled.
                status = (PRF_ERR_NTF_DISABLED);

            }
            else
            {
                struct atts_elmt * att_elmt;
                struct gatt_notify_req * ntf = KE_MSG_ALLOC(GATT_NOTIFY_REQ, TASK_GATT,
                        TASK_GLPS, gatt_notify_req);

                // retrieve value pointer in database
                att_elmt = attsdb_get_attribute(GLPS_HANDLE(GLS_IDX_MEAS_VAL));

                // pack measured value in database
                att_elmt->length = glps_pack_meas_value(att_elmt->value, &(param->meas),
                                                        param->seq_num);

                //Send notification through GATT
                ntf->conhdl  = glps_env.con_info.conhdl;
                ntf->charhdl = GLPS_HANDLE(GLS_IDX_MEAS_VAL);

                ke_msg_send(ntf);

                if(msgid == GLPS_SEND_MEAS_WITH_CTX_REQ)
                {
                    // 2 notification complete messages expected
                    GLPS_SET(MEAS_CTX_SENT);

                    // retrieve value pointer in database
                    att_elmt = attsdb_get_attribute(GLPS_HANDLE(GLS_IDX_MEAS_CTX_VAL));

                    // pack measured value in database
                    att_elmt->length = glps_pack_meas_ctx_value(att_elmt->value,
                                                            &(param->ctx), param->seq_num);

                    ntf = KE_MSG_ALLOC(GATT_NOTIFY_REQ, TASK_GATT,
                            TASK_GLPS, gatt_notify_req);

                    //Send notification through GATT
                    ntf->conhdl  = glps_env.con_info.conhdl;
                    ntf->charhdl = GLPS_HANDLE(GLS_IDX_MEAS_CTX_VAL);

                    ke_msg_send(ntf);
                }
                else
                {
                    // 1 notification complete messages expected
                    GLPS_CLEAR(MEAS_CTX_SENT);
                }
            }
        }
    }
    else
    {
        //Wrong Connection Handle
        status = (PRF_ERR_INVALID_PARAM);
    }

    // send command complete if an error occurs
    if(status != PRF_ERR_OK)
    {
        // allow to send other measurements
        GLPS_CLEAR(SENDING_MEAS);

        // send completed information to APP task that contains error status
        struct glps_req_cmp_evt * cmp_evt = KE_MSG_ALLOC(GLPS_REQ_CMP_EVT, glps_env.con_info.appid,
                TASK_GLPS, glps_req_cmp_evt);

        cmp_evt->conhdl     = param->conhdl;
        cmp_evt->request    = GLPS_SEND_MEAS_REQ_NTF_CMP;
        cmp_evt->status     = status;

        ke_msg_send(cmp_evt);
    }

    return (KE_MSG_CONSUMED);
}
Exemple #26
0
/**
 ****************************************************************************************
 * @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);
    uint8_t status;
    // Get the address of the environment
    struct tipc_env_tag *tipc_env = PRF_CLIENT_GET_ENV(dest_id, tipc);
    if(state == TIPC_DISCOVERING)
    {
        if ((param->status == ATT_ERR_ATTRIBUTE_NOT_FOUND)||
                (param->status == ATT_ERR_NO_ERROR))
        {
            // Currently Discovering Current Time service characteristics.
            if(tipc_env->last_svc_req  == ATT_SVC_CURRENT_TIME)
            {
                // service start/end handles has been received
                if(tipc_env->last_uuid_req == ATT_SVC_CURRENT_TIME)
                {
                    // check if service handles are not ok
                    if (tipc_env->cts.svc.shdl == ATT_INVALID_HANDLE)
                    {
                        // stop discovery procedure.
                        tipc_enable_cfm_send(tipc_env, &tipc_env->con_info, PRF_ERR_STOP_DISC_CHAR_MISSING);
                    }
                    //too many services found only one such service should exist
                    else if(tipc_env->nb_svc != 1)
                    {
                        // stop discovery procedure.
                        tipc_enable_cfm_send(tipc_env, &tipc_env->con_info, PRF_ERR_MULTIPLE_SVC);
                    }
                    // check if service handles are ok
                    else
                    {
                        //discover all CTS characteristics
                        prf_disc_char_all_send(&(tipc_env->con_info), &(tipc_env->cts.svc));
                        tipc_env->last_uuid_req = ATT_DECL_CHARACTERISTIC;
                    }

                }
                else if(tipc_env->last_uuid_req == ATT_DECL_CHARACTERISTIC)
                {
                    status = prf_check_svc_char_validity(TIPC_CHAR_CTS_MAX, tipc_env->cts.chars,
                            tipc_cts_char);

                    //  check for characteristic properties.
                    if(status == PRF_ERR_OK)
                    {
                        tipc_env->last_uuid_req = ATT_INVALID_HANDLE;
                        tipc_env->last_char_code = TIPC_CHAR_CTS_CURR_TIME;
                        //request all service characteristic description for CTS
                        prf_disc_char_desc_send(&(tipc_env->con_info), &(tipc_env->cts.chars[TIPC_CHAR_CTS_CURR_TIME]));
                    }
                    else
                    {
                        // stop discovery procedure.
                        tipc_enable_cfm_send(tipc_env, &tipc_env->con_info, status);
                    }
                }
                else
                {
                    status = prf_check_svc_char_desc_validity(TIPC_DESC_CTS_MAX,
                            tipc_env->cts.descs,
                            tipc_cts_char_desc,
                            tipc_env->cts.chars);

                    if(status == PRF_ERR_OK)
                    {
                        // reset number of services
                        tipc_env->nb_svc = 0;

                        //start discovering NDCS on peer
                        prf_disc_svc_send(&(tipc_env->con_info), ATT_SVC_NEXT_DST_CHANGE);

                        tipc_env->last_uuid_req = ATT_SVC_NEXT_DST_CHANGE;
                        tipc_env->last_svc_req  = ATT_SVC_NEXT_DST_CHANGE;
                    }
                    else
                    {
                        // stop discovery procedure.
                        tipc_enable_cfm_send(tipc_env, &tipc_env->con_info, status);
                    }
                }
            }

            // Currently Next DST Change service characteristics.
            else if(tipc_env->last_svc_req  == ATT_SVC_NEXT_DST_CHANGE)
            {
                // service start/end handles has been received
                if(tipc_env->last_uuid_req == ATT_SVC_NEXT_DST_CHANGE)
                {
                    if (tipc_env->ndcs.svc.shdl == ATT_INVALID_HANDLE)
                    {
                        // reset number of services
                        tipc_env->nb_svc = 0;

                        //start discovering RTUS on peer
                        prf_disc_svc_send(&(tipc_env->con_info), ATT_SVC_REF_TIME_UPDATE);

                        tipc_env->last_uuid_req = ATT_SVC_REF_TIME_UPDATE;
                        tipc_env->last_svc_req  = ATT_SVC_REF_TIME_UPDATE;
                    }
                    //too many services found only one such service should exist
                    else if(tipc_env->nb_svc != 1)
                    {
                        // stop discovery procedure.
                        tipc_enable_cfm_send(tipc_env, &tipc_env->con_info, PRF_ERR_MULTIPLE_SVC);
                    }
                    // check if service handles are ok
                    else
                    {
                        //discover all NDCS characteristics
                        prf_disc_char_all_send(&(tipc_env->con_info), &(tipc_env->ndcs.svc));
                        tipc_env->last_uuid_req = ATT_DECL_CHARACTERISTIC;
                    }
                }
                else if(tipc_env->last_uuid_req == ATT_DECL_CHARACTERISTIC)
                {
                    status = prf_check_svc_char_validity(TIPC_CHAR_NDCS_MAX, tipc_env->ndcs.chars,
                            tipc_ndcs_char);

                    //  check for characteristic properties.
                    if(status == PRF_ERR_OK)
                    {
                        // reset number of services
                        tipc_env->nb_svc = 0;

                        //start discovering RTUS on peer
                        prf_disc_svc_send(&(tipc_env->con_info), ATT_SVC_REF_TIME_UPDATE);

                        tipc_env->last_uuid_req = ATT_SVC_REF_TIME_UPDATE;
                        tipc_env->last_svc_req  = ATT_SVC_REF_TIME_UPDATE;
                    }
                    else
                    {
                        // stop discovery procedure.
                        tipc_enable_cfm_send(tipc_env, &tipc_env->con_info, status);
                    }
                }
            }

            // Currently Reference Time Update service characteristics.
            else if(tipc_env->last_svc_req  == ATT_SVC_REF_TIME_UPDATE)
            {
                // service start/end handles has been received
                if(tipc_env->last_uuid_req == ATT_SVC_REF_TIME_UPDATE)
                {
                    if (tipc_env->rtus.svc.shdl == ATT_INVALID_HANDLE)
                    {
                        // send app the details about the discovered TIPS DB to save
                        tipc_enable_cfm_send(tipc_env, &tipc_env->con_info, PRF_ERR_OK);
                    }
                    //too many services found only one such service should exist
                    else if(tipc_env->nb_svc != 1)
                    {
                        // stop discovery procedure.
                        tipc_enable_cfm_send(tipc_env, &tipc_env->con_info, PRF_ERR_MULTIPLE_SVC);
                    }
                    // check if service handles are ok
                    else
                    {
                        //discover all RTUS characteristics
                        prf_disc_char_all_send(&(tipc_env->con_info), &(tipc_env->rtus.svc));
                        tipc_env->last_uuid_req = ATT_DECL_CHARACTERISTIC;
                    }
                }
                else if(tipc_env->last_uuid_req == ATT_DECL_CHARACTERISTIC)
                {
                    status = prf_check_svc_char_validity(TIPC_CHAR_RTUS_MAX, tipc_env->rtus.chars,
                            tipc_rtus_char);

                    //  check for characteristic properties.
                    if(status == PRF_ERR_OK)
                    {
                        // send app the details about the discovered TIPS DB to save
                        tipc_enable_cfm_send(tipc_env, &tipc_env->con_info, PRF_ERR_OK);
                    }
                    else
                    {
                        // stop discovery procedure.
                        tipc_enable_cfm_send(tipc_env, &tipc_env->con_info, status);
                    }
                }
            }
        }
    }
    else if(state == TIPC_CONNECTED)
    {
        switch(param->req_type)
        {
            case GATTC_WRITE:
            case GATTC_WRITE_NO_RESPONSE:
            {
                struct tipc_wr_char_rsp *wr_cfm = KE_MSG_ALLOC(TIPC_WR_CHAR_RSP,
                        tipc_env->con_info.appid, dest_id, tipc_wr_char_rsp);

                wr_cfm->conhdl    = gapc_get_conhdl(tipc_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:
            {
                // an error occurs while reading peer attribute, inform app
                if(param->status != GATT_ERR_NO_ERROR)
                {
                    tipc_error_ind_send(tipc_env, param->status);
                }
            }
            break;
            default: break;
        }
    }
    return (KE_MSG_CONSUMED);
}
Exemple #27
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref BEACON_CREATE_DB_REQ message.
 * The handler adds BAS into the database using value of the features param.
 * @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 beacon_create_db_req_handler(ke_msg_id_t const msgid,
                                      struct beacon_create_db_req const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    // Service content flag
    uint8_t cfg_flag = BEACON_CFG_FLAG_MANDATORY_MASK;
    // Status
    uint8_t status = PRF_ERR_OK;
//     // Counter
//     uint8_t i;
//     // Battery Level characteristic value permissions
//     uint16_t perm;
//     // Battery Level characteristic value properties
//     uint8_t prop;

    // Save profile id
    beacon_env.con_info.prf_id = TASK_BEACON;
    //beacon_env.features        = param->features;
    status = atts_svc_create_db(&beacon_env.shdl, (uint8_t *)&cfg_flag, BEACON_IDX_NB, NULL,dest_id, &beacon_att_db[0]);

    //Disable service
    status = attsdb_svc_set_permission(beacon_env.shdl, PERM(SVC, DISABLE));

    
    //Go to Idle State
    if (status == ATT_ERR_NO_ERROR)
    {
        //If we are here, database has been fulfilled with success, go to idle test
        ke_state_set(TASK_BEACON, BEACON_IDLE);
    }
    
    //Send response to application
    struct beacon_create_db_cfm * cfm = KE_MSG_ALLOC(BEACON_CREATE_DB_CFM, beacon_env.con_info.appid,
                                                   TASK_BEACON, beacon_create_db_cfm);
    cfm->status = status;
    ke_msg_send(cfm);
    
//     // Check number of BAS instances
//     if (param->bas_nb <= BASS_NB_BAS_INSTANCES_MAX)
//     {
//         // Save number of BAS
//         bass_env.bas_nb = param->bas_nb;

//         for (i = 0; ((i < param->bas_nb) && (status == PRF_ERR_OK)); i++)
//         {
//             // Save database configuration
//             bass_env.features[i] = param->features[i];

//             // Check if notifications are supported
//             if (bass_env.features[i] == BAS_BATT_LVL_NTF_SUP)
//             {
//                 cfg_flag |= BAS_CFG_FLAG_NTF_SUP_MASK;
//             }

//             // Check if multiple instances
//             if (bass_env.bas_nb > 1)
//             {
//                 cfg_flag |= BAS_CFG_FLAG_MTP_BAS_MASK;
//             }

//             //Create BAS in the DB
//             status = atts_svc_create_db(&bass_env.shdl[i], (uint8_t *)&cfg_flag, BAS_IDX_NB, NULL,
//                                         dest_id, &bas_att_db[0]);

//             //Disable the service and set optional features
//             if (status == PRF_ERR_OK)
//             {
//                 //Disable service
//                 status = attsdb_svc_set_permission(bass_env.shdl[i], PERM(SVC, DISABLE));

//                 //Set optional properties and permissions
//                 if (bass_env.features[i] == BAS_BATT_LVL_NTF_SUP)
//                 {
//                     prop = ATT_CHAR_PROP_RD | ATT_CHAR_PROP_NTF;
//                     perm = PERM(RD, ENABLE) | PERM(NTF, ENABLE);

//                     attsdb_att_partial_value_update(bass_env.shdl[i] + BAS_IDX_BATT_LVL_CHAR, 0, 1, &prop);
//                     attsdb_att_set_permission(bass_env.shdl[i] + BAS_IDX_BATT_LVL_VAL, perm);
//                 }
//             }

//             // Reset configuration flag
//             cfg_flag = BAS_CFG_FLAG_MANDATORY_MASK;
//         }

//         if (status == PRF_ERR_OK)
//         {
//             //If we are here, database has been fulfilled with success, go to idle state
//             ke_state_set(TASK_BASS, BASS_IDLE);
//         }
//     }
//     else
//     {
//         status = PRF_ERR_INVALID_PARAM;
//     }

//     // Send confirmation to application
//     struct bass_create_db_cfm * cfm = KE_MSG_ALLOC(BASS_CREATE_DB_CFM, src_id, TASK_BASS,
//                                                    bass_create_db_cfm);
//     cfm->status = status;
//     ke_msg_send(cfm);

     return (KE_MSG_CONSUMED);
}
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GATT_HANDLE_VALUE_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 gatt_handle_value_ind_handler(ke_msg_id_t const msgid,
                                         struct gatt_handle_value_ind 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)
    {
        // Check if we were waiting for the indication
        if (cscpc_env->operation != NULL)
        {
            if (((struct cscpc_cmd *)cscpc_env->operation)->operation == CSCPC_CTNL_PT_CFG_IND_OP_CODE)
            {
                // Stop the procedure timeout timer
                ke_timer_clear(CSCPC_TIMEOUT_TIMER_IND, dest_id);

                // CSC Measurement value has been received
                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);

                // Connection Handle
                ind->conhdl   = param->conhdl;
                // Attribute code
                ind->att_code = CSCPC_IND_SC_CTNL_PT;

                // Requested operation code
                ind->value.ctnl_pt_rsp.req_op_code = param->value[1];
                // Response value
                ind->value.ctnl_pt_rsp.resp_value  = param->value[2];

                // Get the list of supported sensor locations if needed
                if ((ind->value.ctnl_pt_rsp.req_op_code == CSCP_CTNL_PT_OP_REQ_SUPP_LOC) &&
                    (ind->value.ctnl_pt_rsp.resp_value == CSCP_CTNL_PT_RESP_SUCCESS) &&
                    (param->size > 3))
                {
                    // Get the number of supported locations that have been received
                    uint8_t nb_supp_loc = (param->size - 3);
                    // Counter
                    uint8_t counter;
                    // Location
                    uint8_t loc;

                    for (counter = 0; counter < nb_supp_loc; counter++)
                    {
                        loc = param->value[counter + 3];

                        // Check if valid
                        if (loc < CSCP_LOC_MAX)
                        {
                            ind->value.ctnl_pt_rsp.supp_loc |= (1 << loc);
                        }
                    }
                }

                // Send the message
                ke_msg_send(ind);

                // Send the complete event message
                cscpc_send_cmp_evt(cscpc_env, CSCPC_CTNL_PT_CFG_WR_OP_CODE, PRF_ERR_OK);
            }
            // else drop the message
        }
        // else drop the message
    }
    // else ignore the message

    return (KE_MSG_CONSUMED);
}
Exemple #29
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GATTC_READ_IND message.
 * Generic event received after every simple read command sent to peer server.
 * @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_read_ind_handler(ke_msg_id_t const msgid,
                                    struct gattc_read_ind const *param,
                                    ke_task_id_t const dest_id,
                                    ke_task_id_t const src_id)
{
    // Get the address of the environment
    struct tipc_env_tag *tipc_env = PRF_CLIENT_GET_ENV(dest_id, tipc);

    //Current Time Characteristic
    if (tipc_env->last_char_code == TIPC_RD_CTS_CURR_TIME)
    {
        //Build a TIPC_CT_IND message
        struct tipc_ct_ind * ind = KE_MSG_ALLOC(TIPC_CT_IND,
                                                tipc_env->con_info.appid, dest_id,
                                                tipc_ct_ind);

        // retrieve connection handle
        ind->conhdl = gapc_get_conhdl(tipc_env->con_info.conidx);
        // Unpack Current Time Value.
        tipc_unpack_curr_time_value(&(ind->ct_val), (uint8_t*) &(param->value[0]));
        //Indication Type
        ind->ind_type = TIP_RD_RSP,

        ke_msg_send(ind);
    }
    //Local Time Information Characteristic
    else if (tipc_env->last_char_code == TIPC_RD_CTS_LOCAL_TIME_INFO)
    {
        //Build a TIPC_LTI_RD_RSP message
        struct tipc_lti_rd_rsp * rsp = KE_MSG_ALLOC(TIPC_LTI_RD_RSP,
                                                    tipc_env->con_info.appid, dest_id,
                                                    tipc_lti_rd_rsp);

        // Retrieve Connection handle
        rsp->conhdl = gapc_get_conhdl(tipc_env->con_info.conidx);
        // Local Time Information Value
        rsp->lti_val.time_zone         = param->value[0];
        rsp->lti_val.dst_offset         = param->value[1];

        ke_msg_send(rsp);
    }
    //Reference Time Information Characteristic
    else if (tipc_env->last_char_code == TIPC_RD_CTS_REF_TIME_INFO)
    {
        //Build a TIPC_RTI_RD_RSP message
        struct tipc_rti_rd_rsp * rsp = KE_MSG_ALLOC(TIPC_RTI_RD_RSP,
                                                    tipc_env->con_info.appid, dest_id,
                                                    tipc_rti_rd_rsp);

        // Retrieve Connection handle
        rsp->conhdl = gapc_get_conhdl(tipc_env->con_info.conidx);
        // Reference Time Information Value
        rsp->rti_val.time_source      = param->value[0];
        rsp->rti_val.time_accuracy    = param->value[1];
        rsp->rti_val.days_update      = param->value[2];
        rsp->rti_val.hours_update     = param->value[3];

        ke_msg_send(rsp);
    }
    //Time with DST Characteristic
    else if (tipc_env->last_char_code == TIPC_RD_NDCS_TIME_WITH_DST)
    {
        //Build a TIPC_TDST_RD_RSP message
        struct tipc_tdst_rd_rsp * rsp = KE_MSG_ALLOC(TIPC_TDST_RD_RSP,
                                                     tipc_env->con_info.appid, dest_id,
                                                     tipc_tdst_rd_rsp);

        // Retrieve Connection handle
        rsp->conhdl = gapc_get_conhdl(tipc_env->con_info.conidx);
        // Time with DST Value
        prf_unpack_date_time((uint8_t*) &(param->value[0]), &(rsp->tdst_val.date_time));
        rsp->tdst_val.dst_offset        = param->value[7];

        ke_msg_send(rsp);
    }
    //Time Update State Characteristic
    else if (tipc_env->last_char_code == TIPC_RD_RTUS_TIME_UPD_STATE)
    {
        //Build a TIPC_TUS_RD_RSP message
        struct tipc_tus_rd_rsp * rsp = KE_MSG_ALLOC(TIPC_TUS_RD_RSP,
                                                    tipc_env->con_info.appid, dest_id,
                                                    tipc_tus_rd_rsp);

        // Retrieve Connection handle
        rsp->conhdl = gapc_get_conhdl(tipc_env->con_info.conidx);
        // Reference Time Information Value
        rsp->tus_val.current_state     = param->value[0];
        rsp->tus_val.result            = param->value[1];

        ke_msg_send(rsp);
    }
    //Current Time Characteristic - Client Characteristic Configuration Descriptor
    else if (tipc_env->last_char_code == TIPC_RD_CTS_CURR_TIME_CLI_CFG)
    {
        //Build a TIPC_CT_NTF_CFG_RD_RSP message
        struct tipc_ct_ntf_cfg_rd_rsp * rsp = KE_MSG_ALLOC(TIPC_CT_NTF_CFG_RD_RSP,
                                                           tipc_env->con_info.appid, dest_id,
                                                           tipc_ct_ntf_cfg_rd_rsp);

        // Retrieve Connection handle
        rsp->conhdl = gapc_get_conhdl(tipc_env->con_info.conidx);
        // Notification Configuration
        memcpy(&rsp->ntf_cfg, &param->value[0], sizeof(rsp->ntf_cfg));

        ke_msg_send(rsp);
    }

    return (KE_MSG_CONSUMED);
}
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GATT_CMP_EVT 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_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 cscpc_env_tag *cscpc_env = PRF_CLIENT_GET_ENV(dest_id, cscpc);

    if (cscpc_env != NULL)
    {
        // Status
        uint8_t status = PRF_ERR_STOP_DISC_CHAR_MISSING;

        ASSERT_ERR(cscpc_env->operation != NULL);
        ASSERT_ERR(((struct cscpc_cmd *)cscpc_env->operation)->operation == CSCPC_ENABLE_OP_CODE);

        if ((param->status == ATT_ERR_ATTRIBUTE_NOT_FOUND) ||
            (param->status == ATT_ERR_NO_ERROR))
        {
            /* -------------------------------------------------
             * SERVICE DISCOVERY -------------------------------
             * ------------------------------------------------- */
            if (cscpc_env->last_req == ATT_SVC_CYCLING_SPEED_CADENCE)
            {
                if (cscpc_env->nb_svc > 0)
                {
                    // Check if service handles are OK
                    if ((cscpc_env->cscs.svc.shdl != ATT_INVALID_HANDLE) &&
                        (cscpc_env->cscs.svc.ehdl != ATT_INVALID_HANDLE) &&
                        (cscpc_env->cscs.svc.shdl < cscpc_env->cscs.svc.ehdl))
                    {
                        // Status is OK
                        status = PRF_ERR_OK;

                        // Discover all CSCS characteristics
                        cscpc_env->last_req = ATT_DECL_CHARACTERISTIC;
                        prf_disc_char_all_send(&(cscpc_env->con_info), &(cscpc_env->cscs.svc));
                    }
                    // Handles are not corrects, the Cycling Speed and Cadence Service has not been found, stop
                }
                // The Cycling Speed and Cadence Service has not been found, stop discovery
            }

            /* -------------------------------------------------
             * CHARACTERISTICS DISCOVERY -----------------------
             * ------------------------------------------------- */
            else if (cscpc_env->last_req == ATT_DECL_CHARACTERISTIC)
            {
                // Check if mandatory properties have been found and if properties are correct
                status = prf_check_svc_char_validity(CSCP_CSCS_CHAR_MAX, cscpc_env->cscs.chars, cscpc_cscs_char);

                // Check for characteristic properties.
                if (status == PRF_ERR_OK)
                {
                    cscpc_env->last_req = CSCP_CSCS_CSC_MEAS_CHAR;

                    // Find the Client Characteristic Configuration Descriptor for the CSC Measurement characteristic
                    prf_disc_char_desc_send(&(cscpc_env->con_info),
                                            &(cscpc_env->cscs.chars[CSCP_CSCS_CSC_MEAS_CHAR]));
                }
            }

            /* -------------------------------------------------
             * DESCRIPTORS DISCOVERY ---------------------------
             * ------------------------------------------------- */
            else
            {
                // Discovery over ?
                bool disc_over = true;

                if (cscpc_env->last_req == CSCP_CSCS_CSC_MEAS_CHAR)
                {
                    // Check if the SC Control Point Characteristic has been found
                    if (cscpc_env->cscs.chars[CSCP_CSCS_SC_CTNL_PT_CHAR].char_hdl != ATT_INVALID_SEARCH_HANDLE)
                    {
                        // Status is OK
                        status = PRF_ERR_OK;

                        // Find the Client Characteristic Configuration Descriptor for the SC Control Point characteristic
                        cscpc_env->last_req = CSCP_CSCS_SC_CTNL_PT_CHAR;
                        prf_disc_char_desc_send(&(cscpc_env->con_info),
                                                &(cscpc_env->cscs.chars[CSCP_CSCS_SC_CTNL_PT_CHAR]));

                        // Discovery continues
                        disc_over = false;
                    }
                }
                else
                {
                    // Discovery is over
                    ASSERT_ERR(cscpc_env->last_req == CSCP_CSCS_SC_CTNL_PT_CHAR);
                }

                if (disc_over)
                {
                    status = prf_check_svc_char_desc_validity(CSCPC_DESC_MAX,
                                                              cscpc_env->cscs.descs,
                                                              cscpc_cscs_char_desc,
                                                              cscpc_env->cscs.chars);

                    if (status == PRF_ERR_OK)
                    {
                        // Reset number of services
                        cscpc_env->nb_svc = 0;

                        // Register in GATT for notifications/indications
                        prf_register_atthdl2gatt(&cscpc_env->con_info, &cscpc_env->cscs.svc);

                        // Send the content of the service to the HL
                        struct cscpc_cscs_content_ind *ind = KE_MSG_ALLOC(CSCPC_CSCS_CONTENT_IND,
                                                                          cscpc_env->con_info.appid,
                                                                          cscpc_env->con_info.prf_id,
                                                                          cscpc_cscs_content_ind);

                        ind->conhdl = cscpc_env->con_info.conhdl;
                        memcpy(&ind->cscs, &cscpc_env->cscs, sizeof(struct cscpc_cscs_content));

                        // Send the message
                        ke_msg_send(ind);

                        // Stop discovery procedure.
                        cscpc_send_cmp_evt(cscpc_env, CSCPC_ENABLE_OP_CODE, status);
                    }
                }
            }
        }
        else
        {
            status = param->status;
        }

        if (status != PRF_ERR_OK)
        {
            // Stop discovery procedure.
            cscpc_send_cmp_evt(cscpc_env, CSCPC_ENABLE_OP_CODE, status);
        }
    }
    // else ignore the message

    return (KE_MSG_CONSUMED);
}