Exemplo n.º 1
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref QPPS_ENABLE_REQ message.
 * The handler enables the Quintic private Profile.
 * @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 qpps_enable_req_handler(ke_msg_id_t const msgid,
                                   struct qpps_enable_req const *param,
                                   ke_task_id_t const dest_id,
                                   ke_task_id_t const src_id)
{
    uint16_t value = 0;

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

    // If this connection is a not configuration one, apply config saved by app
    if(param->con_type == PRF_CON_NORMAL)
    {
		qpps_env.features = param->ntf_en;
		for (uint8_t i = 0; i < qpps_env.ntf_char_num; i++)
		{
			//Set Val NTF Configuration in DB
  			if (QPPS_IS_SUPPORTED(i, QPPS_VALUE_NTF_CFG))
			{
		        value = QPPS_VALUE_NTF_CFG;
				attsdb_att_set_value(qpps_env.shdl + QPPS_IDX_VAL_NTF_CFG + i*3, sizeof(uint16_t),
									(uint8_t *)&value);
		    }
            else
            {
                value = 0;
				attsdb_att_set_value(qpps_env.shdl + QPPS_IDX_VAL_NTF_CFG + i*3, sizeof(uint16_t),
									(uint8_t *)&value);
            }
		}
    }
	else
	{
		for (uint8_t i = 0; i < qpps_env.ntf_char_num; i++)
		{
			//Set Val NTF Configuration in DB
			attsdb_att_set_value(qpps_env.shdl + QPPS_IDX_VAL_NTF_CFG + i*3, sizeof(uint16_t),
								 (uint8_t *)&value);
		}
	}

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

    // Go to connected state
    ke_state_set(TASK_QPPS, QPPS_CONNECTED);

    return (KE_MSG_CONSUMED);
}
Exemplo n.º 2
0
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 char_code = PROXR_ERR_CHAR;
    uint8_t status = PRF_APP_ERROR;
    
    if (param->conhdl == beacon_env.con_info.conhdl)
    {
        if (param->handle == beacon_env.shdl + BEACON_IDX_LVL_VAL)
        {

            //Save value in DB
            attsdb_att_set_value(param->handle, sizeof(uint8_t), (uint8_t *)&param->value[0]);
                
#if QN_NVDS_WRITE
            if (NVDS_OK == nvds_put(NVDS_TAG_MEASURED_POWER, sizeof(param->value[0]), (uint8_t *)&param->value[0]))
            {
                status = PRF_ERR_OK;
            }
#else
            status = PRF_ERR_OK;
#endif
            //Response
            atts_write_rsp_send(beacon_env.con_info.conhdl, param->handle, status);
        }
    }

    return (KE_MSG_CONSUMED);
}
Exemplo n.º 3
0
void cscps_send_rsp_ind(uint16_t handle, uint8_t req_op_code, uint8_t status)
{
    // Error response
    uint8_t rsp[CSCP_SC_CNTL_PT_RSP_MIN_LEN];

    // Response Code
    rsp[0] = CSCP_CTNL_PT_RSP_CODE;
    // Request Operation Code
    rsp[1] = req_op_code;
    // Response value
    rsp[2] = status;

    // Set the value in the database - If we are here the handle is valid
    attsdb_att_set_value(handle, 3, (uint8_t *)&rsp);

    // Send an indication
    struct gatt_indicate_req *ind = KE_MSG_ALLOC(GATT_INDICATE_REQ,
                                                 TASK_GATT, cscps_env.con_info.prf_id,
                                                 gatt_indicate_req);

    ind->conhdl  = cscps_env.con_info.conhdl;
    ind->charhdl = handle;

    ke_msg_send(ind);
}
Exemplo n.º 4
0
uint8_t hogpd_ntf_cfg_ind_send(uint16_t ntf_cfg, uint16_t handle, uint8_t cfg_code,
                               uint8_t hids_nb, uint8_t report_nb)
{
    // Status
    uint8_t status = PRF_APP_ERROR;
    // Mask
    uint8_t mask = 0x00;
    // Pointer to the flag saving the notification configuration
    uint8_t *flag = &hogpd_env.features[hids_nb].svc_features;

    // Check if provided value is correct
    if ((ntf_cfg == PRF_CLI_STOP_NTFIND) || (ntf_cfg == PRF_CLI_START_NTF))
    {
        // Set value in the database
        attsdb_att_set_value(handle, sizeof(uint16_t), (uint8_t *)&ntf_cfg);

        if (cfg_code == HOGPD_BOOT_KB_IN_REPORT_CFG)
        {
            mask = HOGPD_BOOT_KB_IN_NTF_CFG_MASK;
        }
        else if (cfg_code == HOGPD_BOOT_MOUSE_IN_REPORT_CFG)
        {
            mask = HOGPD_BOOT_MOUSE_IN_NTF_CFG_MASK;
        }
        else if (cfg_code == HOGPD_REPORT_CFG)
        {
            mask = HOGPD_REPORT_NTF_CFG_MASK;
            flag = &hogpd_env.features[hids_nb].report_char_cfg[report_nb];
        }

        // Save new status in the environment
        if (ntf_cfg == PRF_CLI_START_NTF)
        {
            *flag |= mask;
        }
        else
        {
            *flag &= ~mask;
        }

        // Inform APP of configuration change
        struct hogpd_ntf_cfg_ind * ind = KE_MSG_ALLOC(HOGPD_NTF_CFG_IND,
                                                      hogpd_env.con_info.appid, TASK_HOGPD,
                                                      hogpd_ntf_cfg_ind);

        co_write16p(&ind->conhdl, hogpd_env.con_info.conhdl);
        co_write16p(&ind->ntf_en, ntf_cfg);
        ind->hids_nb   = hids_nb;
        ind->report_nb = report_nb;
        ind->cfg_code  = cfg_code;

        ke_msg_send(ind);

        status = PRF_ERR_OK;
    }

    return status;
}
Exemplo n.º 5
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref QPPS_DATA_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 qpps_data_send_req_handler(ke_msg_id_t const msgid,
                                      struct qpps_data_send_req const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
	 if((param->conhdl == qpps_env.conhdl) &&
			(param->length <= QPP_DATA_MAX_LEN) &&
			(param->index <= qpps_env.ntf_char_num))
    {
        // Check if notifications are enabled
        if(QPPS_IS_SUPPORTED(param->index, QPPS_VALUE_NTF_CFG))
        {
            //Update value in DB
            attsdb_att_set_value(qpps_env.shdl + QPPS_IDX_VAL + param->index * 3,
                                 param->length, (void *)param->data);

            //send notification through GATT
            struct gatt_notify_req * ntf = KE_MSG_ALLOC(GATT_NOTIFY_REQ, TASK_GATT,
                                                        TASK_QPPS, gatt_notify_req);
            ntf->conhdl  = qpps_env.conhdl;
            ntf->charhdl = qpps_env.shdl + QPPS_IDX_VAL + param->index * 3;

            ke_msg_send(ntf);
        }
        //notification not enabled, simply don't send anything
        else
        {
            // Send CFM to APP that value was not sent not
            struct qpps_data_send_cfm * cfm = KE_MSG_ALLOC(QPPS_DATA_SEND_CFM, qpps_env.appid,
                    TASK_QPPS, qpps_data_send_cfm);

            cfm->conhdl = qpps_env.conhdl;
            cfm->status = PRF_ERR_NTF_DISABLED;;

            ke_msg_send(cfm);
        }
    }
    else
    {
        // Derek, Send Confirm here, not Error
        // Wrong Connection Handle
        qpps_error_ind_send(PRF_ERR_INVALID_PARAM);
    }
    return (KE_MSG_CONSUMED);
}
Exemplo n.º 6
0
void hogpd_init_ntf_cfg(uint16_t ntf_cfg, uint16_t handle, uint8_t con_type,
                        uint8_t *flag, uint8_t mask)
{
    // Default Ntf Cfg value
    uint16_t value = PRF_CLI_STOP_NTFIND;

    //Written value is 0 is discovery connection, given value if normal
    if(con_type == PRF_CON_NORMAL)
    {
        memcpy(&value, &ntf_cfg, sizeof(uint16_t));

        // Save new status in the environment
        if (value == PRF_CLI_START_NTF)
        {
            *flag |= HOGPD_REPORT_NTF_CFG_MASK;
        }
    }

    attsdb_att_set_value(handle, sizeof(uint16_t), (uint8_t *)&value);
}
Exemplo n.º 7
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref BAPS_ENABLE_REQ message.
 * The handler enables the Battery 'Profile' Server 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 beacon_enable_req_handler(ke_msg_id_t const msgid,
                                   struct beacon_enable_req const *param,
                                   ke_task_id_t const dest_id,
                                   ke_task_id_t const src_id)
{
    // Save the application task id
    beacon_env.con_info.appid = src_id;
    // Save the connection handle associated to the profile
    beacon_env.conhdl = param->conhdl;
    
    // Check if the provided connection exist
    if (gap_get_rec_idx(param->conhdl) == GAP_INVALID_CONIDX)
    {
        // ??????????????????
        // The connection doesn't exist, request disallowed
        prf_server_error_ind_send((prf_env_struct *)&beacon_env, PRF_ERR_REQ_DISALLOWED,
                                  BEACON_ERROR_IND, BEACON_ENABLE_REQ);
    }
    else
    {
        attsdb_att_set_value(beacon_env.shdl + BEACON_IDX_LVL_VAL, sizeof(uint8_t),
                                  (uint8_t *)&param->measured_power_val);
        attsdb_svc_set_permission(beacon_env.shdl, param->sec_lvl);
    
        // Go to connected state
        ke_state_set(TASK_BEACON, BEACON_CONNECTED);
    }
    
    
    
//     // Attribute offset - Used to retrieve Char. Pres. Format Descriptor handle
//     uint8_t offset;
//     // Packed Char. Presentation Format value
//     uint8_t packed_char_pres[PRF_CHAR_PRES_FMT_SIZE];
//     // Counter
//     uint8_t i;
//     // Notification Configuration
//     uint16_t ntf_cfg = 0;

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

//     // Check if the provided connection exist
//     if (gap_get_rec_idx(param->conhdl) == GAP_INVALID_CONIDX)
//     {
//         // The connection doesn't exist, request disallowed
//         prf_server_error_ind_send((prf_env_struct *)&bass_env, PRF_ERR_REQ_DISALLOWED,
//                                   BASS_ERROR_IND, BASS_ENABLE_REQ);
//     }
//     else
//     {
//         // For each BAS instance
//         for (i = 0; i < bass_env.bas_nb; i++)
//         {
//             // Reset Offset value
//             offset = BAS_IDX_BATT_LVL_NTF_CFG;

//             // Update Battery Level value in DB
//             attsdb_att_set_value(bass_env.shdl[i] + BAS_IDX_BATT_LVL_VAL, sizeof(uint8_t),
//                                  (uint8_t *)&param->current_batt_lvl[i]);

//             // Check if BAS supports notifications
//             if (bass_env.features[i] == BAS_BATT_LVL_NTF_SUP)
//             {
//                 // Increment offset (Client Char. Cfg is placed before Char. Pres Fmt. in DB)
//                 offset++;

//                 // If client is a bonded client
//                 if (param->con_type == PRF_CON_NORMAL)
//                 {
//                     ntf_cfg = param->batt_level_ntf_cfg[i];

//                     /*
//                      * The server shall send a notification if value of the Battery Level characteristic
//                      * has changed while the service has been disconnected from a bonded client.
//                      */
//                     if (param->batt_level_ntf_cfg[i] == PRF_CLI_START_NTF)
//                     {
//                         // Conserve information in environment
//                         bass_env.features[i] |= BASS_FLAG_NTF_CFG_BIT;

//                         // Check if old and previous battery level values are different
//                         if (param->old_batt_lvl[i] != param->current_batt_lvl[i])
//                         {
//                             //Notify current battery level value
//                             struct gatt_notify_req *ntf = KE_MSG_ALLOC(GATT_NOTIFY_REQ, TASK_GATT,
//                                                                        TASK_BASS, gatt_notify_req);

//                             ntf->conhdl  = bass_env.con_info.conhdl;
//                             ntf->charhdl = bass_env.shdl[i] + BAS_IDX_BATT_LVL_VAL;

//                             ke_msg_send(ntf);
//                         }
//                     }
//                 }

//                 // Set NTF Cfg value in the DB
//                 attsdb_att_set_value(bass_env.shdl[i] + BAS_IDX_BATT_LVL_NTF_CFG, sizeof(uint16_t),
//                                      (uint8_t *)&ntf_cfg);
//             }

//             // Check if Characteristic Presentation Format descriptor has been added
//             if (bass_env.bas_nb > 1)
//             {
//                 prf_pack_char_pres_fmt(&packed_char_pres[0], &param->batt_level_pres_format[i]);

//                 /*
//                  * Set Characteristic Presentation Format descriptor value
//                  * Not supposed to change during connection
//                  */
//                 attsdb_att_set_value(bass_env.shdl[i] + offset,
//                                      PRF_CHAR_PRES_FMT_SIZE,
//                                      &packed_char_pres[0]);
//             }

//             // Enable Service + Set Security Level
//             attsdb_svc_set_permission(bass_env.shdl[i], param->sec_lvl);
//         }

//         // Go to connected state
//         ke_state_set(TASK_BASS, BASS_CONNECTED);
//     }

    return (KE_MSG_CONSUMED);
}
Exemplo n.º 8
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);
}
Exemplo n.º 9
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);
}
Exemplo n.º 10
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 = PRF_ERR_OK;

    if (param->conhdl == qpps_env.conhdl)
    {
        // Client Char. Configuration
		uint8_t char_index = param->handle - (qpps_env.shdl + QPPS_IDX_VAL_NTF_CFG);
        if ((param->handle > (qpps_env.shdl + QPPS_IDX_VAL_CHAR)) && ((char_index % 3) == 0))
        {
            uint16_t value = 0x0000;

            //Extract value before check
            memcpy(&value, &(param->value), sizeof(uint16_t));

            if ((value == PRF_CLI_STOP_NTFIND) || (value == PRF_CLI_START_NTF))
            {
                if (value == PRF_CLI_STOP_NTFIND)
                {
                    qpps_env.features &= ~(QPPS_VALUE_NTF_CFG << (char_index / 3));
                }
                else //PRF_CLI_START_NTF
                {
                    qpps_env.features |= QPPS_VALUE_NTF_CFG << (char_index / 3);
                }
            }
            else
            {
                status = PRF_APP_ERROR;
            }

            if (status == PRF_ERR_OK)
            {
                uint8_t *old_value;
                atts_size_t length;

                attsdb_att_get_value(param->handle, &length, &old_value);
                if (value != co_read16p(old_value))
                {
                    //Update the attribute value
                    attsdb_att_set_value(param->handle, sizeof(uint16_t), (uint8_t *)&value);

                    if(param->last)
                    {
                        //Inform APP of configuration change
                        struct qpps_cfg_indntf_ind * ind = KE_MSG_ALLOC(QPPS_CFG_INDNTF_IND,
                                                                        qpps_env.appid, TASK_QPPS,
                                                                        qpps_cfg_indntf_ind);

                        ind->char_index = (char_index / 3);
                        memcpy(&ind->cfg_val, &value, sizeof(uint16_t));

                        ke_msg_send(ind);
                    }
                }
            }
        }
        else if (param->handle == (qpps_env.shdl + QPPS_IDX_RX_DATA_VAL))
        {
			if (param->length <= QPP_DATA_MAX_LEN)
			{
				//inform APP of configuration change
				struct qpps_data_val_ind * ind = KE_MSG_ALLOC_DYN(QPPS_DAVA_VAL_IND,
																  qpps_env.appid,
																  TASK_QPPS,
																  qpps_data_val_ind, param->length);

				memcpy(&ind->conhdl, &(qpps_env.conhdl), sizeof(uint16_t));
				//Send received data to app value
				ind->length = param->length;
				memcpy(ind->data, param->value, param->length);

				ke_msg_send(ind);
			}
			else
			{
				status = QPPS_ERR_RX_DATA_EXCEED_MAX_LENGTH;
			}
        }
		else
		{
			status = QPPS_ERR_INVALID_PARAM;
		}
    }

    if (param->response)
    {
        //Send write response
        atts_write_rsp_send(qpps_env.conhdl, param->handle, status);
    }

    return (KE_MSG_CONSUMED);
}
Exemplo n.º 11
0
uint8_t hogpd_ntf_send(uint8_t hids_nb, uint8_t char_code, uint8_t report_nb,
                       uint16_t report_len, uint8_t *p_report)
{
    // Status
    uint8_t status = PRF_ERR_OK;
    // Handle
    uint16_t handle;
    // Mask
    uint8_t mask;
    // Flag
    uint8_t flag;

    // Check if the required Report Char. is supported
    if (hogpd_env.att_tbl[hids_nb][char_code + report_nb] != 0x00)
    {
        handle = hogpd_env.shdl[hids_nb] + hogpd_env.att_tbl[hids_nb][char_code + report_nb] + 1;

        // Set value in the database
        attsdb_att_set_value(handle, report_len, p_report);

        // Check if notifications have been enabled for the required characteristic
        switch(char_code)
        {
            case HOGPD_REPORT_CHAR:
                flag = hogpd_env.features[hids_nb].report_char_cfg[report_nb];
                mask = HOGPD_REPORT_NTF_CFG_MASK;
                break;
            case HOGPD_BOOT_KB_IN_REPORT_CHAR:
                flag = hogpd_env.features[hids_nb].svc_features;
                mask = HOGPD_BOOT_KB_IN_NTF_CFG_MASK;
                break;
            case HOGPD_BOOT_MOUSE_IN_REPORT_CHAR:
                flag = hogpd_env.features[hids_nb].svc_features;
                mask = HOGPD_BOOT_MOUSE_IN_NTF_CFG_MASK;
                break;
            default:
                return PRF_ERR_INVALID_PARAM;
        }

        if ((flag & mask) != mask)
        {
            status = PRF_ERR_NTF_DISABLED;
        }

        // Check if notifications are enabled
        if (status == PRF_ERR_OK)
        {
            // Send notification through GATT
            struct gatt_notify_req * ntf = KE_MSG_ALLOC(GATT_NOTIFY_REQ, TASK_GATT,
                                                        TASK_HOGPD, gatt_notify_req);

            ntf->conhdl  = hogpd_env.con_info.conhdl;
            ntf->charhdl = handle;

            ke_msg_send(ntf);
        }
    }
    else
    {
        status = PRF_ERR_FEATURE_NOT_SUPPORTED;
    }

    return status;
}
Exemplo n.º 12
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)
{
    uint16_t value = 0x0000;
    uint8_t status = PRF_ERR_OK;
    uint8_t char_code = 0;

    if (param->conhdl == blps_env.con_info.conhdl)
    {
        //Extract value before check
        memcpy(&value, &(param->value), sizeof(uint16_t));

        //BP Measurement Char. - Client Char. Configuration
        if (param->handle == (blps_env.shdl + BPS_IDX_BP_MEAS_IND_CFG))
        {
            if ((value == PRF_CLI_STOP_NTFIND) || (value == PRF_CLI_START_IND))
            {
                char_code = BPS_BP_MEAS_CODE;

                if (value == PRF_CLI_STOP_NTFIND)
                {
                    blps_env.evt_cfg &= ~BLPS_BP_MEAS_IND_CFG;
                }
                else //PRF_CLI_START_IND
                {
                    blps_env.evt_cfg |= BLPS_BP_MEAS_IND_CFG;
                }
            }
            else
            {
                status = PRF_APP_ERROR;
            }
        }
        else if (param->handle == (blps_env.shdl + BPS_IDX_INTM_CUFF_PRESS_NTF_CFG))
        {
            if ((value == PRF_CLI_STOP_NTFIND) || (value == PRF_CLI_START_NTF))
            {
                char_code = BPS_INTERM_CP_CODE;

                if (value == PRF_CLI_STOP_NTFIND)
                {
                    blps_env.evt_cfg &= ~BLPS_INTM_CUFF_PRESS_NTF_CFG;
                }
                else //PRF_CLI_START_NTF
                {
                    blps_env.evt_cfg |= BLPS_INTM_CUFF_PRESS_NTF_CFG;
                }
            }
            else
            {
                status = PRF_APP_ERROR;
            }
        }

        if (status == PRF_ERR_OK)
        {
            //Update the attribute value
            attsdb_att_set_value(param->handle, sizeof(uint16_t), (uint8_t *)&value);
            if(param->last)
            {
                //Inform APP of configuration change
                struct blps_cfg_indntf_ind * ind = KE_MSG_ALLOC(BLPS_CFG_INDNTF_IND,
                                                                blps_env.con_info.appid, TASK_BLPS,
                                                                blps_cfg_indntf_ind);

                memcpy(&ind->conhdl, &blps_env.con_info.conhdl, sizeof(uint16_t));
                ind->char_code = char_code;
                memcpy(&ind->cfg_val, &value, sizeof(uint16_t));

                ke_msg_send(ind);
            }
        }
    }

    //Send write response
    atts_write_rsp_send(blps_env.con_info.conhdl, param->handle, status);

    return (KE_MSG_CONSUMED);
}
Exemplo n.º 13
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref BLPS_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 blps_meas_send_req_handler(ke_msg_id_t const msgid,
                                      struct blps_meas_send_req const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    uint8_t packed_bp[BLPS_BP_MEAS_MAX_LEN];
    uint8_t status = PRF_ERR_OK;
    uint8_t size;

    if(param->conhdl == blps_env.con_info.conhdl)
    {
        //Pack the BP Measurement value
        size = blps_pack_meas_value(&packed_bp[0], &param->meas_val);

        //Intermediary blood pressure, must be notified if enabled
        if(param->flag_interm_cp == 0x01)
        {
            //Check if Char. is supported
            if (BLPS_IS_SUPPORTED(BLPS_INTM_CUFF_PRESS_SUP))
            {
                //Check if notifications are enabled
                if(BLPS_IS_ENABLED(BLPS_INTM_CUFF_PRESS_NTF_CFG))
                {
                    //Update value in DB
                    attsdb_att_set_value(blps_env.shdl + BPS_IDX_INTM_CUFF_PRESS_VAL,
                                         size, &packed_bp[0]);

                    //Send notification through GATT
                    struct gatt_notify_req * ntf = KE_MSG_ALLOC(GATT_NOTIFY_REQ, TASK_GATT,
                                                                TASK_BLPS, gatt_notify_req);
                    ntf->conhdl  = blps_env.con_info.conhdl;
                    ntf->charhdl = blps_env.shdl + BPS_IDX_INTM_CUFF_PRESS_VAL;

                    ke_msg_send(ntf);
                }
                //notification not enabled, simply don't send anything
                else
                {
                    status = PRF_ERR_NTF_DISABLED;
                }
            }
            else
            {
                status = PRF_ERR_FEATURE_NOT_SUPPORTED;
            }
        }
        //Stable Blood Pressure Measurement, must be indicated if enabled
        else
        {
            if(BLPS_IS_ENABLED(BLPS_BP_MEAS_IND_CFG))
            {
                //Update value in DB
                attsdb_att_set_value(blps_env.shdl + BPS_IDX_BP_MEAS_VAL,
                                     size, &packed_bp[0]);

                //Send indication through GATT
                struct gatt_indicate_req * ind = KE_MSG_ALLOC(GATT_INDICATE_REQ, TASK_GATT,
                                                              TASK_BLPS, gatt_indicate_req);
                ind->conhdl  = blps_env.con_info.conhdl;
                ind->charhdl = blps_env.shdl + BPS_IDX_BP_MEAS_VAL;

                ke_msg_send(ind);
            }
            else
            {
                status = PRF_ERR_IND_DISABLED;
            }
        }

    }
    else
    {
        //Wrong Connection Handle
        status = (PRF_ERR_INVALID_PARAM);
    }

    // verify that no error occurs
    if(status != PRF_ERR_OK)
    {
        blps_meas_send_cfm_send(status);
    }

    return (KE_MSG_CONSUMED);
}
Exemplo n.º 14
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref BLPS_ENABLE_REQ message.
 * The handler enables the Blood Pressure 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 blps_enable_req_handler(ke_msg_id_t const msgid,
                                   struct blps_enable_req const *param,
                                   ke_task_id_t const dest_id,
                                   ke_task_id_t const src_id)
{
    //Value used to initialize all readable value in DB
    uint16_t indntf_cfg = 0;

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

    // Check if the provided connection exist
    if (gap_get_rec_idx(param->conhdl) == GAP_INVALID_CONIDX)
    {
        // The connection doesn't exist, request disallowed
        prf_server_error_ind_send((prf_env_struct *)&blps_env, PRF_ERR_REQ_DISALLOWED,
                                  BLPS_ERROR_IND, BLPS_ENABLE_REQ);
    }
    else
    {
        // Set Blood Pressure Feature Value in database - Not supposed to change during connection
        attsdb_att_set_value(blps_env.shdl + BPS_IDX_BP_FEATURE_VAL, sizeof(uint16_t),
                             (uint8_t *)&param->bp_feature);

        // Configure Blood Pressure Measuremment IND Cfg in DB
        if(param->con_type == PRF_CON_NORMAL)
        {
            memcpy(&indntf_cfg, &param->bp_meas_ind_en, sizeof(uint16_t));

            if (param->bp_meas_ind_en == PRF_CLI_START_IND)
            {
                blps_env.evt_cfg |= BLPS_BP_MEAS_IND_CFG;
            }
        }

        //Set BP Meas. Char. IND Configuration in DB - 0 if not normal connection
        attsdb_att_set_value(blps_env.shdl + BPS_IDX_BP_MEAS_IND_CFG, sizeof(uint16_t),
                             (uint8_t *)&indntf_cfg);

        // Configure Intermediate Cuff Pressure NTF Cfg in DB
        if (BLPS_IS_SUPPORTED(BLPS_INTM_CUFF_PRESS_SUP))
        {
            if(param->con_type == PRF_CON_NORMAL)
            {
                memcpy(&indntf_cfg, &param->interm_cp_ntf_en, sizeof(uint16_t));

                if (param->interm_cp_ntf_en == PRF_CLI_START_NTF)
                {
                    blps_env.evt_cfg |= BLPS_INTM_CUFF_PRESS_NTF_CFG;
                }
            }

            //Set Intm. Cuff Pressure NTF Configuration in DB - 0 if not normal connection
            attsdb_att_set_value(blps_env.shdl + BPS_IDX_INTM_CUFF_PRESS_NTF_CFG, sizeof(uint16_t),
                                 (uint8_t *)&indntf_cfg);
        }

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

        // Go to connected state
        ke_state_set(TASK_BLPS, BLPS_CONNECTED);
    }

    return (KE_MSG_CONSUMED);
}