Ejemplo n.º 1
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 == scppc_env->con_info.conhdl)
    {
       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), GATT_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);
}
Ejemplo n.º 2
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref HOGPBH_BOOT_KB_OUT_REPORT_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 hogpbh_boot_report_wr_req_handler(ke_msg_id_t const msgid,
                                                  struct hogpbh_boot_report_wr_req const *param,
                                                  ke_task_id_t const dest_id,
                                                  ke_task_id_t const src_id)
{
    // Descriptor handle
    uint16_t val_hdl = ATT_INVALID_SEARCH_HANDLE;
    // Status
    uint8_t status = PRF_ERR_OK;
    // Write Type
    uint8_t wr_type = GATT_WRITE_CHAR;
    // Get the address of the environment
    struct hogpbh_env_tag *hogpbh_env = PRF_CLIENT_GET_ENV(dest_id, hogpbh);

    // Save the Characteristic Code
    hogpbh_env->last_char_code = param->char_code;

    // Check Connection Handle and HIDS Instance Nb
    if((param->conhdl == hogpbh_env->con_info.conhdl) &&
       (param->hids_nb < hogpbh_env->hids_nb) &&
       (param->report_length <= HOGPBH_BOOT_REPORT_MAX_LEN))
    {
        switch (param->char_code)
        {
            case (HOGPBH_CHAR_BOOT_KB_OUT_REPORT):

                // Write Without Response is available for the Boot Keyboard Ouput Report
                if (param->wr_type == GATT_WRITE_NO_RESPONSE)
                {
                    wr_type = param->wr_type;
                }

                break;

            case (HOGPBH_CHAR_BOOT_KB_IN_REPORT):
            case (HOGPBH_CHAR_BOOT_MOUSE_IN_REPORT):

                // Check if the characteristic is writable
                if ((hogpbh_env->hids[param->hids_nb].chars[param->char_code].prop & ATT_CHAR_PROP_WR)
                                                                                  != ATT_CHAR_PROP_WR)
                {
                    status = PRF_ERR_NOT_WRITABLE;
                }

                break;

            default:
                status = PRF_ERR_INVALID_PARAM;
                break;
        }

        if (status == PRF_ERR_OK)
        {
            val_hdl = hogpbh_env->hids[param->hids_nb].chars[param->char_code].val_hdl;

            // Check if the handle value exists
            if (val_hdl != ATT_INVALID_SEARCH_HANDLE)
            {
                prf_gatt_write(&hogpbh_env->con_info, val_hdl, (uint8_t *)&param->report[0],
                               param->report_length, wr_type);
            }
            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_WR_CHAR_RSP, status);
    }

    return (KE_MSG_CONSUMED);
}
Ejemplo n.º 3
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref CSCPC_CFG_NTFIND_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_ctnl_pt_cfg_cmd_handler(ke_msg_id_t const msgid,
                                         struct cscpc_ctnl_pt_cfg_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)
    {
        // Status
        uint8_t status     = PRF_ERR_OK;

        do
        {
            // State is Connected or Busy
            ASSERT_ERR(ke_state_get(dest_id) > CSCPC_IDLE);

            // Check the provided connection handle
            if (param->conhdl != cscpc_env->con_info.conhdl)
            {
                status = PRF_ERR_INVALID_PARAM;
                break;
            }

            if (ke_state_get(dest_id) == CSCPC_BUSY)
            {
                // Another procedure is pending, keep the command for later
                msg_status = KE_MSG_SAVED;
                // Status is PRF_ERR_OK, no message will be sent to the application
                break;
            }

            // Check if the characteristic has been found
            if (cscpc_env->cscs.descs[CSCPC_DESC_SC_CTNL_PT_CL_CFG].desc_hdl != ATT_INVALID_SEARCH_HANDLE)
            {
                // Packed request
                uint8_t req[CSCP_SC_CNTL_PT_REQ_MAX_LEN];
                // Request Length
                uint8_t req_len = CSCP_SC_CNTL_PT_REQ_MIN_LEN;

                // Set the operation code
                req[0] = param->sc_ctnl_pt.op_code;

                // Fulfill the message according to the operation code
                switch (param->sc_ctnl_pt.op_code)
                {
                    case (CSCP_CTNL_PT_OP_SET_CUMUL_VAL):
                    {
                        // Set the cumulative value
                        co_write32p(&req[1], param->sc_ctnl_pt.value.cumul_val);
                        // Update length
                        req_len += 4;
                    } break;

                    case (CSCP_CTNL_PT_OP_UPD_LOC):
                    {
                        // Set the sensor location
                        req[1] = param->sc_ctnl_pt.value.sensor_loc;
                        // Update length
                        req_len++;
                    } break;

                    case (CSCP_CTNL_PT_OP_RESERVED):
                    case (CSCP_CTNL_PT_OP_START_CALIB):
                    case (CSCP_CTNL_PT_OP_REQ_SUPP_LOC):
                    {
                        // Nothing more to do
                    } break;

                    default:
                    {
                        status = PRF_ERR_INVALID_PARAM;
                    } break;
                }

                if (status == PRF_ERR_OK)
                {
                    // Set the operation code
                    param->operation = CSCPC_CTNL_PT_CFG_WR_OP_CODE;

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

                    // Go to the Busy state
                    ke_state_set(dest_id, CSCPC_BUSY);

                    // Send the write request
                    prf_gatt_write(&(cscpc_env->con_info), cscpc_env->cscs.chars[CSCP_CSCS_SC_CTNL_PT_CHAR].val_hdl,
                                   (uint8_t *)&req[0], req_len, GATT_WRITE_CHAR);
                }
            }
            else
            {
                status = PRF_ERR_INEXISTENT_HDL;
            }
        } while (0);

        if (status != PRF_ERR_OK)
        {
            // Send a complete event status to the application
            cscpc_send_cmp_evt(cscpc_env, CSCPC_CTNL_PT_CFG_WR_OP_CODE, status);
        }
    }
    else
    {
        // No connection
        cscpc_send_no_conn_cmp_evt(dest_id, src_id, param->conhdl, CSCPC_CTNL_PT_CFG_WR_OP_CODE);
    }

    return (int)msg_status;
}
Ejemplo n.º 4
0
/**
 ****************************************************************************************
 * @brief Handles reception of the @ref ANPC_WRITE_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_write_cmd_handler(ke_msg_id_t const msgid,
                                   struct anpc_write_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)
    {
        // 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)
            {
                msg_status = KE_MSG_SAVED;
            }
            else    // state = ANPC_CONNECTED
            {
                // Attribute handle
                uint16_t handle    = ATT_INVALID_SEARCH_HANDLE;
                // Length
                uint8_t length;

                ASSERT_ERR(anpc_env->operation == NULL);

                switch (param->write_code)
                {
                    // Write Alert Notification Control Point Characteristic Value
                    case (ANPC_WR_ALERT_NTF_CTNL_PT):
                    {
                        // Check the Category ID and the Command ID
                        if ((param->value.ctnl_pt.cmd_id < CMD_ID_NB) &&
                            ((param->value.ctnl_pt.cat_id < CAT_ID_NB) || (param->value.ctnl_pt.cat_id == CAT_ID_ALL_SUPPORTED_CAT)))
                        {
                            handle  = anpc_env->ans.chars[ANPC_CHAR_ALERT_NTF_CTNL_PT].val_hdl;
                            length  = sizeof(struct anp_ctnl_pt);
                        }
                        else
                        {
                            status = PRF_ERR_INVALID_PARAM;
                        }
                    } break;

                    // Write New Alert Characteristic Client Char. Cfg. Descriptor Value
                    case (ANPC_RD_WR_NEW_ALERT_CFG):
                    {
                        if (param->value.new_alert_ntf_cfg <= PRF_CLI_START_NTF)
                        {
                            handle  = anpc_env->ans.descs[ANPC_DESC_NEW_ALERT_CL_CFG].desc_hdl;
                            length  = sizeof(uint16_t);
                        }
                        else
                        {
                            status = PRF_ERR_INVALID_PARAM;
                        }
                    } break;

                    // Write Unread Alert Status Characteristic Client Char. Cfg. Descriptor Value
                    case (ANPC_RD_WR_UNREAD_ALERT_STATUS_CFG):
                    {
                        if (param->value.unread_alert_status_ntf_cfg <= PRF_CLI_START_NTF)
                        {
                            handle  = anpc_env->ans.descs[ANPC_DESC_UNREAD_ALERT_STATUS_CL_CFG].desc_hdl;
                            length  = sizeof(uint16_t);
                        }
                        else
                        {
                            status = PRF_ERR_INVALID_PARAM;
                        }
                    } break;

                    default:
                    {
                        status = PRF_ERR_INVALID_PARAM;
                    } break;
                }

                if (status == PRF_ERR_OK)
                {
                    // Check if handle is viable
                    if (handle != ATT_INVALID_SEARCH_HANDLE)
                    {
                        // Send the write request
                        prf_gatt_write(&(anpc_env->con_info), handle,
                                       (uint8_t *)&param->value, length, GATTC_WRITE);

                        // Force the operation value
                        param->operation      = ANPC_WRITE_OP_CODE;
                        // Store the command structure
                        anpc_env->operation   = param;

                        msg_status = KE_MSG_NO_FREE;

                        // 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_WRITE_OP_CODE, status);
        }
    }
    else
    {
        anpc_send_no_conn_cmp_evt(dest_id, src_id, param->conhdl, ANPC_WRITE_OP_CODE);
    }

    return (int)msg_status;
}