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

    if (KE_IDX_GET(src_id) == scppc_env->con_info.conidx)
    {
        //Scan Refresh
        if (param->handle == scppc_env->scps.chars[SCPPC_CHAR_SCAN_REFRESH].val_hdl)
        {
            if (param->value[0] == SCPP_SERVER_REQUIRES_REFRESH)
            {
                // Rewrite the most recent settings written on the server
                struct scppc_scan_intv_wd_wr_req * req = KE_MSG_ALLOC(SCPPC_SCAN_INTV_WD_WR_REQ,
                                                                      dest_id, dest_id,
                                                                      scppc_scan_intv_wd_wr_req);

                req->conhdl = gapc_get_conhdl(scppc_env->con_info.conidx);

                co_write16p(&req->scan_intv_wd.le_scan_intv, scppc_env->scan_intv_wd.le_scan_intv);
                co_write16p(&req->scan_intv_wd.le_scan_window, scppc_env->scan_intv_wd.le_scan_window);

                ke_msg_send(req);
            }
        }
    }
    return (KE_MSG_CONSUMED);
}
예제 #2
0
파일: prf_utils.c 프로젝트: imGit/DA14580
void prf_pack_char_pres_fmt(uint8_t *packed_val, const struct prf_char_pres_fmt* char_pres_fmt)
{
    *packed_val =               char_pres_fmt->format;
    *(packed_val + 1) =         char_pres_fmt->exponent;
    co_write16p(packed_val + 2, char_pres_fmt->unit);
    *(packed_val + 4) =         char_pres_fmt->name_space;
    co_write16p(packed_val + 5, char_pres_fmt->description);
}
예제 #3
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;
}
예제 #4
0
파일: prf_utils.c 프로젝트: imGit/DA14580
void prf_gatt_write_ntf_ind(struct prf_con_info* con_info, uint16_t handle, uint16_t ntf_ind_cfg)
{
    uint8_t value[2];

    // put value in air format
    co_write16p((&value[0]), ntf_ind_cfg);
    // write value over GATT
    prf_gatt_write(con_info, handle, value, 2, GATTC_WRITE);
}
예제 #5
0
파일: prf_utils.c 프로젝트: imGit/DA14580
uint8_t prf_pack_date_time(uint8_t *packed_date, const struct prf_date_time* date_time)
{
    co_write16p(packed_date, date_time->year);
    *(packed_date + 2) = date_time->month;
    *(packed_date + 3) = date_time->day;
    *(packed_date + 4) = date_time->hour;
    *(packed_date + 5) = date_time->min;
    *(packed_date + 6) = date_time->sec;

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

    if (param->conhdl == gapc_get_conhdl(scppc_env->con_info.conidx))
    {
       if (scppc_env->scps.chars[SCPPC_CHAR_SCAN_INTV_WD].char_hdl != ATT_INVALID_SEARCH_HANDLE)
        {
           if (src_id == scppc_env->con_info.appid)
           {
               // Save the last written value
               co_write16p(&scppc_env->scan_intv_wd.le_scan_intv, param->scan_intv_wd.le_scan_intv);
               co_write16p(&scppc_env->scan_intv_wd.le_scan_window, param->scan_intv_wd.le_scan_window);
           }

           // Send GATT Write Request
           prf_gatt_write(&scppc_env->con_info, scppc_env->scps.chars[SCPPC_CHAR_SCAN_INTV_WD].val_hdl,
                          (uint8_t *)&param->scan_intv_wd, sizeof(struct scan_intv_wd), GATTC_WRITE_NO_RESPONSE);
        }
        //send app error indication for inexistent handle for this characteristic
        else
        {
            scppc_error_ind_send(scppc_env, PRF_ERR_INEXISTENT_HDL);
        }
    }
    else
    {
        scppc_error_ind_send(scppc_env, PRF_ERR_INVALID_PARAM);
    }

    return (KE_MSG_CONSUMED);
}
예제 #7
0
파일: prf_utils.c 프로젝트: imGit/DA14580
void prf_disc_char_all_send(struct prf_con_info *con_info,
                            struct prf_svc *svc)
{
    struct gattc_disc_cmd * char_req = KE_MSG_ALLOC_DYN(GATTC_DISC_CMD,
                                       KE_BUILD_ID(TASK_GATTC, con_info->conidx), con_info->prf_id,
                                       gattc_disc_cmd, ATT_UUID_16_LEN);

    char_req->req_type  = GATTC_DISC_ALL_CHAR;
    char_req->start_hdl = svc->shdl;
    char_req->end_hdl   = svc->ehdl;

    // UUID info - Don't care
    char_req->uuid_len = ATT_UUID_16_LEN;
    //set the first two bytes to the value array, LSB to MSB:Health Thermometer Service UUID first
    co_write16p(&(char_req->uuid[0]), ATT_INVALID_UUID);

    //send the message to GATT, which will send back the response when it gets it
    ke_msg_send(char_req);
}
예제 #8
0
파일: prf_utils.c 프로젝트: imGit/DA14580
void prf_disc_incl_svc_send(struct prf_con_info* con_info, struct prf_svc *svc)
{
    // Send GATT discover included services
    struct gattc_disc_cmd * svc_req = KE_MSG_ALLOC_DYN(GATTC_DISC_CMD,
                                      KE_BUILD_ID(TASK_GATTC, con_info->conidx), con_info->prf_id,
                                      gattc_disc_cmd, ATT_UUID_16_LEN);

    //gatt request type: by UUID
    svc_req->req_type         = GATTC_DISC_INCLUDED_SVC;
    //start handle;
    svc_req->start_hdl        = svc->shdl;
    //end handle
    svc_req->end_hdl          = svc->ehdl;

    // UUID info - Don't care
    svc_req->uuid_len = ATT_UUID_16_LEN;
    //set the first two bytes to the value array, LSB to MSB:Health Thermometer Service UUID first
    co_write16p(&(svc_req->uuid[0]), ATT_INVALID_UUID);

    // Send the message to GATT, which will send back the response when it gets it
    ke_msg_send(svc_req);
}
예제 #9
0
파일: prf_utils.c 프로젝트: imGit/DA14580
void prf_disc_svc_send(struct prf_con_info* con_info, uint16_t uuid)
{
    //send GATT discover primary services by UUID request: find by type request
    struct gattc_disc_cmd * svc_req = KE_MSG_ALLOC_DYN(GATTC_DISC_CMD,
                                      KE_BUILD_ID(TASK_GATTC, con_info->conidx), con_info->prf_id,
                                      gattc_disc_cmd, ATT_UUID_16_LEN);

    //gatt request type: by UUID
    svc_req->req_type         = GATTC_DISC_BY_UUID_SVC;
    //start handle;
    svc_req->start_hdl        = ATT_1ST_REQ_START_HDL;
    //end handle
    svc_req->end_hdl          = ATT_1ST_REQ_END_HDL;

    // UUID search
    svc_req->uuid_len = ATT_UUID_16_LEN;

    //set the first two bytes to the value array, LSB to MSB:Health Thermometer Service UUID first
    co_write16p(&(svc_req->uuid[0]), uuid);

    //send the message to GATT, which will send back the response when it gets it
    ke_msg_send(svc_req);
}
예제 #10
0
파일: prf_utils.c 프로젝트: imGit/DA14580
void prf_disc_char_desc_send(struct prf_con_info* con_info, struct prf_char_inf * charact)
{
    // Check if there is at least one descriptor to find
    if ((charact->val_hdl + 1) <= (charact->char_hdl + charact->char_ehdl_off - 1))
    {

        // Ask for handles of a certain uuid
        struct gattc_disc_cmd * dsc_req = KE_MSG_ALLOC_DYN(GATTC_DISC_CMD,
                                          KE_BUILD_ID(TASK_GATTC, con_info->conidx), con_info->prf_id,
                                          gattc_disc_cmd, ATT_UUID_16_LEN);

        dsc_req->req_type  = GATTC_DISC_DESC_CHAR;
        dsc_req->start_hdl = charact->val_hdl + 1;
        dsc_req->end_hdl   = charact->char_hdl + charact->char_ehdl_off - 1;

        // UUID info - Don't care
        dsc_req->uuid_len = ATT_UUID_16_LEN;
        //set the first two bytes to the value array, LSB to MSB:Health Thermometer Service UUID first
        co_write16p(&(dsc_req->uuid[0]), ATT_INVALID_UUID);

        //send the message to GATT;there should be only one handle response every time
        ke_msg_send(dsc_req);
    }
    else
    {
        // TODO [FBE] to be changed if SDP task implemented
        // Send a GATT complete event message
        struct gattc_cmp_evt *evt = KE_MSG_ALLOC(GATTC_CMP_EVT, con_info->prf_id,
                                    KE_BUILD_ID(TASK_GATTC , con_info->conidx),
                                    gattc_cmp_evt);

        evt->status = PRF_ERR_OK;

        // Send the message
        ke_msg_send(evt);
    }
}
예제 #11
0
/*
 ****************************************************************************************
 * @brief Gatt Read Characteristic request. *//**
 *
 * @param[in] req_type      GATT request type:
 * - GATT_READ_CHAR
 * - GATT_READ_BY_UUID_CHAR
 * - GATT_READ_LONG_CHAR
 * - GATT_READ_MULT_LONG_CHAR
 * - GATT_READ_DESC
 * - GATT_READ_LONG_DESC
 * @param[in] conhdl        Connection handle.
 * @param[in] valhdl        Value handle.
 * @response  GATT_READ_CHAR_RESP or GATT_READ_CHAR_MULTI_RESP
 * @description
 *
 *  This API is used by the application to send a GATT_READ_CHAR_REQ mssage.
 *  Upon reception of this message, GATT will checks whether the parameters are correct,
 *  if not correct then the GATT_CMP_EVT message with error code GATT_INVALID_PARAM_ERR 
 *  will be generically built and sent to Application directly. If parameter is correct,
 *  the GATT_READ_CHAR_RESP message will be received.
 *
 ****************************************************************************************
 */
void app_gatt_read_char_req(uint8_t req_type, uint16_t conhdl, uint16_t valhdl)
{
    struct gatt_read_char_req *msg = KE_MSG_ALLOC(GATT_READ_CHAR_REQ, TASK_GATT, TASK_APP,
                                                  gatt_read_char_req);

    //Connection handle
    msg->conhdl = conhdl;
    //GATT request type
    msg->req_type = req_type;
    //Read offset
    msg->offset = 0;
    //Start handle range
    msg->start_hdl = 0x0001;
    //End handle range
    msg->end_hdl = GATT_MAX_ATTR_HDL;
    //Number of UUID
    msg->nb_uuid = 0x01;
    //Handle of char value
    msg->uuid[0].expect_resp_size = ATT_UUID_16_LEN;
    msg->uuid[0].value_size = ATT_UUID_16_LEN;
    co_write16p(&msg->uuid[0].value[0], valhdl);

    ke_msg_send(msg);
}
예제 #12
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref SCPPC_ENABLE_REQ message.
 * The handler enables the Scan Parameters Profile Client Role.
 * @param[in] msgid Id of the message received (probably unused).
 * @param[in] param Pointer to the parameters of the message.
 * @param[in] dest_id ID of the receiving task instance (probably unused).
 * @param[in] src_id ID of the sending task instance.
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
static int scppc_enable_req_handler(ke_msg_id_t const msgid,
                                   struct scppc_enable_req const *param,
                                   ke_task_id_t const dest_id,
                                   ke_task_id_t const src_id)
{
    // Status
    uint8_t status;
    // Scan Parameters Profile Client Role Task Environment
    struct scppc_env_tag *scppc_env;
    // Connection Information
    struct prf_con_info con_info;

    // Fill the Connection Information structure
    con_info.conidx = gapc_get_conidx(param->conhdl);
    con_info.prf_id = dest_id;
    con_info.appid  = src_id;

    // Add an environment for the provided device
    status = PRF_CLIENT_ENABLE(con_info, param, scppc);

    if (status == PRF_ERR_FEATURE_NOT_SUPPORTED)
    {
        // The message has been forwarded to another task id.
        return (KE_MSG_NO_FREE);
    }
    else if (status == PRF_ERR_OK)
    {
        scppc_env = PRF_CLIENT_GET_ENV(dest_id, scppc);

        // Save Scan Interval Window value
        memcpy(&scppc_env->scan_intv_wd, &param->scan_intv_wd, sizeof(struct scan_intv_wd));

        // Config connection, start discovering
        if(param->con_type == PRF_CON_DISCOVERY)
        {
            //start discovering SCPS on peer
            prf_disc_svc_send(&(scppc_env->con_info), ATT_SVC_SCAN_PARAMETERS);

            scppc_env->last_uuid_req = ATT_SVC_SCAN_PARAMETERS;

            // Go to DISCOVERING state
            ke_state_set(dest_id, SCPPC_DISCOVERING);
        }
        // Normal connection, get saved att details
        else
        {
            scppc_env->scps = param->scps;

            if (scppc_env->scps.chars[SCPPC_CHAR_SCAN_REFRESH].char_hdl != ATT_INVALID_HANDLE)
            {
                /* If connected to a bonded Scan Server, the Scan Client shall enable notifications of the
                 * Scan Refresh characteristic using the Client Characteristic Configuration descriptor.
                 */
                struct scppc_scan_refresh_ntf_cfg_req *req = KE_MSG_ALLOC(SCPPC_SCAN_REFRESH_NTF_CFG_REQ,
                                                                          dest_id, dest_id,
                                                                          scppc_scan_refresh_ntf_cfg_req);

                req->conhdl    = gapc_get_conhdl(scppc_env->con_info.conidx);
                req->ntf_cfg    = PRF_CLI_START_NTF;

                // send the message
                ke_msg_send(req);
            }
            else
            {
                // Write Scan Interval Windows value
                struct scppc_scan_intv_wd_wr_req * req = KE_MSG_ALLOC(SCPPC_SCAN_INTV_WD_WR_REQ,
                                                                      dest_id, dest_id,
                                                                      scppc_scan_intv_wd_wr_req);

                req->conhdl = gapc_get_conhdl(scppc_env->con_info.conidx);

                co_write16p(&req->scan_intv_wd.le_scan_intv, scppc_env->scan_intv_wd.le_scan_intv);
                co_write16p(&req->scan_intv_wd.le_scan_window, scppc_env->scan_intv_wd.le_scan_window);

                ke_msg_send(req);
            }


            scppc_enable_cfm_send(scppc_env, &con_info, PRF_ERR_OK);
        }
    }
    else
    {
        // An error has been raised during the process, scps is NULL and won't be handled
        scppc_enable_cfm_send(NULL, &con_info, status);
    }

    return (KE_MSG_CONSUMED);
}
예제 #13
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GATTC_CMP_EVT message.
 * This generic event is received for different requests, so need to keep track.
 * @param[in] msgid Id of the message received (probably unused).
 * @param[in] param Pointer to the parameters of the message.
 * @param[in] dest_id ID of the receiving task instance (probably unused).
 * @param[in] src_id ID of the sending task instance.
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
static int gattc_cmp_evt_handler(ke_msg_id_t const msgid, struct gattc_cmp_evt const *param,
                                ke_task_id_t const dest_id, ke_task_id_t const src_id)
{
    uint8_t state = ke_state_get(dest_id);
    // Get the address of the environment
    struct scppc_env_tag *scppc_env = PRF_CLIENT_GET_ENV(dest_id, scppc);
    uint8_t status = PRF_ERR_OK;

    if(state == SCPPC_DISCOVERING)
    {
        if ((param->status == ATT_ERR_ATTRIBUTE_NOT_FOUND) ||
                (param->status == ATT_ERR_NO_ERROR))
        {
            // Service start/end handles has been received
            if(scppc_env->last_uuid_req == ATT_SVC_SCAN_PARAMETERS)
            {
                // check if service handles are not ok
                if(scppc_env->scps.svc.shdl== ATT_INVALID_HANDLE)
                {
                    // stop discovery procedure.
                    scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, PRF_ERR_STOP_DISC_CHAR_MISSING);
                }
                // Too many services found only one such service should exist
                else if(scppc_env->nb_svc > 1)
                {
                    scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, PRF_ERR_MULTIPLE_SVC);
                }
                else
                {
                    // Discover all SCPS characteristics
                    prf_disc_char_all_send(&(scppc_env->con_info), &(scppc_env->scps.svc));
                    scppc_env->last_uuid_req = ATT_DECL_CHARACTERISTIC;
                }
            }
            else if(scppc_env->last_uuid_req == ATT_DECL_CHARACTERISTIC)
            {
                status = prf_check_svc_char_validity(SCPPC_CHAR_MAX, scppc_env->scps.chars,
                        scppc_scps_char);

                if(status == PRF_ERR_OK)
                {
                    //If Scan Refresh Char. is present, discover its descriptor
                    if (scppc_env->scps.chars[SCPPC_CHAR_SCAN_REFRESH].char_hdl != ATT_INVALID_HANDLE)
                    {
                        scppc_env->last_uuid_req = ATT_INVALID_HANDLE;
                        scppc_env->last_char_code = scppc_scps_char_desc[SCPPC_DESC_SCAN_REFRESH_CFG].char_code;

                        // Discover Scan Refresh Char. Descriptor - Mandatory
                        prf_disc_char_desc_send(&(scppc_env->con_info),
                                &(scppc_env->scps.chars[scppc_env->last_char_code]));
                    }
                    else
                    {
                        scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, status);
                    }
                }
                else
                {
                    // Stop discovery procedure.
                    scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, status);
                }
            }
            else
            {
                status = prf_check_svc_char_desc_validity(SCPPC_DESC_MAX,
                        scppc_env->scps.descs,
                        scppc_scps_char_desc,
                        scppc_env->scps.chars);

                scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, status);
            }

            if (status == PRF_ERR_OK)
            {
                // Write Scan Interval Windows value
                struct scppc_scan_intv_wd_wr_req * req = KE_MSG_ALLOC(SCPPC_SCAN_INTV_WD_WR_REQ,
                        dest_id, dest_id,
                        scppc_scan_intv_wd_wr_req);

                req->conhdl = gapc_get_conhdl(scppc_env->con_info.conidx);

                co_write16p(&req->scan_intv_wd.le_scan_intv, scppc_env->scan_intv_wd.le_scan_intv);
                co_write16p(&req->scan_intv_wd.le_scan_window, scppc_env->scan_intv_wd.le_scan_window);

                ke_msg_send(req);
            }
        }
    }
    else if (state == SCPPC_CONNECTED)
    {
        switch(param->req_type)
        {
            case GATTC_WRITE:
            {
                struct scppc_wr_char_rsp *wr_cfm = KE_MSG_ALLOC(SCPPC_WR_CHAR_RSP,
                        scppc_env->con_info.appid, dest_id,
                        scppc_wr_char_rsp);

                wr_cfm->conhdl    = gapc_get_conhdl(scppc_env->con_info.conidx);
                //it will be a GATT status code
                wr_cfm->status    = param->status;

                // send the message
                ke_msg_send(wr_cfm);
            }
            break;

            case GATTC_READ:
            {
                if(param->status != GATT_ERR_NO_ERROR)
                {
                    // an error occurs while reading peer device attribute
                    scppc_error_ind_send(scppc_env, param->status);
                }
            }
            break;
            default: break;
        }
    }
    return (KE_MSG_CONSUMED);
}
예제 #14
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GATT_READ_CHAR_RESP message.
 * @param[in] msgid Id of the message received.
 * @param[in] param Pointer to the parameters of the message.
 * @param[in] dest_id ID of the receiving task instance.
 * @param[in] src_id ID of the sending task instance.
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
static int gatt_rd_char_rsp_handler(ke_msg_id_t const msgid,
                                    struct gatt_read_char_resp const *param,
                                    ke_task_id_t const dest_id,
                                    ke_task_id_t const src_id)
{
    // Get the address of the environment
    struct cscpc_env_tag *cscpc_env = PRF_CLIENT_GET_ENV(dest_id, cscpc);

    if (cscpc_env != NULL)
    {
        ASSERT_ERR(cscpc_env->operation != NULL);
        ASSERT_ERR(((struct cscpc_cmd *)cscpc_env->operation)->operation == CSCPC_READ_OP_CODE);

        if (param->status == GATT_NO_ERROR)
        {
            // Send the read value to the HL
            struct cscpc_value_ind *ind = KE_MSG_ALLOC(CSCPC_VALUE_IND,
                                                       cscpc_env->con_info.appid,
                                                       cscpc_env->con_info.prf_id,
                                                       cscpc_value_ind);

            ind->conhdl   = cscpc_env->con_info.conhdl;

            switch (((struct cscpc_read_cmd *)cscpc_env->operation)->read_code)
            {
                // Read CSC Feature Characteristic value
                case (CSCPC_RD_CSC_FEAT):
                {
                    co_write16p(&ind->value.sensor_feat, param->data.data[0]);

                    // Mask the reserved bits
                    ind->value.sensor_feat &= CSCP_FEAT_ALL_SUPP;
                } break;

                // Read Sensor Location Characteristic value
                case (CSCPC_RD_SENSOR_LOC):
                {
                    ind->value.sensor_loc = (param->data.data[0] < CSCP_LOC_MAX) ? param->data.data[0] : CSCP_LOC_OTHER;
                } break;

                // Read Client Characteristic Configuration Descriptor value
                case (CSCPC_RD_WR_CSC_MEAS_CFG):
                case (CSCPC_RD_WR_SC_CTNL_PT_CFG):
                {
                    co_write16p(&ind->value.ntf_cfg, param->data.data[0]);
                } break;

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

            ind->att_code = ((struct cscpc_read_cmd *)cscpc_env->operation)->read_code;

            // Send the message to the application
            ke_msg_send(ind);
        }

        // Send a complete event status to the application
        cscpc_send_cmp_evt(cscpc_env, CSCPC_READ_OP_CODE, param->status);
    }
    // else drop the message

    return (KE_MSG_CONSUMED);
}
예제 #15
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GATT_CMP_EVT message.
 * This generic event is received for different requests, so need to keep track.
 * @param[in] msgid Id of the message received (probably unused).
 * @param[in] param Pointer to the parameters of the message.
 * @param[in] dest_id ID of the receiving task instance (probably unused).
 * @param[in] src_id ID of the sending task instance.
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
static int gatt_cmp_evt_handler(ke_msg_id_t const msgid,
                                struct gatt_cmp_evt const *param,
                                ke_task_id_t const dest_id,
                                ke_task_id_t const src_id)
{
    // Get the address of the environment
    struct scppc_env_tag *scppc_env = PRF_CLIENT_GET_ENV(dest_id, scppc);

    uint8_t status = PRF_ERR_OK;

    if ((param->status == ATT_ERR_ATTRIBUTE_NOT_FOUND) ||
        (param->status == ATT_ERR_NO_ERROR))
    {
        // Service start/end handles has been received
        if(scppc_env->last_uuid_req == ATT_SVC_SCAN_PARAMETERS)
        {
            // check if service handles are not ok
            if(scppc_env->scps.svc.shdl== ATT_INVALID_HANDLE)
            {
                // stop discovery procedure.
                scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, PRF_ERR_STOP_DISC_CHAR_MISSING);
            }
            // Too many services found only one such service should exist
            else if(scppc_env->nb_svc > 1)
            {
                scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, PRF_ERR_MULTIPLE_SVC);
            }
            else
            {
                // Discover all SCPS characteristics
                prf_disc_char_all_send(&(scppc_env->con_info), &(scppc_env->scps.svc));
                scppc_env->last_uuid_req = ATT_DECL_CHARACTERISTIC;
            }
        }
        else if(scppc_env->last_uuid_req == ATT_DECL_CHARACTERISTIC)
        {
            status = prf_check_svc_char_validity(SCPPC_CHAR_MAX, scppc_env->scps.chars,
                                                 scppc_scps_char);

            if(status == PRF_ERR_OK)
            {
                //If Scan Refresh Char. is present, discover its descriptor
                if (scppc_env->scps.chars[SCPPC_CHAR_SCAN_REFRESH].char_hdl != ATT_INVALID_HANDLE)
                {
                    scppc_env->last_uuid_req = ATT_INVALID_HANDLE;
                    scppc_env->last_char_code = scppc_scps_char_desc[SCPPC_DESC_SCAN_REFRESH_CFG].char_code;

                    // Discover Scan Refresh Char. Descriptor - Mandatory
                    prf_disc_char_desc_send(&(scppc_env->con_info),
                                            &(scppc_env->scps.chars[scppc_env->last_char_code]));
                }
                else
                {
                    scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, status);
                }
            }
            else
            {
                // Stop discovery procedure.
                scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, status);
            }
        }
        else
        {
            status = prf_check_svc_char_desc_validity(SCPPC_DESC_MAX,
                                                      scppc_env->scps.descs,
                                                      scppc_scps_char_desc,
                                                      scppc_env->scps.chars);

            scppc_enable_cfm_send(scppc_env, &scppc_env->con_info, status);
        }

        if (status == PRF_ERR_OK)
        {
            // Write Scan Interval Windows value
            struct scppc_scan_intv_wd_wr_req * req = KE_MSG_ALLOC(SCPPC_SCAN_INTV_WD_WR_REQ,
                                                                  dest_id, dest_id,
                                                                  scppc_scan_intv_wd_wr_req);

            req->conhdl = scppc_env->con_info.conhdl;

            co_write16p(&req->scan_intv_wd.le_scan_intv, scppc_env->scan_intv_wd.le_scan_intv);
            co_write16p(&req->scan_intv_wd.le_scan_window, scppc_env->scan_intv_wd.le_scan_window);

            ke_msg_send(req);
        }
    }

    return (KE_MSG_CONSUMED);
}
예제 #16
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref GL2C_CODE_ATT_WR_CMD_IND message.
 * @param[in] msgid Id of the message received (probably unused).
 * @param[in] param Pointer to the parameters of the message.
 * @param[in] dest_id ID of the receiving task instance (probably unused).
 * @param[in] src_id ID of the sending task instance.
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
static int gattc_write_cmd_ind_handler(ke_msg_id_t const msgid,
                                      struct gattc_write_cmd_ind const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{
    // Counter
    uint8_t i;
    // Status
    uint8_t status = PRF_APP_ERROR;
    // Written value
    uint16_t ntf_cfg;

    // Look for the BAS instance
    for (i = 0; ((i < bass_env.bas_nb) && (status == PRF_APP_ERROR)); i++)
    {
        if (param->handle == bass_env.shdl[i] + BAS_IDX_BATT_LVL_NTF_CFG)
        {
            // Go out of the loop
            status = PRF_ERR_OK;
        }
    }

    //Revert Last incrementation
    i--;

    // If the attribute has been found, status is PRF_ERR_OK
    if (status == PRF_ERR_OK)
    {
        // Extract value before check
        ntf_cfg = co_read16p(&param->value[0]);

        // Only update configuration if value for stop or notification enable
        if ((ntf_cfg == PRF_CLI_STOP_NTFIND) || (ntf_cfg == PRF_CLI_START_NTF))
        {
            // Set NTF Cfg value in the DB
            attmdb_att_set_value(bass_env.shdl[i] + BAS_IDX_BATT_LVL_NTF_CFG, sizeof(uint16_t),
                                 (uint8_t *)&ntf_cfg);

            // Conserve information in environment
            if (ntf_cfg == PRF_CLI_START_NTF)
            {
                // Ntf cfg bit set to 1
                bass_env.features[i] |= BASS_FLAG_NTF_CFG_BIT;
            }
            else
            {
                // Ntf cfg bit set to 0
                bass_env.features[i] &= ~BASS_FLAG_NTF_CFG_BIT;
            }
            if(param->last)
            {
                // Inform APP of configuration change
                struct bass_batt_level_ntf_cfg_ind * ind = KE_MSG_ALLOC(BASS_BATT_LEVEL_NTF_CFG_IND,
                                                                        bass_env.con_info.appid, TASK_BASS,
                                                                        bass_batt_level_ntf_cfg_ind);
                ind->conhdl = gapc_get_conhdl(bass_env.con_info.conidx);
                co_write16p(&ind->ntf_cfg, ntf_cfg);
                ind->bas_instance = i;

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

        // Send write response
        atts_write_rsp_send(bass_env.con_info.conidx, param->handle, status);
    }

    return (KE_MSG_CONSUMED);
}