Example #1
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref QPPC_RD_CHAR_REQ message.
 * Check if the handle exists in profile(already discovered) and send request, otherwise
 * error to APP.
 * @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 qppc_rd_char_req_handler(ke_msg_id_t const msgid,
                                    struct qppc_rd_char_req const *param,
                                    ke_task_id_t const dest_id,
                                    ke_task_id_t const src_id)
{
    uint16_t search_hdl = ATT_INVALID_SEARCH_HANDLE;
    // Get the address of the environment
    struct qppc_env_tag *qppc_env = PRF_CLIENT_GET_ENV(dest_id, qppc);

    if (param->conhdl == qppc_env->con_info.conhdl && 
        param->char_code < qppc_env->nb_char)
    {
        qppc_env->last_char_code = param->char_code;
        search_hdl = qppc_env->qpps.descs[param->char_code].desc_hdl;

        //check if handle is variable
        if (search_hdl != ATT_INVALID_SEARCH_HANDLE)
        {
            prf_read_char_send(&(qppc_env->con_info), qppc_env->qpps.svc.shdl, qppc_env->qpps.svc.ehdl, search_hdl);
        }
        else
        {
            qppc_error_ind_send(qppc_env, PRF_ERR_INEXISTENT_HDL);
        }
    }
    else
    {
        qppc_error_ind_send(qppc_env, PRF_ERR_INVALID_PARAM);
    }

    return (KE_MSG_CONSUMED);
}
Example #2
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref PROXM_RD_ALERT_LVL_REQ message.
 * Request to read the LLS alert level.
 * @param[in] msgid Id of the message received (probably unused).
 * @param[in] param Pointer to the parameters of the message.
 * @param[in] dest_id ID of the receiving task instance (probably unused).
 * @param[in] src_id ID of the sending task instance.
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
static int proxm_rd_alert_lvl_req_handler(ke_msg_id_t const msgid,
        struct proxm_rd_alert_lvl_req const *param,
        ke_task_id_t const dest_id,
        ke_task_id_t const src_id)
{
    // Get the address of the environment
    struct proxm_env_tag *proxm_env = PRF_CLIENT_GET_ENV(dest_id, proxm);

    // Save the read characteristic code
    proxm_env->last_char_code = PROXM_RD_LL_ALERT_LVL;

    if(param->conhdl == gapc_get_conhdl(proxm_env->con_info.conidx))
    {
        if(proxm_env->lls.charact.val_hdl != ATT_INVALID_HANDLE)
        {
            // Send Read Char. request
            prf_read_char_send(&proxm_env->con_info,
                               proxm_env->lls.svc.shdl, proxm_env->lls.svc.ehdl,
                               proxm_env->lls.charact.val_hdl);
        }
        else
        {
            prf_client_att_info_rsp((prf_env_struct*) proxm_env, PROXM_RD_CHAR_RSP,
                                    PRF_ERR_INEXISTENT_HDL, NULL);
        }
    }
    else
    {
        // Wrong connection handle
        prf_client_att_info_rsp((prf_env_struct*) proxm_env, PROXM_RD_CHAR_RSP,
                                PRF_ERR_INVALID_PARAM, NULL);
    }

    return (KE_MSG_CONSUMED);
}
Example #3
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GLPC_READ_FEATURES_REQ message.
 * Send by application task, it's used to retrieve Glucose Sensor features.
 *
 * @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 glpc_read_features_req_handler(ke_msg_id_t const msgid,
                                          struct glpc_read_features_req 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);

    uint8_t status = glpc_validate_request(glpc_env, param->conhdl, GLPC_CHAR_FEATURE);

    // request can be performed
    if(status == PRF_ERR_OK)
    {
        // read glucose sensor feature
        prf_read_char_send(&(glpc_env->con_info),  glpc_env->gls.svc.shdl,
                glpc_env->gls.svc.ehdl,  glpc_env->gls.chars[GLPC_CHAR_FEATURE].val_hdl);
    }
    // send command response with error code
    else
    {
        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 error status
        rsp->conhdl = param->conhdl;
        rsp->status = status;

        ke_msg_send(rsp);
    }

    return (KE_MSG_CONSUMED);
}
Example #4
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref HOGPBH_RD_CHAR_REQ message.
 * @param[in] msgid Id of the message received (probably unused).
 * @param[in] param Pointer to the parameters of the message.
 * @param[in] dest_id ID of the receiving task instance (probably unused).
 * @param[in] src_id ID of the sending task instance.
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
static int hogpbh_rd_char_req_handler(ke_msg_id_t const msgid,
                                      struct hogpbh_rd_char_req const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    // Status
    uint8_t status = PRF_ERR_OK;
    // Attribute handle
    uint16_t search_hdl = ATT_INVALID_SEARCH_HANDLE;
    // Get the address of the environment
    struct hogpbh_env_tag *hogpbh_env = PRF_CLIENT_GET_ENV(dest_id, hogpbh);

    // Save the attribute read code
    hogpbh_env->last_char_code = param->char_code;

    if((param->conhdl == hogpbh_env->con_info.conhdl) &&
       (param->hids_nb < HOGPBH_NB_HIDS_INST_MAX))
    {
        // Descriptor
        if(((param->char_code & HOGPBH_DESC_MASK) == HOGPBH_DESC_MASK) &&
           ((param->char_code & ~HOGPBH_DESC_MASK) < HOGPBH_DESC_MASK))
        {
            search_hdl = hogpbh_env->hids[param->hids_nb].descs[param->char_code & ~HOGPBH_DESC_MASK].desc_hdl;
        }
        // Characteristic
        else if (param->char_code < HOGPBH_CHAR_MAX)
        {
            search_hdl = hogpbh_env->hids[param->hids_nb].chars[param->char_code].val_hdl;
        }

        // Check if handle is viable
        if (search_hdl != ATT_INVALID_SEARCH_HANDLE)
        {
            prf_read_char_send(&(hogpbh_env->con_info), hogpbh_env->hids[param->hids_nb].svc.shdl,
                               hogpbh_env->hids[param->hids_nb].svc.ehdl, search_hdl);

            // Save the service instance number
            hogpbh_env->last_svc_inst_req  = param->hids_nb;
        }
        else
        {
            status = PRF_ERR_INEXISTENT_HDL;
        }
    }
    else
    {
        status = PRF_ERR_INVALID_PARAM;

    }

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

    return (KE_MSG_CONSUMED);
}
Example #5
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref STREAMDATAH_STREAMON_REQ message.
 * Turns on the stream by writing a nonzero value to the STREAMDATAD_ENABLE attribute.
 * @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 streamdatah_rd_streamon_enable_req_handler(ke_msg_id_t const msgid,
                                    struct streamdatah_rd_streamon_enable_req const *param,
                                    ke_task_id_t const dest_id,
                                    ke_task_id_t const src_id)
{
    // Get the address of the environment
    struct streamdatah_env_tag *streamdatah_env = PRF_CLIENT_GET_ENV(dest_id, streamdatah);
	
	prf_read_char_send(&streamdatah_env->con_info,
					   streamdatah_env->streamdatad.svc.shdl, streamdatah_env->streamdatad.svc.ehdl,
					   streamdatah_env->streamdatad.chars[STREAMDATAD_ENABLE_CHAR].val_hdl);
    return (KE_MSG_CONSUMED);
}
Example #6
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref HTPC_RD_DATETIME_REQ message.
 * Check if the handle exists in profile(already discovered) and send request, otherwise
 * error to APP.
 * @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 htpc_rd_char_req_handler(ke_msg_id_t const msgid,
                                        struct htpc_rd_char_req const *param,
                                        ke_task_id_t const dest_id,
                                        ke_task_id_t const src_id)
{
    // Attribute handle
    uint16_t search_hdl = ATT_INVALID_SEARCH_HANDLE;
    // Get the address of the environment
    struct htpc_env_tag *htpc_env = PRF_CLIENT_GET_ENV(dest_id, htpc);

    if(param->conhdl == gapc_get_conhdl(htpc_env->con_info.conidx))
    {
        // Descriptors
        if(((param->char_code & HTPC_DESC_HTS_MASK) == HTPC_DESC_HTS_MASK) &&
           ((param->char_code & ~HTPC_DESC_HTS_MASK) < HTPC_DESC_HTS_MAX))
        {
            search_hdl = htpc_env->hts.descs[param->char_code & ~HTPC_DESC_HTS_MASK].desc_hdl;
        }
        // Characteristic
        else if (param->char_code < HTPC_CHAR_HTS_MAX)
        {
            search_hdl = htpc_env->hts.chars[param->char_code].val_hdl;
        }

        // Check if handle is viable
        if (search_hdl != ATT_INVALID_SEARCH_HANDLE)
        {
            htpc_env->last_char_code = param->char_code;
            prf_read_char_send(&(htpc_env->con_info), htpc_env->hts.svc.shdl,
                               htpc_env->hts.svc.ehdl, search_hdl);
        }
        else
        {
            prf_client_att_info_rsp((prf_env_struct*) htpc_env, HTPC_RD_CHAR_RSP,
                    PRF_ERR_INEXISTENT_HDL, NULL);

        }
    }
    else
    {
        prf_client_att_info_rsp((prf_env_struct*) htpc_env, HTPC_RD_CHAR_RSP,
                PRF_ERR_INVALID_PARAM, NULL);

    }

    return (KE_MSG_CONSUMED);
}
Example #7
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref BASC_CHAR_RD_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 basc_char_rd_req_handler(ke_msg_id_t const msgid,
                                               struct basc_char_rd_req const *param,
                                               ke_task_id_t const dest_id,
                                               ke_task_id_t const src_id)
{
    uint16_t search_hdl = ATT_INVALID_SEARCH_HANDLE;
    // Get the address of the environment
    struct basc_env_tag *basc_env = PRF_CLIENT_GET_ENV(dest_id, basc);

    // Check Connection Handle, BAS Instance
    if((param->conhdl == basc_env->con_info.conhdl) &&
       (param->bas_nb < BASC_NB_BAS_INSTANCES_MAX))
    {
        //Battery Level Service Descriptor
        if(((param->char_code & BAS_DESC_MASK) == BAS_DESC_MASK) &&
           ((param->char_code & ~BAS_DESC_MASK) < BAS_DESC_MASK))
        {
            search_hdl = basc_env->bas[param->bas_nb].descs[param->char_code & ~BAS_DESC_MASK].desc_hdl;
        }
        //Battery Service Characteristic
        else if (param->char_code < BAS_CHAR_MAX)
        {
            search_hdl = basc_env->bas[param->bas_nb].chars[param->char_code].val_hdl;
        }

        // Check if handle is viable
        if (search_hdl != ATT_INVALID_SEARCH_HANDLE)
        {
            prf_read_char_send(&(basc_env->con_info), basc_env->bas[param->bas_nb].svc.shdl,
                               basc_env->bas[param->bas_nb].svc.ehdl, search_hdl);
            // Save the service instance number
            basc_env->last_svc_inst_req  = param->bas_nb;
            // Save the attribute read code
            basc_env->last_char_code     = param->char_code;
        }
        else
        {
            basc_error_ind_send(basc_env, PRF_ERR_INEXISTENT_HDL);
        }
    }
    else
    {
        basc_error_ind_send(basc_env, PRF_ERR_INVALID_PARAM);
    }

    return (KE_MSG_CONSUMED);
}
Example #8
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref BLPC_RD_DATETIME_REQ message.
 * Check if the handle exists in profile(already discovered) and send request, otherwise
 * error to APP.
 * @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 blpc_rd_char_req_handler(ke_msg_id_t const msgid,
                                        struct blpc_rd_char_req const *param,
                                        ke_task_id_t const dest_id,
                                        ke_task_id_t const src_id)
{
    uint16_t search_hdl = 0x0000;
    uint16_t shdl = 0x0000;
    uint16_t ehdl = 0x0000;
    // Get the address of the environment
    struct blpc_env_tag *blpc_env = PRF_CLIENT_GET_ENV(dest_id, blpc);

    if(param->conhdl == gapc_get_conhdl(blpc_env->con_info.conidx))
    {
        if((param->char_code & BLPC_DESC_MASK) == BLPC_DESC_MASK)
        {
            search_hdl = blpc_env->bps.descs[param->char_code & ~BLPC_DESC_MASK].desc_hdl;
            shdl = blpc_env->bps.svc.shdl;
            ehdl = blpc_env->bps.svc.ehdl;
        }
        else
        {
            search_hdl = blpc_env->bps.chars[param->char_code].val_hdl;
            shdl = blpc_env->bps.svc.shdl;
            ehdl = blpc_env->bps.svc.ehdl;
        }

        //check if handle is viable
        if (search_hdl != ATT_INVALID_SEARCH_HANDLE)
        {
            prf_read_char_send(&(blpc_env->con_info), shdl, ehdl, search_hdl);
        }
        else
        {
            prf_client_att_info_rsp((prf_env_struct*) blpc_env, BLPC_RD_CHAR_RSP,
                    PRF_ERR_INEXISTENT_HDL, NULL);
        }
    }
    else
    {
        prf_client_att_info_rsp((prf_env_struct*) blpc_env, BLPC_RD_CHAR_RSP,
                PRF_ERR_INVALID_PARAM, NULL);
    }

    return (KE_MSG_CONSUMED);
}
Example #9
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref HRPC_RD_DATETIME_REQ message.
 * Check if the handle exists in profile(already discovered) and send request, otherwise
 * error to APP.
 * @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 hrpc_rd_char_req_handler(ke_msg_id_t const msgid,
                                        struct hrpc_rd_char_req const *param,
                                        ke_task_id_t const dest_id,
                                        ke_task_id_t const src_id)
{
    uint16_t search_hdl = ATT_INVALID_SEARCH_HANDLE;
    // Get the address of the environment
    struct hrpc_env_tag *hrpc_env = PRF_CLIENT_GET_ENV(dest_id, hrpc);

    if(param->conhdl == hrpc_env->con_info.conhdl)
    {
        if(((param->char_code & HRPC_DESC_MASK) == HRPC_DESC_MASK) &&
           ((param->char_code & ~HRPC_DESC_MASK) < HRPC_DESC_MAX))
        {
            search_hdl = hrpc_env->hrs.descs[param->char_code & ~HRPC_DESC_MASK].desc_hdl;
        }
        else if (param->char_code < HRPC_CHAR_MAX)
        {
            search_hdl = hrpc_env->hrs.chars[param->char_code].val_hdl;
        }

        //check if handle is viable
        if (search_hdl != ATT_INVALID_SEARCH_HANDLE)
        {
            hrpc_env->last_char_code = param->char_code;
            prf_read_char_send(&(hrpc_env->con_info), hrpc_env->hrs.svc.shdl, hrpc_env->hrs.svc.ehdl, search_hdl);
        }
        else
        {
            hrpc_error_ind_send(hrpc_env, PRF_ERR_INEXISTENT_HDL);
        }
    }
    else
    {
        hrpc_error_ind_send(hrpc_env, PRF_ERR_INVALID_PARAM);
    }

    return (KE_MSG_CONSUMED);
}
Example #10
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref SCPPC_SCAN_REFRESH_NTF_CFG_RD_REQ message.
 * @param[in] msgid Id of the message received (probably unused).
 * @param[in] param Pointer to the parameters of the message.
 * @param[in] dest_id ID of the receiving task instance (probably unused).
 * @param[in] src_id ID of the sending task instance.
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
static int scppc_scan_refresh_ntf_cfg_rd_req_handler(ke_msg_id_t const msgid,
                                                     struct scppc_scan_refresh_ntf_cfg_rd_req const *param,
                                                     ke_task_id_t const dest_id,
                                                     ke_task_id_t const src_id)
{
    // Get the address of the environment
    struct scppc_env_tag *scppc_env = PRF_CLIENT_GET_ENV(dest_id, scppc);

    if (param->conhdl == gapc_get_conhdl(scppc_env->con_info.conidx))
    {
        scppc_env->last_char_code = SCPPC_DESC_SCAN_REFRESH_CFG;

        prf_read_char_send(&(scppc_env->con_info),
                           scppc_env->scps.svc.shdl,
                           scppc_env->scps.svc.ehdl,
                           scppc_env->scps.descs[SCPPC_DESC_SCAN_REFRESH_CFG].desc_hdl);
    }
    else
    {
        scppc_error_ind_send(scppc_env, PRF_ERR_INVALID_PARAM);
    }

    return (KE_MSG_CONSUMED);
}
Example #11
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref TIPC_RD_CHAR_REQ message.
 * Check if the handle exists in profile(already discovered) and send request, otherwise
 * error to APP.
 * @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 tipc_rd_char_req_handler(ke_msg_id_t const msgid,
                                        struct tipc_rd_char_req const *param,
                                        ke_task_id_t const dest_id,
                                        ke_task_id_t const src_id)
{
    // Attribute Handle
    uint16_t search_hdl = ATT_INVALID_SEARCH_HANDLE;
    // Service
    struct prf_svc *svc;

    // Get the address of the environment
    struct tipc_env_tag *tipc_env = PRF_CLIENT_GET_ENV(dest_id, tipc);

    if(param->conhdl == gapc_get_conhdl(tipc_env->con_info.conidx))
    {
        //Next DST Change Service Characteristic
        if (((param->char_code & TIPC_CHAR_NDCS_MASK) == TIPC_CHAR_NDCS_MASK) &&
            ((param->char_code & ~TIPC_CHAR_NDCS_MASK) < TIPC_CHAR_NDCS_MAX))
        {
            svc = &tipc_env->ndcs.svc;
            search_hdl = tipc_env->ndcs.chars[param->char_code & ~TIPC_CHAR_NDCS_MASK].val_hdl;
        }
        //Reference Time Update Service Characteristic
        else if (((param->char_code & TIPC_CHAR_RTUS_MASK) == TIPC_CHAR_RTUS_MASK) &&
                 ((param->char_code & ~TIPC_CHAR_RTUS_MASK) < TIPC_CHAR_RTUS_MAX))
        {
            svc = &tipc_env->rtus.svc;
            search_hdl = tipc_env->rtus.chars[param->char_code & ~TIPC_CHAR_RTUS_MASK].val_hdl;
        }
        else
        {
            svc = &tipc_env->cts.svc;

            //Current Time Characteristic Descriptor
            if (((param->char_code & TIPC_DESC_CTS_MASK) == TIPC_DESC_CTS_MASK) &&
                ((param->char_code & ~TIPC_DESC_CTS_MASK) < TIPC_DESC_CTS_MAX))
            {
                search_hdl = tipc_env->cts.descs[param->char_code & ~TIPC_DESC_CTS_MASK].desc_hdl;
            }
            //Current Time Service Characteristic
            else if (param->char_code < TIPC_CHAR_CTS_MAX)
            {
                search_hdl = tipc_env->cts.chars[param->char_code].val_hdl;
            }
        }

        // Check if handle is viable
        if (search_hdl != ATT_INVALID_SEARCH_HANDLE)
        {
            tipc_env->last_char_code = param->char_code;
            prf_read_char_send(&(tipc_env->con_info), svc->shdl, svc->ehdl, search_hdl);
        }
        else
        {
            tipc_error_ind_send(tipc_env, PRF_ERR_INEXISTENT_HDL);
        }
    }
    else
    {
        tipc_error_ind_send(tipc_env, PRF_ERR_INVALID_PARAM);
    }

    return (KE_MSG_CONSUMED);
}
Example #12
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref CSCPC_READ_CMD message.
 * @param[in] msgid Id of the message received.
 * @param[in] param Pointer to the parameters of the message.
 * @param[in] dest_id ID of the receiving task instance.
 * @param[in] src_id ID of the sending task instance.
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
static int cscpc_read_cmd_handler(ke_msg_id_t const msgid,
                                  struct cscpc_read_cmd *param,
                                  ke_task_id_t const dest_id,
                                  ke_task_id_t const src_id)
{
    // Message status
    uint8_t msg_status = KE_MSG_CONSUMED;

    // Get the address of the environment
    struct cscpc_env_tag *cscpc_env = PRF_CLIENT_GET_ENV(dest_id, cscpc);

    if (cscpc_env != NULL)
    {
        // Attribute Handle
        uint16_t handle    = ATT_INVALID_SEARCH_HANDLE;
        // Status
        uint8_t status     = PRF_ERR_OK;

        ASSERT_ERR(ke_state_get(dest_id) != CSCPC_IDLE);

        // Check the provided connection handle
        if (param->conhdl == cscpc_env->con_info.conhdl)
        {
            // Check the current state
            if (ke_state_get(dest_id) == CSCPC_BUSY)
            {
                // Keep the request for later
                msg_status = KE_MSG_SAVED;
            }
            else    // State is CSCPC_CONNECTED
            {
                ASSERT_ERR(cscpc_env->operation == NULL);

                switch (param->read_code)
                {
                    // Read CSC Feature
                    case (CSCPC_RD_CSC_FEAT):
                    {
                        handle = cscpc_env->cscs.chars[CSCP_CSCS_CSC_FEAT_CHAR].val_hdl;
                    } break;

                    // Read Sensor Location
                    case (CSCPC_RD_SENSOR_LOC):
                    {
                        handle = cscpc_env->cscs.chars[CSCP_CSCS_SENSOR_LOC_CHAR].val_hdl;
                    } break;

                    // Read CSC Measurement Characteristic Client Char. Cfg. Descriptor Value
                    case (CSCPC_RD_WR_CSC_MEAS_CFG):
                    {
                        handle = cscpc_env->cscs.descs[CSCPC_DESC_CSC_MEAS_CL_CFG].desc_hdl;
                    } break;

                    // Read Unread Alert Characteristic Client Char. Cfg. Descriptor Value
                    case (CSCPC_RD_WR_SC_CTNL_PT_CFG):
                    {
                        handle = cscpc_env->cscs.descs[CSCPC_DESC_SC_CTNL_PT_CL_CFG].desc_hdl;
                    } break;

                    default:
                    {
                        status = PRF_ERR_INVALID_PARAM;
                    } break;
                }

                // Check if handle is viable
                if (handle != ATT_INVALID_SEARCH_HANDLE)
                {
                    // Force the operation value
                    param->operation       = CSCPC_READ_OP_CODE;

                    // Store the command structure
                    cscpc_env->operation   = param;
                    msg_status             = KE_MSG_NO_FREE;

                    // Send the read request
                    prf_read_char_send(&(cscpc_env->con_info), cscpc_env->cscs.svc.shdl,
                                       cscpc_env->cscs.svc.ehdl, handle);

                    // Go to the Busy state
                    ke_state_set(dest_id, CSCPC_BUSY);
                }
                else
                {
                    status = PRF_ERR_INEXISTENT_HDL;
                }
            }
        }
        else
        {
            status = PRF_ERR_INVALID_PARAM;
        }

        if (status != PRF_ERR_OK)
        {
            // Send the complete event message to the task id stored in the environment
            cscpc_send_cmp_evt(cscpc_env, CSCPC_READ_OP_CODE, status);
        }
    }
    else
    {
        // No connection exists, send the status to the requester
        cscpc_send_no_conn_cmp_evt(dest_id, src_id, param->conhdl, CSCPC_READ_OP_CODE);
    }

    return (int)msg_status;
}
Example #13
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref ANPC_ENABLE_CMD message.
 * @param[in] msgid Id of the message received.
 * @param[in] param Pointer to the parameters of the message.
 * @param[in] dest_id ID of the receiving task instance.
 * @param[in] src_id ID of the sending task instance.
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
static int anpc_enable_cmd_handler(ke_msg_id_t const msgid,
                                   struct anpc_enable_cmd *param,
                                   ke_task_id_t const dest_id,
                                   ke_task_id_t const src_id)
{
    // Status
    uint8_t status     = PRF_ERR_OK;
    // Message status
    uint8_t msg_status = KE_MSG_CONSUMED;
    // Alert Notification Profile Client Role Task Environment
    struct anpc_env_tag *anpc_env;
    // Connection Information
    struct prf_con_info con_info;

    // Check if the provided connection handle is valid
    if (gapc_get_conidx(param->conhdl) != GAP_INVALID_CONIDX)
    {
        // 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 connection
        status = PRF_CLIENT_ENABLE(con_info, param, anpc);
    }
    else
    {
        status = PRF_ERR_REQ_DISALLOWED;
    }

    if (status == PRF_ERR_OK)
    {
        // Get the newly created environment
        anpc_env = PRF_CLIENT_GET_ENV(dest_id, anpc);

        // Keep the connection info
        memcpy(&anpc_env->con_info, &con_info, sizeof(struct prf_con_info));

        // Start discovering
        if (param->con_type == PRF_CON_DISCOVERY)
        {
            // Configure the environment for a discovery procedure
            anpc_env->last_req  = ATT_SVC_ALERT_NTF;
            // Force the operation value
            param->operation    = ANPC_ENABLE_OP_CODE;

            prf_disc_svc_send(&(anpc_env->con_info), ATT_SVC_ALERT_NTF);
        }
        // Bond information are provided
        else
        {
            // Keep the provided database content
            memcpy(&anpc_env->ans, &param->ans, sizeof(struct anpc_ans_content));

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

            // Force the operation value
            param->operation = ANPC_ENABLE_RD_NEW_ALERT_OP_CODE;

            // Check Supported New Alert Category
            prf_read_char_send(&(anpc_env->con_info), anpc_env->ans.svc.shdl,
                               anpc_env->ans.svc.ehdl, anpc_env->ans.chars[ANPC_CHAR_SUP_NEW_ALERT_CAT].val_hdl);
        }

        // Keep the operation
        anpc_env->operation = (void *)param;
        // Do not free the message
        msg_status = KE_MSG_NO_FREE;

        // Go to BUSY state
        ke_state_set(dest_id, ANPC_BUSY);
    }
    else if (status == PRF_ERR_FEATURE_NOT_SUPPORTED)
    {
        // The message will be forwarded towards the good task instance
        msg_status = KE_MSG_NO_FREE;
    }
    else
    {
        // The request is disallowed (profile already enabled for this connection, or not enough memory, ...)
        anpc_send_no_conn_cmp_evt(dest_id, src_id, param->conhdl, ANPC_ENABLE_OP_CODE);
    }

    return (int)msg_status;
}
Example #14
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GATTC_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 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)
{
    // Get the address of the environment
    struct anpc_env_tag *anpc_env = PRF_CLIENT_GET_ENV(dest_id, anpc);

    if (anpc_env != NULL)
    {
        switch (param->req_type)
        {
            case (GATTC_DISC_BY_UUID_SVC):
            case (GATTC_DISC_ALL_CHAR):
            case (GATTC_DISC_DESC_CHAR):
            {
                // Status
                uint8_t status = PRF_ERR_STOP_DISC_CHAR_MISSING;

                if ((param->status == ATT_ERR_ATTRIBUTE_NOT_FOUND) ||
                    (param->status == ATT_ERR_NO_ERROR))
                {
                    ASSERT_ERR(((struct anpc_cmd *)anpc_env->operation)->operation == ANPC_ENABLE_OP_CODE);

                    /* -------------------------------------------------
                     * SERVICE DISCOVERY -------------------------------
                     * ------------------------------------------------- */
                    if (anpc_env->last_req == ATT_SVC_ALERT_NTF)
                    {
                        if (anpc_env->nb_svc > 0)
                        {
                            // Check if service handles are OK
                            if ((anpc_env->ans.svc.shdl != ATT_INVALID_HANDLE) &&
                                (anpc_env->ans.svc.ehdl != ATT_INVALID_HANDLE) &&
                                (anpc_env->ans.svc.shdl < anpc_env->ans.svc.ehdl))
                            {
                                // Status is OK
                                status = PRF_ERR_OK;

                                // Discover all ANS characteristics
                                prf_disc_char_all_send(&(anpc_env->con_info), &(anpc_env->ans.svc));
                                anpc_env->last_req = ATT_DECL_CHARACTERISTIC;
                            }
                            // Handles are not corrects, the Phone Alert Status Service has not been found, stop
                        }
                        // The Phone Alert Status Service has not been found, stop discovery
                    }
                    /* -------------------------------------------------
                     * CHARACTERISTICS DISCOVERY -----------------------
                     * ------------------------------------------------- */
                    else if (anpc_env->last_req == ATT_DECL_CHARACTERISTIC)
                    {
                        // Check if mandatory properties have been found and if properties are correct
                        status = prf_check_svc_char_validity(ANPC_CHAR_MAX, anpc_env->ans.chars, anpc_ans_char);

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

                            // Find the Client Characteristic Configuration Descriptor for the New Alert characteristic
                            prf_disc_char_desc_send(&(anpc_env->con_info),
                                                    &(anpc_env->ans.chars[ANPC_CHAR_NEW_ALERT]));
                        }
                    }
                    /* -------------------------------------------------
                     * DESCRIPTORS DISCOVERY ---------------------------
                     * ------------------------------------------------- */
                    else
                    {
                        if (anpc_env->last_req == ANPC_CHAR_NEW_ALERT)
                        {
                            status = PRF_ERR_OK;

                            anpc_env->last_req = ANPC_CHAR_UNREAD_ALERT_STATUS;

                            // Find the Client Characteristic Configuration Descriptor for the Unread Alert Status characteristic
                            prf_disc_char_desc_send(&(anpc_env->con_info),
                                                    &(anpc_env->ans.chars[ANPC_CHAR_UNREAD_ALERT_STATUS]));
                        }
                        else if (anpc_env->last_req == ANPC_CHAR_UNREAD_ALERT_STATUS)
                        {
                            status = prf_check_svc_char_desc_validity(ANPC_DESC_MAX,
                                                                      anpc_env->ans.descs,
                                                                      anpc_ans_char_desc,
                                                                      anpc_env->ans.chars);

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

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

                                // Send the content of the service to the HL
                                struct anpc_ans_content_ind *ind = KE_MSG_ALLOC(ANPC_ANS_CONTENT_IND,
                                                                                anpc_env->con_info.appid,
                                                                                anpc_env->con_info.prf_id,
                                                                                anpc_ans_content_ind);

                                ind->conhdl = gapc_get_conhdl(anpc_env->con_info.conidx);
                                memcpy(&ind->ans, &anpc_env->ans, sizeof(struct anpc_ans_content));

                                // Send the message
                                ke_msg_send(ind);

                                // Force the operation value
                                ((struct anpc_enable_cmd *)anpc_env->operation)->operation = ANPC_ENABLE_RD_NEW_ALERT_OP_CODE;
                                // Check Supported New Alert Categories
                                prf_read_char_send(&(anpc_env->con_info), anpc_env->ans.svc.shdl,
                                                   anpc_env->ans.svc.ehdl, anpc_env->ans.chars[ANPC_CHAR_SUP_NEW_ALERT_CAT].val_hdl);
                            }
                        }
                        else
                        {
                            ASSERT_ERR(0);
                        }
                    }
                }
                else
                {
                    status = param->status;
                }

                if (status != PRF_ERR_OK)
                {
                    // Stop discovery procedure.
                    anpc_send_cmp_evt(anpc_env, ANPC_ENABLE_OP_CODE, status);
                }
            } break;

            case (GATTC_WRITE):
            {
                // Retrieve the operation currently performed
                uint8_t operation = ((struct anpc_cmd *)anpc_env->operation)->operation;

                switch (operation)
                {
                    case (ANPC_WRITE_OP_CODE):
                    {
                        uint8_t wr_code = ((struct anpc_write_cmd *)anpc_env->operation)->write_code;

                        if ((wr_code == ANPC_RD_WR_NEW_ALERT_CFG) ||
                            (wr_code == ANPC_RD_WR_UNREAD_ALERT_STATUS_CFG) ||
                            (wr_code == ANPC_WR_ALERT_NTF_CTNL_PT))
                        {
                            anpc_send_cmp_evt(anpc_env, ANPC_WRITE_OP_CODE, param->status);
                        }
                        else
                        {
                            ASSERT_ERR(0);
                        }
                    } break;

                    case (ANPC_ENABLE_WR_NEW_ALERT_OP_CODE):
                    {
                        // Look for the next category to enable
                        if (anpc_found_next_alert_cat(anpc_env, ((struct anpc_enable_cmd *)anpc_env->operation)->new_alert_enable))
                        {
                            // Enable sending of notifications for the found category ID
                            anpc_write_alert_ntf_ctnl_pt(anpc_env, CMD_ID_EN_NEW_IN_ALERT_NTF, anpc_env->last_req - 1);
                        }
                        else
                        {
                            // Force the operation value
                            ((struct anpc_cmd *)anpc_env->operation)->operation = ANPC_ENABLE_WR_NTF_NEW_ALERT_OP_CODE;
                            // Send a "Notify New Alert Immediately" command with the Category ID field set to 0xFF
                            anpc_write_alert_ntf_ctnl_pt(anpc_env, CMD_ID_NTF_NEW_IN_ALERT_IMM, CAT_ID_ALL_SUPPORTED_CAT);
                        }
                    } break;

                    case (ANPC_ENABLE_WR_NTF_NEW_ALERT_OP_CODE):
                    {
                        // Reset the environment
                        anpc_env->last_req = CAT_ID_SPL_ALERT;

                        if (anpc_found_next_alert_cat(anpc_env, ((struct anpc_enable_cmd *)anpc_env->operation)->unread_alert_enable))
                        {
                            // Force the operation value
                            ((struct anpc_cmd *)anpc_env->operation)->operation = ANPC_ENABLE_WR_UNREAD_ALERT_OP_CODE;
                            // Enable sending of notifications for the found category ID
                            anpc_write_alert_ntf_ctnl_pt(anpc_env, CMD_ID_EN_UNREAD_CAT_STATUS_NTF, anpc_env->last_req - 1);
                        }
                        else
                        {
                            anpc_send_cmp_evt(anpc_env, ANPC_ENABLE_OP_CODE, PRF_ERR_OK);
                        }
                    } break;

                    case (ANPC_ENABLE_WR_UNREAD_ALERT_OP_CODE):
                    {
                        // Look for the next category to enable
                        if (anpc_found_next_alert_cat(anpc_env, ((struct anpc_enable_cmd *)anpc_env->operation)->unread_alert_enable))
                        {
                            // Enable sending of notifications for the found category ID
                            anpc_write_alert_ntf_ctnl_pt(anpc_env, CMD_ID_EN_UNREAD_CAT_STATUS_NTF, anpc_env->last_req - 1);
                        }
                        else
                        {
                            // Force the operation value
                            ((struct anpc_cmd *)anpc_env->operation)->operation = ANPC_ENABLE_WR_NTF_UNREAD_ALERT_OP_CODE;
                            // Send a "Notify New Alert Immediately" command with the Category ID field set to 0xFF
                            anpc_write_alert_ntf_ctnl_pt(anpc_env, CMD_ID_NTF_UNREAD_CAT_STATUS_IMM, CAT_ID_ALL_SUPPORTED_CAT);
                        }
                    } break;

                    case (ANPC_ENABLE_WR_NTF_UNREAD_ALERT_OP_CODE):
                    {
                        // The discovery procedure is over
                        anpc_send_cmp_evt(anpc_env, ANPC_ENABLE_OP_CODE, param->status);
                    } break;

                    default:
                    {
                        ASSERT_ERR(0);
                    } break;
                }
            } break;

            case (GATTC_READ):
            {
                switch (((struct anpc_cmd *)anpc_env->operation)->operation)
                {
                    // Read Supported New Alert Category Characteristic value
                    case (ANPC_ENABLE_RD_NEW_ALERT_OP_CODE):
                    {
                        if (param->status == GATT_ERR_NO_ERROR)
                        {
                            // Force the operation value
                            ((struct anpc_cmd *)anpc_env->operation)->operation = ANPC_ENABLE_RD_UNREAD_ALERT_OP_CODE;
                            // Check Supported Unread Alert Category
                            prf_read_char_send(&(anpc_env->con_info),
                                               anpc_env->ans.svc.shdl, anpc_env->ans.svc.ehdl,
                                               anpc_env->ans.chars[ANPC_CHAR_SUP_UNREAD_ALERT_CAT].val_hdl);
                        }
                        else
                        {
                            anpc_send_cmp_evt(anpc_env, ANPC_ENABLE_OP_CODE, param->status);
                        }
                    } break;

                    case (ANPC_ENABLE_RD_UNREAD_ALERT_OP_CODE):
                    {
                        if (param->status == GATT_ERR_NO_ERROR)
                        {
                            // If peer device was unknown, stop the procedure
                            if (((struct anpc_enable_cmd *)anpc_env->operation)->con_type == PRF_CON_DISCOVERY)
                            {
                                anpc_send_cmp_evt(anpc_env, ANPC_ENABLE_OP_CODE, PRF_ERR_OK);
                            }
                            // If peer device was already known (bonded), start Recovery from Connection Loss procedure
                            else
                            {
                                // Reset the environment
                                anpc_env->last_req = CAT_ID_SPL_ALERT;

                                if (anpc_found_next_alert_cat(anpc_env, ((struct anpc_enable_cmd *)anpc_env->operation)->new_alert_enable))
                                {
                                    // Force the operation value
                                    ((struct anpc_cmd *)anpc_env->operation)->operation = ANPC_ENABLE_WR_NEW_ALERT_OP_CODE;
                                    // Enable sending of notifications for the found category ID
                                    anpc_write_alert_ntf_ctnl_pt(anpc_env, CMD_ID_EN_NEW_IN_ALERT_NTF, anpc_env->last_req - 1);
                                }
                                else
                                {
                                    // Reset the environment
                                    anpc_env->last_req = CAT_ID_SPL_ALERT;

                                    if (anpc_found_next_alert_cat(anpc_env, ((struct anpc_enable_cmd *)anpc_env->operation)->unread_alert_enable))
                                    {
                                        // Force the operation value
                                        ((struct anpc_cmd *)anpc_env->operation)->operation = ANPC_ENABLE_WR_UNREAD_ALERT_OP_CODE;
                                        // Enable sending of notifications for the found category ID
                                        anpc_write_alert_ntf_ctnl_pt(anpc_env, CMD_ID_EN_UNREAD_CAT_STATUS_NTF, anpc_env->last_req - 1);
                                    }
                                    else
                                    {
                                        anpc_send_cmp_evt(anpc_env, ANPC_ENABLE_OP_CODE, PRF_ERR_OK);
                                    }
                                }
                            }
                        }
                        else
                        {
                            anpc_send_cmp_evt(anpc_env, ANPC_ENABLE_OP_CODE, param->status);
                        }
                    } break;

                    case (ANPC_READ_OP_CODE):
                    {
                        // Inform the requester that the read procedure is over
                        anpc_send_cmp_evt(anpc_env, ANPC_READ_OP_CODE, param->status);
                    } break;

                    default:
                    {
                        ASSERT_ERR(0);
                    }
                }
            } break;

            case (GATTC_REGISTER):
            case (GATTC_UNREGISTER):
            {
                // Do nothing
            } break;

            default:
            {
                ASSERT_ERR(0);
            } break;
        }
    }
    // else ignore the message

    return (KE_MSG_CONSUMED);
}
Example #15
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref ANPC_READ_CMD message.
 * @param[in] msgid Id of the message received.
 * @param[in] param Pointer to the parameters of the message.
 * @param[in] dest_id ID of the receiving task instance.
 * @param[in] src_id ID of the sending task instance.
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
static int anpc_read_cmd_handler(ke_msg_id_t const msgid,
                                  struct anpc_read_cmd *param,
                                  ke_task_id_t const dest_id,
                                  ke_task_id_t const src_id)
{
    // Message status
    uint8_t msg_status = KE_MSG_CONSUMED;

    // Get the address of the environment
    struct anpc_env_tag *anpc_env = PRF_CLIENT_GET_ENV(dest_id, anpc);

    if (anpc_env != NULL)
    {
        // Attribute Handle
        uint16_t handle    = ATT_INVALID_SEARCH_HANDLE;
        // Status
        uint8_t status     = PRF_ERR_OK;

        // State is Connected or Busy
        ASSERT_ERR(ke_state_get(dest_id) != ANPC_IDLE);

        // Check the provided connection handle
        if (gapc_get_conidx(param->conhdl) == anpc_env->con_info.conidx)
        {
            // Check the current state
            if (ke_state_get(dest_id) == ANPC_BUSY)
            {
                // Keep the request for later, status is PRF_ERR_OK
                msg_status = KE_MSG_SAVED;
            }
            else    // State is ANPC_CONNECTED
            {
                ASSERT_ERR(anpc_env->operation == NULL);

                switch (param->read_code)
                {
                    // Read New Alert Characteristic Client Char. Cfg. Descriptor Value
                    case (ANPC_RD_WR_NEW_ALERT_CFG):
                    {
                        handle = anpc_env->ans.descs[ANPC_DESC_NEW_ALERT_CL_CFG].desc_hdl;
                    } break;

                    // Read Unread Alert Characteristic Client Char. Cfg. Descriptor Value
                    case (ANPC_RD_WR_UNREAD_ALERT_STATUS_CFG):
                    {
                        handle = anpc_env->ans.descs[ANPC_DESC_UNREAD_ALERT_STATUS_CL_CFG].desc_hdl;
                    } break;

                    default:
                    {
                        status = PRF_ERR_INVALID_PARAM;
                    } break;
                }

                // Check if handle is viable
                if ((handle != ATT_INVALID_SEARCH_HANDLE) &&
                    (status == PRF_ERR_OK))
                {
                    // Force the operation value
                    param->operation      = ANPC_READ_OP_CODE;

                    // Store the command structure
                    anpc_env->operation   = param;
                    msg_status = KE_MSG_NO_FREE;

                    // Send the read request
                    prf_read_char_send(&(anpc_env->con_info), anpc_env->ans.svc.shdl,
                                       anpc_env->ans.svc.ehdl, handle);

                    // Go to the Busy state
                    ke_state_set(dest_id, ANPC_BUSY);
                }
                else
                {
                    status = PRF_ERR_INEXISTENT_HDL;
                }
            }
        }
        else
        {
            status = PRF_ERR_INVALID_PARAM;
        }


        if (status != PRF_ERR_OK)
        {
            anpc_send_cmp_evt(anpc_env, ANPC_READ_OP_CODE, status);
        }
    }
    else
    {
        // No connection exists
        anpc_send_no_conn_cmp_evt(dest_id, src_id, param->conhdl, ANPC_READ_OP_CODE);
    }

    return (int)msg_status;
}