Пример #1
0
/**
 ****************************************************************************************
 * @brief Handles GAPC command completion events.
 *
 * @param[in] msgid     Id of the message received.
 * @param[in] param     Pointer to the parameters of the message.
 * @param[in] dest_id   ID of the receiving task instance (TASK_GAP).
 * @param[in] src_id    ID of the sending task instance.
 *
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
int gapc_cmp_evt_handler(ke_msg_id_t msgid,
                         struct gapc_cmp_evt *param,
                         ke_task_id_t dest_id,
                         ke_task_id_t src_id)
{
    switch (param->operation)
    {
        case GAPC_ENCRYPT:
            if (param->status != CO_ERROR_NO_ERROR)
            {
                app_env.peer_device.bonded = 0;
                app_disconnect();
            }
            break;
        
        case GAPC_DISCONNECT:
            if (app_env.state == APP_DISCONNECTING)
            {
                printf("app_exit() after GAPC_DISCONNECT_CMD completion\n");
                app_exit();
            }

        default:
            break;
    }

    return 0;
}
Пример #2
0
/**
 ****************************************************************************************
 * @brief Handle Bond indication.
 *
 * @param[in] msgid     Id of the message received.
 * @param[in] param     Pointer to the parameters of the message.
 * @param[in] dest_id   ID of the receiving task instance (TASK_GAP).
 * @param[in] src_id    ID of the sending task instance.
 *
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
int gap_bond_ind_handler(ke_msg_id_t msgid,
                         struct gapc_bond_ind *param,
                         ke_task_id_t dest_id,
                         ke_task_id_t src_id)
{
    switch (param->info)
    {
        case GAPC_PAIRING_SUCCEED:
            if (param->data.auth | GAP_AUTH_BOND)
                app_env.peer_device.bonded = 1;
            
            // discover spota service
            app_env.peer_device.spota.svc_found = 0;
            app_env.peer_device.spota.svc_start_handle = 0;
            app_env.peer_device.spota.svc_end_handle = 0;
            app_env.peer_device.spota.mem_dev_handle = 0;
            app_env.peer_device.spota.gpio_map_handle = 0;
            app_env.peer_device.spota.mem_info_handle = 0;
            app_env.peer_device.spota.patch_len_handle = 0;
            app_env.peer_device.spota.patch_data_handle = 0;
            app_env.peer_device.spota.serv_status_handle = 0;
            app_env.peer_device.spota.serv_status_cli_char_cfg_desc_handle = 0;            

            app_discover_svc_by_uuid_16(app_env.peer_device.device.conidx, SPOTA_PRIMARY_SERVICE_UUID);

            break;

        case GAPC_IRK_EXCH:
            memcpy (app_env.peer_device.irk.irk.key, param->data.irk.irk.key, KEY_LEN);
            memcpy (app_env.peer_device.irk.addr.addr.addr, param->data.irk.addr.addr.addr, KEY_LEN);
            app_env.peer_device.irk.addr.addr_type = param->data.irk.addr.addr_type;
            break;

        case GAPC_LTK_EXCH:
            app_env.peer_device.ediv = param->data.ltk.ediv;
            memcpy (app_env.peer_device.rand_nb, param->data.ltk.randnb.nb, RAND_NB_LEN);
            app_env.peer_device.ltk.key_size = param->data.ltk.key_size;
            memcpy (app_env.peer_device.ltk.ltk.key, param->data.ltk.ltk.key, param->data.ltk.key_size);
            app_env.peer_device.ltk.ediv = param->data.ltk.ediv;
            memcpy (app_env.peer_device.ltk.randnb.nb, param->data.ltk.randnb.nb, RAND_NB_LEN);
            break;

        case GAPC_PAIRING_FAILED:
            printf("Pairing failed. Aborting...\n");
            app_env.peer_device.bonded = 0;
            app_disconnect();
            break;
    }

    return 0;
}
Пример #3
0
int streamdatah_enable_cfm_handler(ke_msg_id_t const msgid,
                                      struct streamdatah_enable_cfm const *param,
                                      ke_task_id_t const dest_id,
                                      ke_task_id_t const src_id)
{	

    if (param->status != PRF_ERR_OK)
        app_disconnect();
    
    
    min_hdl = param->streamdatah.chars[STREAMDATAH_D0_CHAR].val_hdl; 
    max_hdl = param->streamdatah.chars[STREAMDATAH_D9_CHAR].val_hdl;
    
    return (KE_MSG_CONSUMED);
}
Пример #4
0
/**
 ****************************************************************************************
 * @brief Handles reception of encrypt request command
 *
 * @param[in] msgid     Id of the message received.
 * @param[in] param     Pointer to the parameters of the message.
 * @param[in] dest_id   ID of the receiving task instance (TASK_GAP).
 * @param[in] src_id    ID of the sending task instance.
 *
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
int gapc_encrypt_req_ind_handler(ke_msg_id_t const msgid,
        struct gapc_encrypt_req_ind *param,
        ke_task_id_t const dest_id,
        ke_task_id_t const src_id)
{
    struct gapc_encrypt_cfm* cfm = KE_MSG_ALLOC(GAPC_ENCRYPT_CFM, src_id, dest_id, gapc_encrypt_cfm);
    
    if (!app_validate_encrypt_req_func(param))
    {
        cfm->found = false;
    }
    else
    {
        if(((app_sec_env.auth & GAP_AUTH_BOND) != 0)
            && (memcmp(&(app_sec_env.rand_nb), &(param->rand_nb), RAND_NB_LEN) == 0)
            && (app_sec_env.ediv == param->ediv))
        {
            cfm->found = true;
            cfm->key_size = app_sec_env.key_size;
            memcpy(&(cfm->ltk), &(app_sec_env.ltk), KEY_LEN);
            // update connection auth
            app_connect_confirm(app_sec_env.auth);
            app_sec_encrypt_complete_func();
        }
        else
        {
            cfm->found = false;
        }
    }
    
    ke_msg_send(cfm);
    
    if (cfm->found == false)
        app_disconnect();

    return (KE_MSG_CONSUMED);
}
Пример #5
0
/**
 ****************************************************************************************
 * @brief Handles reception of bond indication
 *
 * @param[in] msgid     Id of the message received.
 * @param[in] param     Pointer to the parameters of the message.
 * @param[in] dest_id   ID of the receiving task instance (TASK_GAP).
 * @param[in] src_id    ID of the sending task instance.
 *
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
int gapc_bond_ind_handler(ke_msg_id_t const msgid,
        struct gapc_bond_ind *param,
        ke_task_id_t const dest_id,
        ke_task_id_t const src_id)
{
    
    switch(param->info)
    {
        // Bond Pairing request
        case GAPC_PAIRING_SUCCEED:
        {
            // Save Authentication level
            app_sec_env.auth =  param->data.auth;

            if (app_sec_env.auth & GAP_AUTH_BOND)
            {
                app_sec_env.peer_addr_type = app_env.peer_addr_type;
                           
                memcpy(app_sec_env.peer_addr.addr, app_env.peer_addr.addr, BD_ADDR_LEN);
            }
            app_paired_func();
        }
        break;


        case GAPC_PAIRING_FAILED:
        {
            // disconnect
            app_disconnect();

            // clear bond data.
            app_sec_env.auth = 0;
        }
        break;


        case (GAPC_LTK_EXCH):
        {
            // app_store_ltk_func();
        } 
        break;

        
        case (GAPC_IRK_EXCH):
        {
            // app_store_irk_func();
        } 
        break;

        
        case (GAPC_CSRK_EXCH):
        {
            // app_store_csrk_func();
        } 
        break;


        default:
        {
            ASSERT_ERR(0);
        }
        break;
    }
    return (KE_MSG_CONSUMED);
}
Пример #6
0
/**
 ****************************************************************************************
 * @brief Handles GATTC command completion event.
 *
 * @param[in] msgid     Id of the message received.
 * @param[in] param     Pointer to the parameters of the message.
 * @param[in] dest_id   ID of the receiving task instance (TASK_GAP).
 * @param[in] src_id    ID of the sending task instance.
 *
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
int gattc_cmp_evt_handler(ke_msg_id_t msgid,
                          struct gattc_cmp_evt *param,
                          ke_task_id_t dest_id,
                          ke_task_id_t src_id)
{
    switch(param->req_type)
    {

    case GATTC_DISC_BY_UUID_SVC:
        
        if(param->status != CO_ERROR_NO_ERROR && param->status != ATT_ERR_ATTRIBUTE_NOT_FOUND )
        {
            printf("Error while trying to discover SPOTA service by UUID (status = 0x%02X) \n", param->status);

            // disconnect
            app_env.state = APP_DISCONNECTING;
            app_disconnect();
        }
        else
        {
            if (app_env.peer_device.spota.svc_found != 1)
            {
                printf("Peer device does not support the SPOTA service \n");

                // disconnect
                app_env.state = APP_DISCONNECTING;
                app_disconnect();
            }
            else
            {
                // SPOTA service was discovered. Now discover SPOTA characteristics.
                app_discover_all_char( KE_IDX_GET(src_id), app_env.peer_device.spota.svc_start_handle, app_env.peer_device.spota.svc_end_handle);
            }
        };
        break;


    case GATTC_DISC_ALL_CHAR:

        if(param->status != CO_ERROR_NO_ERROR && param->status != ATT_ERR_ATTRIBUTE_NOT_FOUND )
        {
            printf("Error while trying to discover SPOTA service characteristics (status = 0x%02X) \n", param->status);

            // disconnect
            app_env.state = APP_DISCONNECTING;
            app_disconnect();
        }
        else if ( app_env.peer_device.spota.mem_dev_handle == 0 ||
                  app_env.peer_device.spota.gpio_map_handle == 0 ||
                  app_env.peer_device.spota.mem_info_handle == 0 ||
                  app_env.peer_device.spota.patch_len_handle == 0 ||
                  app_env.peer_device.spota.patch_data_handle == 0 || 
                  app_env.peer_device.spota.serv_status_handle == 0 )
        {
            printf("Error: Missing characteristics in peer device's SPOTA service.\n");

            // disconnect
            app_env.state = APP_DISCONNECTING;
            app_disconnect();
        }
        else
        {
            // trigger next step - discover SPOTA_SERV_STATUS Client char descriptor
            app_discover_char_desc(KE_IDX_GET(src_id), app_env.peer_device.spota.serv_status_handle, app_env.peer_device.spota.svc_end_handle);
        }
        break;


    case GATTC_DISC_DESC_CHAR:

        if(param->status != CO_ERROR_NO_ERROR && param->status != ATT_ERR_ATTRIBUTE_NOT_FOUND )
        {
            printf("Error while trying to discover SPOTA_SERV_STATUS characteristic descriptors (status = 0x%02X) \n", param->status);

            // disconnect
            app_env.state = APP_DISCONNECTING;
            app_disconnect();
        }
        else if ( app_env.peer_device.spota.serv_status_cli_char_cfg_desc_handle == 0 )
        {
            printf("Error: Missing Client Char. Conf. descriptor for SPOTA_SERV_STATUS characteristic.\n");

            // disconnect
            app_env.state = APP_DISCONNECTING;
            app_disconnect();
        }
        else
        {
            // trigger next step - enable SPOTA_SERV_STATUS notifications
            uint8_t v[2];

            app_env.state = APP_EN_SERV_STATUS_NOTIFICATIONS;
            
            v[1] = 0x00;
            v[0] = 0x01;
            app_characteristic_write(KE_IDX_GET(src_id), app_env.peer_device.spota.serv_status_cli_char_cfg_desc_handle, v, 2);
        }
        break;

            
    case GATTC_WRITE:
    case GATTC_WRITE_NO_RESPONSE:

        if(param->status != CO_ERROR_NO_ERROR) // write characteristic command failed
        {
            printf("error: failed to write a characteristic (status=0x%02X). Aborting... \n", param->status);
            // disconnect
            app_env.state = APP_DISCONNECTING;
            app_disconnect();
        }
        else if (app_env.state == APP_EN_SERV_STATUS_NOTIFICATIONS) // write to SPOTA_SERV_STATUS Client Char. Conf. descriptor completed successfully
        {            
            // trigger next step - write to SPOTA_MEM_DEV
            app_suota_write_mem_dev();
        }
        else if (app_env.state == APP_WR_MEM_DEV) // write SPOTA_MEM_DEV completed successfully
        {
            // nothing to do - wait for notification on SPOTA_SERV_STATUS
        }
        else if (app_env.state == APP_WR_GPIO_MAP) // write SPOTA_GPIO_MAP completed successfully 
        {            
            // trigger next step - read spota_mem_info operation
            app_env.state = APP_RD_MEM_INFO;
            app_characteristic_read(KE_IDX_GET(src_id), app_env.peer_device.spota.mem_info_handle);
        }
        else if (app_env.state == APP_WR_PATCH_LEN) // write SPOTA_PATCH_LEN completed successfully
        {
            // init 1st chunk of block
            patch_chunck_offset = 0; // offset in block
            patch_chunck_length = (block_length - patch_chunck_offset) > 20 ? 20: (block_length - patch_chunck_offset);

            //
            // trigger next step - write SPOTA_PATCH_DATA
            //
            app_suota_write_chunks();
        }
        else if (app_env.state == APP_WR_PATCH_DATA) // write SPOTA_PATCH_DATA completed successfully
        {
            // sanity check - should necer happen
            if (expected_write_completion_events_counter <= 0 )
            {
                printf("Fatal error. Unexpected write completion \n");
                // disconnect
                app_env.state = APP_DISCONNECTING;
                app_disconnect();
                return 0;
            }

            --expected_write_completion_events_counter; // decrement expected write completions
        }


    case GATTC_READ:
        
        if(param->status != CO_ERROR_NO_ERROR) // read characteristic command failed
        {
            printf("error: failed to read a characteristic. Aborting... \n");
            // disconnect
            app_env.state = APP_DISCONNECTING;
            app_disconnect();
        }

        else if (app_env.state == APP_RD_MEM_INFO) // read SPOTA_MEM_INFO completed  successfully
        {
            uint32_t mem_info = (app_env.peer_device.spota.mem_info_value[3] << 24) 
                              | (app_env.peer_device.spota.mem_info_value[2] << 16)
                              | (app_env.peer_device.spota.mem_info_value[1] << 8) 
                              | (app_env.peer_device.spota.mem_info_value[0])
                              ;

            printf("Memory Information: 0x%08X \n", mem_info);

            //
            // trigger next step - write SPOTA_PATCH_LEN of 1st block
            //

            // initialize block offset to point to the start of image
            block_offset = 0;
            block_length = (patch_length - block_offset) > suota_block_size 
                         ? suota_block_size
                         : (patch_length - block_offset);

            app_suota_write_patch_len(block_length);

            print_time();
        }

        else if (app_env.state == APP_RD_MEM_INFO_2) // read SPOTA_MEM_INFO completed successfully
        {
            uint32_t mem_info = (app_env.peer_device.spota.mem_info_value[3] << 24) 
                              | (app_env.peer_device.spota.mem_info_value[2] << 16)
                              | (app_env.peer_device.spota.mem_info_value[1] << 8) 
                              | (app_env.peer_device.spota.mem_info_value[0])
                              ;

            printf("Memory Information: 0x%08X \n", mem_info);
            
            //
            // trigger next step - send END OF SUOTA
            //
            app_suota_end();
        }

        break;

    default:
        break;
    }

    return 0;
}
Пример #7
0
/**
 ****************************************************************************************
 * @brief Handles GATTC_EVENT_IND event.
 *
 * @param[in] msgid     Id of the message received.
 * @param[in] param     Pointer to the parameters of the message.
 * @param[in] dest_id   ID of the receiving task instance (TASK_GAP).
 * @param[in] src_id    ID of the sending task instance.
 *
 * @return If the message was consumed or not.
 ****************************************************************************************
 */
int gattc_event_ind_handler(ke_msg_id_t msgid,
                            struct gattc_event_ind *param,
                            ke_task_id_t dest_id,
                            ke_task_id_t src_id)
{
    // handle notifications from SPOTA_SERV_STATUS only 
    if(param->handle != app_env.peer_device.spota.serv_status_handle)
    {
        return 0;
    }
    
    // retrieve notification value
    app_env.peer_device.spota.serv_status_value = param->value[0];

    if (app_env.state == APP_WR_MEM_DEV)
    {
        // check if write SPOTA_MEM_DEV completed successfully
        if (app_env.peer_device.spota.serv_status_value != SPOTA_STATUS_IMG_STARTED)
        {
                printf("error: SPOTA_SERV_STATUS = 0x%02X after writing to SPOTA_MEM_DEV\n", app_env.peer_device.spota.serv_status_value);
                // disconnect
                app_env.state = APP_DISCONNECTING;
                app_disconnect();
                return 0; // in order to exit this function immediately
        }

        // trigger next step - write SPOTA_GPIO_MAP
        app_suota_write_gpio_map();

    }
    else if (app_env.state == APP_WR_PATCH_DATA) // handle the notification only after the last chunk has been written
    {
        // check SPOTA_SERV_STATUS
        if (app_env.peer_device.spota.serv_status_value != SPOTA_STATUS_CMP_OK)
        {
            printf("Error: SPOTA_SERV_STATUS = 0x%02X after writing block \n", app_env.peer_device.spota.serv_status_value);
            // disconnect
            app_env.state = APP_DISCONNECTING;
            app_disconnect();
            return 0; // in order to exit this function immediately
        }

        if(is_last_block())
        {
            // no more blocks to write 

            // trigger next step - read SPOTA_MEM_INFO (the 2nd time)
            app_env.state = APP_RD_MEM_INFO_2;
            app_characteristic_read(KE_IDX_GET(src_id), app_env.peer_device.spota.mem_info_handle);
        }
        else
        {
            // advance to the next block

            next_block();

            if( is_last_block() ) // we may need a different block length for the last block
            {
                // trigger next step - write SPOTA_PATCH_LEN for last block
                app_suota_write_patch_len(block_length);
            }
            else
            {
                // trigger next step - start writing the block chunks
                app_suota_write_chunks();
            }
        }
    }

    else if (app_env.state == APP_WR_END_OF_SUOTA) // handle the notification after the end of SUOTA command has been issued
    {
        // check SPOTA_SERV_STATUS
        if (app_env.peer_device.spota.serv_status_value != SPOTA_STATUS_CMP_OK)
        {
            printf("error: SPOTA_SERV_STATUS = 0x%02X after sending END OF SUOTA \n", app_env.peer_device.spota.serv_status_value);
            // disconnect
            app_env.state = APP_DISCONNECTING;
            app_disconnect();
            return 0; // in order to exit this function immediately
        }

        // no more blocks to write - SUOTA procedure completed successfully
        printf("\nSUOTA procedure completed successfully \n\n");
            
        print_time();

        // send boot command - the receiver will reboot when it receives this command
        // the connection is expected to be lost
        {
            void app_suota_reboot(void);

            app_suota_reboot();
        }

        // trigger next step - disconnect
        app_env.state = APP_DISCONNECTING;
        app_disconnect();
    }
    else
    {
        // no handling of notifications in the rest of the states
        ///    printf(" SPOTA_SERV_STATUS = 0x%02X app_env.state = %d\n", app_env.peer_device.spota.serv_status_value, app_env.state );
    }

    return 0;
}