From f0fabd0d6eaaa08f1c8cb5b32d33c1da332c7410 Mon Sep 17 00:00:00 2001 From: Remi Bettan Date: Tue, 16 Apr 2024 09:48:11 +0300 Subject: [PATCH 1/8] debug code added --- src/fw-update/fw-update-device.cpp | 87 ++++++++++++++++++++++++++++++ src/fw-update/fw-update-device.h | 2 + 2 files changed, 89 insertions(+) diff --git a/src/fw-update/fw-update-device.cpp b/src/fw-update/fw-update-device.cpp index 9455a4719e..b2c7a7fe42 100644 --- a/src/fw-update/fw-update-device.cpp +++ b/src/fw-update/fw-update-device.cpp @@ -32,6 +32,17 @@ namespace librealsense return fw_version.str(); } + std::string datetime_string() + { + auto t = time(nullptr); + char buffer[20] = {}; + const tm* time = localtime(&t); + if (nullptr != time) + strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", time); + + return std::string(buffer); + } + rs2_dfu_state update_device::get_dfu_state(std::shared_ptr messenger) const { uint8_t state = RS2_DFU_STATE_DFU_ERROR; @@ -81,15 +92,84 @@ namespace librealsense LOG_INFO("DFU status: " << lock_status << " , DFU version is: " << payload.dfu_version); } + std::string to_string(platform::usb_status state) + { + switch (state) + { + case platform::RS2_USB_STATUS_SUCCESS: + return "USB_STATUS_SUCCESS"; + case platform::RS2_USB_STATUS_IO: + return "USB_STATUS_IO"; + case platform::RS2_USB_STATUS_INVALID_PARAM: + return "USB_STATUS_INVALID_PARAM"; + case platform::RS2_USB_STATUS_ACCESS: + return "USB_STATUS_ACCESS"; + case platform::RS2_USB_STATUS_NO_DEVICE: + return "USB_STATUS_NO_DEVICE"; + case platform::RS2_USB_STATUS_NOT_FOUND: + return "USB_STATUS_NOT_FOUND"; + case platform::RS2_USB_STATUS_BUSY: + return "USB_STATUS_BUSY"; + case platform::RS2_USB_STATUS_TIMEOUT: + return "USB_STATUS_TIMEOUT"; + case platform::RS2_USB_STATUS_OVERFLOW: + return "USB_STATUS_OVERFLOW"; + case platform::RS2_USB_STATUS_PIPE: + return "USB_STATUS_PIPE"; + case platform::RS2_USB_STATUS_INTERRUPTED: + return "USB_STATUS_INTERRUPTED"; + case platform::RS2_USB_STATUS_NO_MEM: + return "USB_STATUS_NO_MEM"; + case platform::RS2_USB_STATUS_NOT_SUPPORTED: + return "USB_STATUS_NOT_SUPPORTED"; + case platform::RS2_USB_STATUS_OTHER: + return "USB_STATUS_OTHER"; + default: + return "USB???"; + } + } + + std::string to_string(rs2_dfu_state state) + { + switch (state) + { + case(RS2_DFU_STATE_APP_IDLE): + return "APP_IDLE"; + case(RS2_DFU_STATE_APP_DETACH): + return "APP_DETACH"; + case(RS2_DFU_STATE_DFU_DOWNLOAD_SYNC): + return "DFU_DOWNLOAD_SYNC"; + case(RS2_DFU_STATE_DFU_DOWNLOAD_BUSY): + return "DFU_DOWNLOAD_BUSY"; + case(RS2_DFU_STATE_DFU_DOWNLOAD_IDLE): + return "DFU_DOWNLOAD_IDLE"; + case(RS2_DFU_STATE_DFU_MANIFEST_SYNC): + return "DFU_MANIFEST_SYNC"; + case(RS2_DFU_STATE_DFU_MANIFEST): + return "DFU_MANIFEST"; + case(RS2_DFU_STATE_DFU_MANIFEST_WAIT_RESET): + return "DFU_MANIFEST_WAIT_RESET"; + case(RS2_DFU_STATE_DFU_UPLOAD_IDLE): + return "DFU_UPLOAD_IDLE"; + case(RS2_DFU_STATE_DFU_ERROR): + return "DFU_ERROR"; + default: + return "DFU_STATE_???"; + } + } + bool update_device::wait_for_state(std::shared_ptr messenger, const rs2_dfu_state state, size_t timeout) const { std::chrono::milliseconds elapsed_milliseconds; + _out << "wait_for_state: " << to_string(state) << std::endl; auto start = std::chrono::system_clock::now(); do { dfu_status_payload status; uint32_t transferred = 0; auto sts = messenger->control_transfer(0xa1 /*DFU_GETSTATUS_PACKET*/, RS2_DFU_GET_STATUS, 0, 0, (uint8_t*)&status, sizeof(status), transferred, 5000); + _out << datetime_string() << " - " << "DFU_GETSTATUS called, state is: " << to_string(sts) << "\n"; + if (sts != platform::RS2_USB_STATUS_SUCCESS) return false; @@ -120,6 +200,7 @@ namespace librealsense , _physical_port( usb_device->get_info().id ) , _pid( rsutils::string::from() << std::uppercase << rsutils::string::hexdump( usb_device->get_info().pid )) , _product_line( product_line ) + , _out("DFU_GETSTATUS_calls.txt", std::ofstream::app) { if (auto messenger = _usb_device->open(FW_UPDATE_INTERFACE_NUMBER)) { @@ -140,6 +221,7 @@ namespace librealsense } } + update_device::~update_device() { @@ -163,6 +245,7 @@ namespace librealsense size_t offset = 0; uint32_t transferred = 0; int retries = 10; + _out << datetime_string() << " - " << "Starting DFU Process..." << std::endl; while (remaining_bytes > 0) { @@ -170,6 +253,8 @@ namespace librealsense auto curr_block = ((uint8_t*)fw_image + offset); auto sts = messenger->control_transfer(0x21 /*DFU_DOWNLOAD_PACKET*/, RS2_DFU_DOWNLOAD, block_number, 0, curr_block, uint32_t(chunk_size), transferred, 5000); + auto now_time = std::chrono::system_clock::now(); + _out << datetime_string() << " - " << "Download Chunk" << std::endl; if (sts != platform::RS2_USB_STATUS_SUCCESS || !wait_for_state(messenger, RS2_DFU_STATE_DFU_DOWNLOAD_IDLE, 1000)) { auto state = get_dfu_state(messenger); @@ -206,6 +291,8 @@ namespace librealsense if (sts != platform::RS2_USB_STATUS_SUCCESS) throw std::runtime_error("Failed to send final FW packet"); + _out << datetime_string() << " - " << "Final FW packet sent" << std::endl; + // After the zero length DFU_DNLOAD request terminates the Transfer // phase, the device is ready to manifest the new firmware. As described // previously, some devices may accumulate the firmware image and perform diff --git a/src/fw-update/fw-update-device.h b/src/fw-update/fw-update-device.h index 143358b165..e35e634a46 100644 --- a/src/fw-update/fw-update-device.h +++ b/src/fw-update/fw-update-device.h @@ -5,6 +5,7 @@ #include #include "fw-update-device-interface.h" #include "usb/usb-device.h" +#include namespace librealsense { @@ -164,5 +165,6 @@ namespace librealsense std::string _name; std::string _product_line; std::string _serial_number; + mutable std::ofstream _out; }; } From 4831aaa4fa34ce9db1b72668551fda1caeea33ee Mon Sep 17 00:00:00 2001 From: Remi Bettan Date: Mon, 13 May 2024 11:22:33 +0300 Subject: [PATCH 2/8] works well with sc - check with other skus needed --- common/fw-update-helper.cpp | 5 +-- src/ds/d500/d500-fw-update-device.cpp | 13 +----- src/fw-update/fw-update-device.cpp | 65 +++++++++++++++++++++++++-- src/fw-update/fw-update-device.h | 2 + 4 files changed, 65 insertions(+), 20 deletions(-) diff --git a/common/fw-update-helper.cpp b/common/fw-update-helper.cpp index fa2580110a..104d134981 100644 --- a/common/fw-update-helper.cpp +++ b/common/fw-update-helper.cpp @@ -271,11 +271,8 @@ namespace rs2 if ( !log_backup_status.empty() ) log(log_backup_status); - - - - next_progress = 40; + next_progress = _progress + 10; if (_is_signed) { diff --git a/src/ds/d500/d500-fw-update-device.cpp b/src/ds/d500/d500-fw-update-device.cpp index c6c2be21f3..62555c03cb 100644 --- a/src/ds/d500/d500-fw-update-device.cpp +++ b/src/ds/d500/d500-fw-update-device.cpp @@ -37,17 +37,6 @@ ds_d500_update_device::ds_d500_update_device( std::shared_ptr< const device_info void ds_d500_update_device::update(const void* fw_image, int fw_image_size, rs2_update_progress_callback_sptr update_progress_callback) const { - update_device::update( fw_image, fw_image_size ); - - static constexpr float D500_FW_DFU_TIME = 180.0; // [sec] - // We calculate the sleep time needed for each cycle to get to 100% progress bar - // On D500 devices after transferring the FW image the internal DFU progress start on the device - float iteration_sleep_time_ms = (static_cast(D500_FW_DFU_TIME) / 100.0f) * 1000.0f; - for(int i = 1; i <= 100; i++) - { - if (update_progress_callback) - update_progress_callback->on_update_progress( i / 100.f ); - std::this_thread::sleep_for(std::chrono::milliseconds(static_cast(iteration_sleep_time_ms))); - } + update_device::update( fw_image, fw_image_size, update_progress_callback ); } } diff --git a/src/fw-update/fw-update-device.cpp b/src/fw-update/fw-update-device.cpp index b2c7a7fe42..27bc8e5545 100644 --- a/src/fw-update/fw-update-device.cpp +++ b/src/fw-update/fw-update-device.cpp @@ -161,15 +161,12 @@ namespace librealsense bool update_device::wait_for_state(std::shared_ptr messenger, const rs2_dfu_state state, size_t timeout) const { std::chrono::milliseconds elapsed_milliseconds; - _out << "wait_for_state: " << to_string(state) << std::endl; auto start = std::chrono::system_clock::now(); do { dfu_status_payload status; uint32_t transferred = 0; auto sts = messenger->control_transfer(0xa1 /*DFU_GETSTATUS_PACKET*/, RS2_DFU_GET_STATUS, 0, 0, (uint8_t*)&status, sizeof(status), transferred, 5000); - _out << datetime_string() << " - " << "DFU_GETSTATUS called, state is: " << to_string(sts) << "\n"; - if (sts != platform::RS2_USB_STATUS_SUCCESS) return false; @@ -192,6 +189,53 @@ namespace librealsense return false; } + float compute_progress(float progress, float start, float end, float threshold) + { + return start + (ceil(progress * threshold) / threshold) * (end - start) / 100.f; + } + + bool update_device::wait_for_manifest_completion(std::shared_ptr messenger, const rs2_dfu_state state, + size_t timeout, rs2_update_progress_callback_sptr update_progress_callback) const + { + std::chrono::milliseconds elapsed_milliseconds; + _out << "wait_for_state: " << to_string(state) << std::endl; + auto start = std::chrono::system_clock::now(); + rs2_dfu_state dfu_state = RS2_DFU_STATE_APP_IDLE; + dfu_status_payload status; + int percentage_of_transfer = 0; + + do { + uint32_t transferred = 0; + auto sts = messenger->control_transfer(0xa1 /*DFU_GETSTATUS_PACKET*/, RS2_DFU_GET_STATUS, 0, 0, (uint8_t*)&status, sizeof(status), transferred, 5000); + dfu_state = status.get_state(); + percentage_of_transfer = (int)(status.iString); + _out << datetime_string() << " - " << "DFU_GETSTATUS called, state is: " << to_string(dfu_state); + _out << ", iString equals: " << percentage_of_transfer << ", and bwPollTimeOut equals: " << status.bwPollTimeout << std::endl; + + if (update_progress_callback) + { + auto progress_for_bar = compute_progress(static_cast(percentage_of_transfer), 20.f, 100.f, 5.f) / 100.f; + update_progress_callback->on_update_progress(progress_for_bar); + } + + if (sts != platform::RS2_USB_STATUS_SUCCESS) + _out << "control xfer error: " << to_string(sts) << std::endl; + + //test for dfu error state + if (status.is_error_state()) { + return false; + } + + // FW doesn't set the bwPollTimeout value, therefore it is wrong to use status.bwPollTimeout + std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_TIMEOUT)); + + auto curr = std::chrono::system_clock::now(); + elapsed_milliseconds = std::chrono::duration_cast(curr - start); + } while (percentage_of_transfer < 100); + + return true; + } + update_device::update_device( std::shared_ptr< const device_info > const & dev_info, std::shared_ptr< platform::usb_device > const & usb_device, const std::string & product_line ) @@ -280,7 +324,10 @@ namespace librealsense float progress = (float)block_number / (float)blocks_count; LOG_DEBUG("fw update progress: " << progress); if (update_progress_callback) - update_progress_callback->on_update_progress(progress); + { + auto progress_for_bar = compute_progress(progress, 0.f, 20.f, 5.f) / 100.f;//((ceil(progress * 5) / 5) * 20.f / 100.f) / 100.f; + update_progress_callback->on_update_progress(progress_for_bar); + } } // After the final block of firmware has been sent to the device and the status solicited, the host sends a @@ -293,6 +340,16 @@ namespace librealsense _out << datetime_string() << " - " << "Final FW packet sent" << std::endl; + + // d500 code added ---------------------------------- + + if (!wait_for_manifest_completion(messenger, RS2_DFU_STATE_DFU_MANIFEST, 20000, update_progress_callback)) + throw std::runtime_error("Firmware manifest failed"); + + + // end of code added + + // After the zero length DFU_DNLOAD request terminates the Transfer // phase, the device is ready to manifest the new firmware. As described // previously, some devices may accumulate the firmware image and perform diff --git a/src/fw-update/fw-update-device.h b/src/fw-update/fw-update-device.h index e35e634a46..9c68bad962 100644 --- a/src/fw-update/fw-update-device.h +++ b/src/fw-update/fw-update-device.h @@ -147,6 +147,8 @@ namespace librealsense rs2_dfu_state get_dfu_state(std::shared_ptr messenger) const; void detach(std::shared_ptr messenger) const; bool wait_for_state(std::shared_ptr messenger, const rs2_dfu_state state, size_t timeout = 1000) const; + bool wait_for_manifest_completion(std::shared_ptr messenger, const rs2_dfu_state state, + size_t timeout, rs2_update_progress_callback_sptr update_progress_callback) const; void read_device_info(std::shared_ptr messenger); const std::string & get_name() const { return _name; } From 6aff952170ba30cef7c052e86609fb69277c06f2 Mon Sep 17 00:00:00 2001 From: Remi Bettan Date: Thu, 16 May 2024 14:59:28 +0300 Subject: [PATCH 3/8] progress sampling only for d500 devices --- src/ds/d500/d500-fw-update-device.cpp | 43 ++++++++++++++++++++ src/ds/d500/d500-fw-update-device.h | 2 + src/fw-update/fw-update-device.cpp | 57 +++------------------------ src/fw-update/fw-update-device.h | 9 +++-- 4 files changed, 57 insertions(+), 54 deletions(-) diff --git a/src/ds/d500/d500-fw-update-device.cpp b/src/ds/d500/d500-fw-update-device.cpp index 62555c03cb..ff2908e9cc 100644 --- a/src/ds/d500/d500-fw-update-device.cpp +++ b/src/ds/d500/d500-fw-update-device.cpp @@ -39,4 +39,47 @@ ds_d500_update_device::ds_d500_update_device( std::shared_ptr< const device_info { update_device::update( fw_image, fw_image_size, update_progress_callback ); } + + bool ds_d500_update_device::wait_for_manifest_completion(std::shared_ptr messenger, const rs2_dfu_state state, + size_t timeout, rs2_update_progress_callback_sptr update_progress_callback) const + { + std::chrono::milliseconds elapsed_milliseconds; + auto start = std::chrono::system_clock::now(); + rs2_dfu_state dfu_state = RS2_DFU_STATE_APP_IDLE; + dfu_status_payload status; + int percentage_of_transfer = 0; + + do { + uint32_t transferred = 0; + auto sts = messenger->control_transfer(0xa1 /*DFU_GETSTATUS_PACKET*/, RS2_DFU_GET_STATUS, 0, 0, (uint8_t*)&status, sizeof(status), transferred, 5000); + dfu_state = status.get_state(); + percentage_of_transfer = (int)(status.iString); + std::stringstream ss; + ss << "DFU_GETSTATUS called, state is: " << to_string(dfu_state); + ss << ", iString equals: " << percentage_of_transfer << ", and bwPollTimeOut equals: " << status.bwPollTimeout << std::endl; + LOG_DEBUG(ss.str().c_str()); + + if (update_progress_callback) + { + auto progress_for_bar = compute_progress(static_cast(percentage_of_transfer), 20.f, 100.f, 5.f) / 100.f; + update_progress_callback->on_update_progress(progress_for_bar); + } + + if (sts != platform::RS2_USB_STATUS_SUCCESS) + LOG_DEBUG("control xfer error: " << to_string(sts)); + + //test for dfu error state + if (status.is_error_state()) { + return false; + } + + // FW doesn't set the bwPollTimeout value, therefore it is wrong to use status.bwPollTimeout + std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_TIMEOUT)); + + auto curr = std::chrono::system_clock::now(); + elapsed_milliseconds = std::chrono::duration_cast(curr - start); + } while (percentage_of_transfer < 100); + + return true; + } } diff --git a/src/ds/d500/d500-fw-update-device.h b/src/ds/d500/d500-fw-update-device.h index e856313fa8..58175e5728 100644 --- a/src/ds/d500/d500-fw-update-device.h +++ b/src/ds/d500/d500-fw-update-device.h @@ -16,6 +16,8 @@ namespace librealsense virtual bool check_fw_compatibility(const std::vector& image) const override; virtual void update(const void* fw_image, int fw_image_size, rs2_update_progress_callback_sptr = nullptr) const override; + virtual bool wait_for_manifest_completion(std::shared_ptr messenger, const rs2_dfu_state state, + size_t timeout, rs2_update_progress_callback_sptr update_progress_callback) const override; private: std::string parse_serial_number(const std::vector& buffer) const; diff --git a/src/fw-update/fw-update-device.cpp b/src/fw-update/fw-update-device.cpp index 27bc8e5545..88d064fdac 100644 --- a/src/fw-update/fw-update-device.cpp +++ b/src/fw-update/fw-update-device.cpp @@ -14,8 +14,6 @@ #include #include -#define DEFAULT_TIMEOUT 100 -#define FW_UPDATE_INTERFACE_NUMBER 0 namespace librealsense { std::string get_formatted_fw_version(uint32_t fw_last_version) @@ -92,7 +90,7 @@ namespace librealsense LOG_INFO("DFU status: " << lock_status << " , DFU version is: " << payload.dfu_version); } - std::string to_string(platform::usb_status state) + std::string update_device::to_string(platform::usb_status state) const { switch (state) { @@ -129,7 +127,7 @@ namespace librealsense } } - std::string to_string(rs2_dfu_state state) + std::string update_device::to_string(rs2_dfu_state state) const { switch (state) { @@ -189,7 +187,7 @@ namespace librealsense return false; } - float compute_progress(float progress, float start, float end, float threshold) + float update_device::compute_progress(float progress, float start, float end, float threshold) const { return start + (ceil(progress * threshold) / threshold) * (end - start) / 100.f; } @@ -197,41 +195,7 @@ namespace librealsense bool update_device::wait_for_manifest_completion(std::shared_ptr messenger, const rs2_dfu_state state, size_t timeout, rs2_update_progress_callback_sptr update_progress_callback) const { - std::chrono::milliseconds elapsed_milliseconds; - _out << "wait_for_state: " << to_string(state) << std::endl; - auto start = std::chrono::system_clock::now(); - rs2_dfu_state dfu_state = RS2_DFU_STATE_APP_IDLE; - dfu_status_payload status; - int percentage_of_transfer = 0; - - do { - uint32_t transferred = 0; - auto sts = messenger->control_transfer(0xa1 /*DFU_GETSTATUS_PACKET*/, RS2_DFU_GET_STATUS, 0, 0, (uint8_t*)&status, sizeof(status), transferred, 5000); - dfu_state = status.get_state(); - percentage_of_transfer = (int)(status.iString); - _out << datetime_string() << " - " << "DFU_GETSTATUS called, state is: " << to_string(dfu_state); - _out << ", iString equals: " << percentage_of_transfer << ", and bwPollTimeOut equals: " << status.bwPollTimeout << std::endl; - - if (update_progress_callback) - { - auto progress_for_bar = compute_progress(static_cast(percentage_of_transfer), 20.f, 100.f, 5.f) / 100.f; - update_progress_callback->on_update_progress(progress_for_bar); - } - - if (sts != platform::RS2_USB_STATUS_SUCCESS) - _out << "control xfer error: " << to_string(sts) << std::endl; - - //test for dfu error state - if (status.is_error_state()) { - return false; - } - - // FW doesn't set the bwPollTimeout value, therefore it is wrong to use status.bwPollTimeout - std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_TIMEOUT)); - - auto curr = std::chrono::system_clock::now(); - elapsed_milliseconds = std::chrono::duration_cast(curr - start); - } while (percentage_of_transfer < 100); + // used for devices which get the progress percentage in the GET_DFU_STATUS call return true; } @@ -244,7 +208,6 @@ namespace librealsense , _physical_port( usb_device->get_info().id ) , _pid( rsutils::string::from() << std::uppercase << rsutils::string::hexdump( usb_device->get_info().pid )) , _product_line( product_line ) - , _out("DFU_GETSTATUS_calls.txt", std::ofstream::app) { if (auto messenger = _usb_device->open(FW_UPDATE_INTERFACE_NUMBER)) { @@ -289,8 +252,7 @@ namespace librealsense size_t offset = 0; uint32_t transferred = 0; int retries = 10; - _out << datetime_string() << " - " << "Starting DFU Process..." << std::endl; - + while (remaining_bytes > 0) { size_t chunk_size = std::min(transfer_size, remaining_bytes); @@ -298,7 +260,6 @@ namespace librealsense auto curr_block = ((uint8_t*)fw_image + offset); auto sts = messenger->control_transfer(0x21 /*DFU_DOWNLOAD_PACKET*/, RS2_DFU_DOWNLOAD, block_number, 0, curr_block, uint32_t(chunk_size), transferred, 5000); auto now_time = std::chrono::system_clock::now(); - _out << datetime_string() << " - " << "Download Chunk" << std::endl; if (sts != platform::RS2_USB_STATUS_SUCCESS || !wait_for_state(messenger, RS2_DFU_STATE_DFU_DOWNLOAD_IDLE, 1000)) { auto state = get_dfu_state(messenger); @@ -338,18 +299,12 @@ namespace librealsense if (sts != platform::RS2_USB_STATUS_SUCCESS) throw std::runtime_error("Failed to send final FW packet"); - _out << datetime_string() << " - " << "Final FW packet sent" << std::endl; - - - // d500 code added ---------------------------------- + // measuring the progress of the writing to flash (when enabled by FW) if (!wait_for_manifest_completion(messenger, RS2_DFU_STATE_DFU_MANIFEST, 20000, update_progress_callback)) throw std::runtime_error("Firmware manifest failed"); - // end of code added - - // After the zero length DFU_DNLOAD request terminates the Transfer // phase, the device is ready to manifest the new firmware. As described // previously, some devices may accumulate the firmware image and perform diff --git a/src/fw-update/fw-update-device.h b/src/fw-update/fw-update-device.h index 9c68bad962..30549cc291 100644 --- a/src/fw-update/fw-update-device.h +++ b/src/fw-update/fw-update-device.h @@ -147,15 +147,19 @@ namespace librealsense rs2_dfu_state get_dfu_state(std::shared_ptr messenger) const; void detach(std::shared_ptr messenger) const; bool wait_for_state(std::shared_ptr messenger, const rs2_dfu_state state, size_t timeout = 1000) const; - bool wait_for_manifest_completion(std::shared_ptr messenger, const rs2_dfu_state state, + virtual bool wait_for_manifest_completion(std::shared_ptr messenger, const rs2_dfu_state state, size_t timeout, rs2_update_progress_callback_sptr update_progress_callback) const; void read_device_info(std::shared_ptr messenger); const std::string & get_name() const { return _name; } const std::string & get_product_line() const { return _product_line; } const std::string & get_serial_number() const { return _serial_number; } + std::string to_string(platform::usb_status state) const; + std::string to_string(rs2_dfu_state state) const; + float compute_progress(float progress, float start, float end, float threshold) const; - + const int DEFAULT_TIMEOUT = 100; + const int FW_UPDATE_INTERFACE_NUMBER = 0; const std::shared_ptr< const device_info > _dev_info; const platform::rs_usb_device _usb_device; std::vector _serial_number_buffer; @@ -167,6 +171,5 @@ namespace librealsense std::string _name; std::string _product_line; std::string _serial_number; - mutable std::ofstream _out; }; } From 714dfe80643481124c16c454e1e2df557c31cee4 Mon Sep 17 00:00:00 2001 From: Remi Bettan Date: Mon, 20 May 2024 11:39:09 +0300 Subject: [PATCH 4/8] avoid d5XX devices w/o DFU progress feature to get stuck --- src/ds/d500/d500-fw-update-device.cpp | 13 ++++++++++++- src/fw-update/fw-update-device.cpp | 15 +-------------- src/fw-update/fw-update-device.h | 1 - 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/ds/d500/d500-fw-update-device.cpp b/src/ds/d500/d500-fw-update-device.cpp index ff2908e9cc..f8474a879f 100644 --- a/src/ds/d500/d500-fw-update-device.cpp +++ b/src/ds/d500/d500-fw-update-device.cpp @@ -48,12 +48,23 @@ ds_d500_update_device::ds_d500_update_device( std::shared_ptr< const device_info rs2_dfu_state dfu_state = RS2_DFU_STATE_APP_IDLE; dfu_status_payload status; int percentage_of_transfer = 0; + int iteration = 0; + // progress should start increase even in the 2nd iteration, + // when this DFU progress is enabled by FW + int max_iteration_number_for_progress_start = 10; do { uint32_t transferred = 0; auto sts = messenger->control_transfer(0xa1 /*DFU_GETSTATUS_PACKET*/, RS2_DFU_GET_STATUS, 0, 0, (uint8_t*)&status, sizeof(status), transferred, 5000); dfu_state = status.get_state(); percentage_of_transfer = (int)(status.iString); + + // the below code avoids process stuck when using a d5XXX device, + // which has a fw version without the DFU progress feature + if (percentage_of_transfer == 0 && + ++iteration == max_iteration_number_for_progress_start) + return true; + std::stringstream ss; ss << "DFU_GETSTATUS called, state is: " << to_string(dfu_state); ss << ", iString equals: " << percentage_of_transfer << ", and bwPollTimeOut equals: " << status.bwPollTimeout << std::endl; @@ -78,7 +89,7 @@ ds_d500_update_device::ds_d500_update_device( std::shared_ptr< const device_info auto curr = std::chrono::system_clock::now(); elapsed_milliseconds = std::chrono::duration_cast(curr - start); - } while (percentage_of_transfer < 100); + } while (percentage_of_transfer < 100 && dfu_state == RS2_DFU_STATE_DFU_MANIFEST); return true; } diff --git a/src/fw-update/fw-update-device.cpp b/src/fw-update/fw-update-device.cpp index 88d064fdac..2ae9f6e877 100644 --- a/src/fw-update/fw-update-device.cpp +++ b/src/fw-update/fw-update-device.cpp @@ -30,17 +30,6 @@ namespace librealsense return fw_version.str(); } - std::string datetime_string() - { - auto t = time(nullptr); - char buffer[20] = {}; - const tm* time = localtime(&t); - if (nullptr != time) - strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", time); - - return std::string(buffer); - } - rs2_dfu_state update_device::get_dfu_state(std::shared_ptr messenger) const { uint8_t state = RS2_DFU_STATE_DFU_ERROR; @@ -228,7 +217,6 @@ namespace librealsense } } - update_device::~update_device() { @@ -252,14 +240,13 @@ namespace librealsense size_t offset = 0; uint32_t transferred = 0; int retries = 10; - + while (remaining_bytes > 0) { size_t chunk_size = std::min(transfer_size, remaining_bytes); auto curr_block = ((uint8_t*)fw_image + offset); auto sts = messenger->control_transfer(0x21 /*DFU_DOWNLOAD_PACKET*/, RS2_DFU_DOWNLOAD, block_number, 0, curr_block, uint32_t(chunk_size), transferred, 5000); - auto now_time = std::chrono::system_clock::now(); if (sts != platform::RS2_USB_STATUS_SUCCESS || !wait_for_state(messenger, RS2_DFU_STATE_DFU_DOWNLOAD_IDLE, 1000)) { auto state = get_dfu_state(messenger); diff --git a/src/fw-update/fw-update-device.h b/src/fw-update/fw-update-device.h index 30549cc291..6a6c3fd850 100644 --- a/src/fw-update/fw-update-device.h +++ b/src/fw-update/fw-update-device.h @@ -5,7 +5,6 @@ #include #include "fw-update-device-interface.h" #include "usb/usb-device.h" -#include namespace librealsense { From 2981cd0acd0894811b0b66fdde9b2fb06069fc48 Mon Sep 17 00:00:00 2001 From: Remi Bettan Date: Tue, 21 May 2024 11:06:51 +0300 Subject: [PATCH 5/8] cr improvements --- src/ds/d500/d500-fw-update-device.cpp | 19 +++++++----- src/ds/d500/d500-fw-update-device.h | 2 +- src/fw-update/fw-update-device.cpp | 43 ++------------------------- src/fw-update/fw-update-device.h | 2 +- 4 files changed, 17 insertions(+), 49 deletions(-) diff --git a/src/ds/d500/d500-fw-update-device.cpp b/src/ds/d500/d500-fw-update-device.cpp index f8474a879f..ddccfecf04 100644 --- a/src/ds/d500/d500-fw-update-device.cpp +++ b/src/ds/d500/d500-fw-update-device.cpp @@ -41,9 +41,9 @@ ds_d500_update_device::ds_d500_update_device( std::shared_ptr< const device_info } bool ds_d500_update_device::wait_for_manifest_completion(std::shared_ptr messenger, const rs2_dfu_state state, - size_t timeout, rs2_update_progress_callback_sptr update_progress_callback) const + std::chrono::seconds timeout_seconds, rs2_update_progress_callback_sptr update_progress_callback) const { - std::chrono::milliseconds elapsed_milliseconds; + std::chrono::seconds elapsed_seconds; auto start = std::chrono::system_clock::now(); rs2_dfu_state dfu_state = RS2_DFU_STATE_APP_IDLE; dfu_status_payload status; @@ -57,9 +57,9 @@ ds_d500_update_device::ds_d500_update_device( std::shared_ptr< const device_info uint32_t transferred = 0; auto sts = messenger->control_transfer(0xa1 /*DFU_GETSTATUS_PACKET*/, RS2_DFU_GET_STATUS, 0, 0, (uint8_t*)&status, sizeof(status), transferred, 5000); dfu_state = status.get_state(); - percentage_of_transfer = (int)(status.iString); + percentage_of_transfer = static_cast(status.iString); - // the below code avoids process stuck when using a d5XXX device, + // the below code avoids process stuck when using a d5XX device, // which has a fw version without the DFU progress feature if (percentage_of_transfer == 0 && ++iteration == max_iteration_number_for_progress_start) @@ -77,7 +77,7 @@ ds_d500_update_device::ds_d500_update_device( std::shared_ptr< const device_info } if (sts != platform::RS2_USB_STATUS_SUCCESS) - LOG_DEBUG("control xfer error: " << to_string(sts)); + LOG_DEBUG("control xfer error: " << platform::usb_status_to_string[sts]); //test for dfu error state if (status.is_error_state()) { @@ -85,10 +85,15 @@ ds_d500_update_device::ds_d500_update_device( std::shared_ptr< const device_info } // FW doesn't set the bwPollTimeout value, therefore it is wrong to use status.bwPollTimeout - std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_TIMEOUT)); + std::this_thread::sleep_for(std::chrono::seconds(1)); auto curr = std::chrono::system_clock::now(); - elapsed_milliseconds = std::chrono::duration_cast(curr - start); + elapsed_seconds = std::chrono::duration_cast(curr - start); + if (elapsed_seconds > timeout_seconds) + { + LOG_DEBUG("DFU in MANIFEST STATUS Timeout"); + return false; + } } while (percentage_of_transfer < 100 && dfu_state == RS2_DFU_STATE_DFU_MANIFEST); return true; diff --git a/src/ds/d500/d500-fw-update-device.h b/src/ds/d500/d500-fw-update-device.h index 58175e5728..48b18b9952 100644 --- a/src/ds/d500/d500-fw-update-device.h +++ b/src/ds/d500/d500-fw-update-device.h @@ -17,7 +17,7 @@ namespace librealsense virtual bool check_fw_compatibility(const std::vector& image) const override; virtual void update(const void* fw_image, int fw_image_size, rs2_update_progress_callback_sptr = nullptr) const override; virtual bool wait_for_manifest_completion(std::shared_ptr messenger, const rs2_dfu_state state, - size_t timeout, rs2_update_progress_callback_sptr update_progress_callback) const override; + std::chrono::seconds timeout_seconds, rs2_update_progress_callback_sptr update_progress_callback) const override; private: std::string parse_serial_number(const std::vector& buffer) const; diff --git a/src/fw-update/fw-update-device.cpp b/src/fw-update/fw-update-device.cpp index 2ae9f6e877..efd7d51e47 100644 --- a/src/fw-update/fw-update-device.cpp +++ b/src/fw-update/fw-update-device.cpp @@ -79,43 +79,6 @@ namespace librealsense LOG_INFO("DFU status: " << lock_status << " , DFU version is: " << payload.dfu_version); } - std::string update_device::to_string(platform::usb_status state) const - { - switch (state) - { - case platform::RS2_USB_STATUS_SUCCESS: - return "USB_STATUS_SUCCESS"; - case platform::RS2_USB_STATUS_IO: - return "USB_STATUS_IO"; - case platform::RS2_USB_STATUS_INVALID_PARAM: - return "USB_STATUS_INVALID_PARAM"; - case platform::RS2_USB_STATUS_ACCESS: - return "USB_STATUS_ACCESS"; - case platform::RS2_USB_STATUS_NO_DEVICE: - return "USB_STATUS_NO_DEVICE"; - case platform::RS2_USB_STATUS_NOT_FOUND: - return "USB_STATUS_NOT_FOUND"; - case platform::RS2_USB_STATUS_BUSY: - return "USB_STATUS_BUSY"; - case platform::RS2_USB_STATUS_TIMEOUT: - return "USB_STATUS_TIMEOUT"; - case platform::RS2_USB_STATUS_OVERFLOW: - return "USB_STATUS_OVERFLOW"; - case platform::RS2_USB_STATUS_PIPE: - return "USB_STATUS_PIPE"; - case platform::RS2_USB_STATUS_INTERRUPTED: - return "USB_STATUS_INTERRUPTED"; - case platform::RS2_USB_STATUS_NO_MEM: - return "USB_STATUS_NO_MEM"; - case platform::RS2_USB_STATUS_NOT_SUPPORTED: - return "USB_STATUS_NOT_SUPPORTED"; - case platform::RS2_USB_STATUS_OTHER: - return "USB_STATUS_OTHER"; - default: - return "USB???"; - } - } - std::string update_device::to_string(rs2_dfu_state state) const { switch (state) @@ -182,7 +145,7 @@ namespace librealsense } bool update_device::wait_for_manifest_completion(std::shared_ptr messenger, const rs2_dfu_state state, - size_t timeout, rs2_update_progress_callback_sptr update_progress_callback) const + std::chrono::seconds timeout_seconds, rs2_update_progress_callback_sptr update_progress_callback) const { // used for devices which get the progress percentage in the GET_DFU_STATUS call @@ -288,8 +251,8 @@ namespace librealsense // measuring the progress of the writing to flash (when enabled by FW) - if (!wait_for_manifest_completion(messenger, RS2_DFU_STATE_DFU_MANIFEST, 20000, update_progress_callback)) - throw std::runtime_error("Firmware manifest failed"); + if (!wait_for_manifest_completion(messenger, RS2_DFU_STATE_DFU_MANIFEST, std::chrono::seconds(200), update_progress_callback)) + throw std::runtime_error("Firmware manifest completion failed"); // After the zero length DFU_DNLOAD request terminates the Transfer diff --git a/src/fw-update/fw-update-device.h b/src/fw-update/fw-update-device.h index 6a6c3fd850..ac27eab822 100644 --- a/src/fw-update/fw-update-device.h +++ b/src/fw-update/fw-update-device.h @@ -147,7 +147,7 @@ namespace librealsense void detach(std::shared_ptr messenger) const; bool wait_for_state(std::shared_ptr messenger, const rs2_dfu_state state, size_t timeout = 1000) const; virtual bool wait_for_manifest_completion(std::shared_ptr messenger, const rs2_dfu_state state, - size_t timeout, rs2_update_progress_callback_sptr update_progress_callback) const; + std::chrono::seconds timeout_seconds, rs2_update_progress_callback_sptr update_progress_callback) const; void read_device_info(std::shared_ptr messenger); const std::string & get_name() const { return _name; } From c7cf6ee5dd5f40e07db68b489bb3ad9a784364e8 Mon Sep 17 00:00:00 2001 From: Remi Bettan Date: Tue, 21 May 2024 16:13:48 +0300 Subject: [PATCH 6/8] empty commit From 14fe1a4661ba58d4bcf9aab956de561da9a8d9bf Mon Sep 17 00:00:00 2001 From: Remi Bettan Date: Thu, 23 May 2024 13:34:38 +0300 Subject: [PATCH 7/8] cr --- src/ds/d500/d500-fw-update-device.cpp | 2 +- src/fw-update/fw-update-device.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ds/d500/d500-fw-update-device.cpp b/src/ds/d500/d500-fw-update-device.cpp index ddccfecf04..7687a2e977 100644 --- a/src/ds/d500/d500-fw-update-device.cpp +++ b/src/ds/d500/d500-fw-update-device.cpp @@ -91,7 +91,7 @@ ds_d500_update_device::ds_d500_update_device( std::shared_ptr< const device_info elapsed_seconds = std::chrono::duration_cast(curr - start); if (elapsed_seconds > timeout_seconds) { - LOG_DEBUG("DFU in MANIFEST STATUS Timeout"); + LOG_ERROR("DFU in MANIFEST STATUS Timeout"); return false; } } while (percentage_of_transfer < 100 && dfu_state == RS2_DFU_STATE_DFU_MANIFEST); diff --git a/src/fw-update/fw-update-device.cpp b/src/fw-update/fw-update-device.cpp index efd7d51e47..20054b524f 100644 --- a/src/fw-update/fw-update-device.cpp +++ b/src/fw-update/fw-update-device.cpp @@ -141,6 +141,8 @@ namespace librealsense float update_device::compute_progress(float progress, float start, float end, float threshold) const { + if (threshold < 1.f && threshold > -1.f) + throw std::invalid_argument("Avoid division by zero"); return start + (ceil(progress * threshold) / threshold) * (end - start) / 100.f; } @@ -236,7 +238,7 @@ namespace librealsense LOG_DEBUG("fw update progress: " << progress); if (update_progress_callback) { - auto progress_for_bar = compute_progress(progress, 0.f, 20.f, 5.f) / 100.f;//((ceil(progress * 5) / 5) * 20.f / 100.f) / 100.f; + auto progress_for_bar = compute_progress(progress, 0.f, 20.f, 5.f) / 100.f; update_progress_callback->on_update_progress(progress_for_bar); } } From 4e26e9318cc220f9e1488fe495b734f0d4dcb069 Mon Sep 17 00:00:00 2001 From: Remi Bettan Date: Thu, 23 May 2024 14:40:55 +0300 Subject: [PATCH 8/8] cr2 --- src/fw-update/fw-update-device.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fw-update/fw-update-device.cpp b/src/fw-update/fw-update-device.cpp index 20054b524f..75141fa3c8 100644 --- a/src/fw-update/fw-update-device.cpp +++ b/src/fw-update/fw-update-device.cpp @@ -141,7 +141,7 @@ namespace librealsense float update_device::compute_progress(float progress, float start, float end, float threshold) const { - if (threshold < 1.f && threshold > -1.f) + if (threshold < 1.f) throw std::invalid_argument("Avoid division by zero"); return start + (ceil(progress * threshold) / threshold) * (end - start) / 100.f; }