This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Update device information after DFU

Hi,

Recently, we were trying to support the HID device OTA function.

We have make an user control panel which could read the device FW version via driver which communicate to OS directly.

Thus, we would like to let the panel show modified FW version after the OTA is proceed in the system (PC).

Somehow, we just found that system could not read the version after OTA.

(The FW version is the character in Device Information UUID)

Not sure whether it need to ask system to proceed the discover again or there is an easy way?

If it still need to request the host to proceed the discover again, which API I should use in peripheral device?

And does it need to modified the bootloader to achieve the requirement? Hope there is no need to modified the bootloader.

I am looking forward to hearing any response.

Parents
  • Hi,

    My understanding is that you have a HID device that uses the Device Information Service, and that you change the product version when you update the firmware?  Is that correct? The DIS has a firmware revision string (BLE_UUID_FIRMWARE_REVISION_STRING_CHAR) which it makes sense to use. Then you populate this (ble_dis_init_t::fw_rev_str) when initializing the DIS and the only change you need is to change this number in every firmware release. There is no need to update the bootloader for this, assuming you only need this information when the application is active and not when in bootloader mode.

    I do not know when various operations systems read the DIS, but for the nRF point of view there sould not be any problem with this change, and it is just up to the central (client) to read this the FW revision string characteristic in order to check which firmware revision is in use.

Reply
  • Hi,

    My understanding is that you have a HID device that uses the Device Information Service, and that you change the product version when you update the firmware?  Is that correct? The DIS has a firmware revision string (BLE_UUID_FIRMWARE_REVISION_STRING_CHAR) which it makes sense to use. Then you populate this (ble_dis_init_t::fw_rev_str) when initializing the DIS and the only change you need is to change this number in every firmware release. There is no need to update the bootloader for this, assuming you only need this information when the application is active and not when in bootloader mode.

    I do not know when various operations systems read the DIS, but for the nRF point of view there sould not be any problem with this change, and it is just up to the central (client) to read this the FW revision string characteristic in order to check which firmware revision is in use.

Children
  • My understanding is that you have a HID device that uses the Device Information Service, and that you change the product version when you update the firmware?  Is that correct?

    Yes, your understanding is correct.

    The DIS has a firmware revision string (BLE_UUID_FIRMWARE_REVISION_STRING_CHAR) which it makes sense to use.

    Yes, I did change the FW version in this character when I upgrade to the new FW. Somehow, the information in system did not update the FW string. I assume that OS did not ask for it due to it did not know there is device proceed OTA already.

    I do not know when various operations systems read the DIS, but for the nRF point of view there sould not be any problem with this change, and it is just up to the central (client) to read this the FW revision string characteristic in order to check which firmware revision is in use.

    Is there a way for HID device active push the firmware revision string to the central?

    I was trying to make dis_init(); again when I press the button 1.

    /**@brief Function for initializing Device Information Service.
     */
    static void dis_init(void)
    {
    		NRF_LOG_INFO("Enter device initial \r\n");
    	
        ret_code_t       err_code;
        ble_dis_init_t   dis_init_obj;
        ble_dis_pnp_id_t pnp_id;
    
        pnp_id.vendor_id_source = PNP_ID_VENDOR_ID_SOURCE;
        pnp_id.vendor_id        = PNP_ID_VENDOR_ID;
        pnp_id.product_id       = PNP_ID_PRODUCT_ID;
        pnp_id.product_version  = PNP_ID_PRODUCT_VERSION;
    
        memset(&dis_init_obj, 0, sizeof(dis_init_obj));
    
        ble_srv_ascii_to_utf8(&dis_init_obj.manufact_name_str, MANUFACTURER_NAME);
    	ble_srv_ascii_to_utf8 (&dis_init_obj.fw_rev_str, FIRMWARE_VERSION);
        dis_init_obj.p_pnp_id = &pnp_id;
    
        dis_init_obj.dis_char_rd_sec = SEC_OPEN;
    
        err_code = ble_dis_init(&dis_init_obj);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for handling events from the BSP module.
     *
     * @param[in]   event   Event generated by button press.
     */
    static void bsp_event_handler(bsp_event_t event)
    {
        uint32_t         err_code;
        static uint8_t * p_key = 0; 
        static uint8_t   size  = 0;
    		
    		ble_conn_state_conn_handle_list_t conn_handles = ble_conn_state_periph_handles();
        switch (event)
        {
            case BSP_EVENT_SLEEP:
                sleep_mode_enter();
    					
    
            case BSP_EVENT_DISCONNECT:
                err_code = sd_ble_gap_disconnect(m_conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                if (err_code != NRF_ERROR_INVALID_STATE)
                {
                    APP_ERROR_CHECK(err_code);
                }
                break;
    
            case BSP_EVENT_WHITELIST_OFF:
                if (m_conn_handle == BLE_CONN_HANDLE_INVALID)
                {
                    err_code = ble_advertising_restart_without_whitelist(&m_advertising);
                    if (err_code != NRF_ERROR_INVALID_STATE)
                    {
                        APP_ERROR_CHECK(err_code);
                    }
                }
                break;
    
            case BSP_EVENT_KEY_0:
                if (m_conn_handle != BLE_CONN_HANDLE_INVALID)
                {
    							NRF_LOG_INFO("One click detected successfully\r\n");
    							dis_init();
                }
                break;
    
            default:
                break;
        }
    }

    Somehow, it did not work though the it has enter in to the function.

    But from sniffer I could not observe it has been update to OS.

    00> <info> app: Connected
    00> <info> peer_manager_handler: Connection secured: role: Peripheral, conn_handle: 0, procedure: Bonding
    00> <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Bonding data, action: Update
    00> <info> app: New Bond, add the peer to the whitelist if possible
    00> <info> app:   m_whitelist_peer_cnt 2, MAX_PEERS_WLIST 8
    00> <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Peer rank, action: Update
    00> <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Local database, action: Update
    00> <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Central address resolution, action: Update
    00> <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Local database, action: Update
    00> <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Local database, action: Update
    00> <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Local database, action: Update
    00> 
    00> <info> app: One Cilck detected successfully
    00> 
    00> <info> app: Enter device initial 

    In this case, do you know when will central will request the information during the connection?

    I just found that I need to repair the device to allow system proceed the read again?

    Or there is any API could notified host that the service is changed in device then make the host proceed request again?

  • Hi,

    CY said:
    I was trying to make dis_init(); again when I press the button 1.

    I do not see any reason for initializing more than once. Just initialize after reset, like you do other services. Note that the Device Information Service (DIS) does not use notifications/indications so there is no way you can push data to the central or force the central to read it. 

    CY said:
    In this case, do you know when will central will request the information during the connection?

    DIS information? That is up to the central implementation. Nothing forces it to read the DIS information. If you make the SW running on the central, then you can make sure to read it.

    CY said:
    I just found that I need to repair the device to allow system proceed the read again?

    It might be that some centrals will only read DIS once, assuming that it never changes. Again, that would depend on the central.

    CY said:
    Or there is any API could notified host that the service is changed in device then make the host proceed request again?

    There is a service changed concept, but that is not applicable here. The DIS service remains the same, it is just that the data has changed. You can try to ensure that you use service changed indications (enable it in both the application and bootloder sdk_config.h file), and perhaps some centrals will read the DIS characteristics after doing a new service discovery. That would make sense, but you can never be guaranteed that this will happen or will not change if the central changes (assuming you do not controll it).

Related