diff --git a/common/fw-update-helper.cpp b/common/fw-update-helper.cpp index 179bf66b6d..ff635df36a 100644 --- a/common/fw-update-helper.cpp +++ b/common/fw-update-helper.cpp @@ -148,7 +148,7 @@ namespace rs2 _progress = 30; - // Write signed firmware to appropriate file descritptor + // Write signed firmware to appropriate file descriptor std::ofstream fw_path_in_device(_dev.get_info(RS2_CAMERA_INFO_DFU_DEVICE_PATH), std::ios::binary); if (fw_path_in_device) { @@ -245,7 +245,7 @@ namespace rs2 } else { - log_backup_status = "Back-up camera flash cannot be saved"; + log_backup_status = "Backup flash is not supported"; } } catch( const std::exception& e ) @@ -268,7 +268,9 @@ namespace rs2 } } - log(log_backup_status); + if ( !log_backup_status.empty() ) + log(log_backup_status); + @@ -297,6 +299,7 @@ namespace rs2 { if (serial == d.get_info(RS2_CAMERA_INFO_FIRMWARE_UPDATE_ID)) { + log( "DFU device '" + serial + "' found" ); dfu = d; return true; } @@ -332,29 +335,17 @@ namespace rs2 { _progress = float(next_progress); - log("Recovery device connected, starting update"); + log("Recovery device connected, starting update..\n" + "Internal write is in progress\n" + "Please DO NOT DISCONNECT the camera"); dfu.update(_fw, [&](const float progress) { _progress = ((ceil(progress * 10) / 10 * (90 - next_progress)) + next_progress); }); - // D400 devices takes 3 seconds after image transition until DFU process finish. - // D500 only starts the process after the image is transferred and it takes much time.. - if( !_is_d500_device ) - { - log( "Firmware Download completed, await DFU transition event" ); - std::this_thread::sleep_for( std::chrono::seconds( 3 ) ); - } - else - { - log( "Firmware Download completed, await DFU transition event\n" - "Internal write is in progress\n" - "Please DO NOT DISCONNECT the camera (might take a few minutes)"); - std::this_thread::sleep_for( std::chrono::seconds( 60 ) ); - } - - log("Firmware Update completed, waiting for device to reconnect"); + log( "Firmware Download completed, await DFU transition event" ); + std::this_thread::sleep_for( std::chrono::seconds( 3 ) ); } else { @@ -389,13 +380,14 @@ namespace rs2 } return false; - }, cleanup, std::chrono::seconds(_is_d500_device ? 120 : 60))) // TODO: HKR DFU issue - increased timeout from 60 to 120 seconds for HKR to complete FW write to flash + }, cleanup, std::chrono::seconds(60))) { fail("Original device did not reconnect in time!"); return; } - log("Device reconnected succesfully!"); + log( "Device reconnected successfully!\n" + "FW update process completed successfully" ); _progress = 100; diff --git a/include/librealsense2/h/rs_internal.h b/include/librealsense2/h/rs_internal.h index d0b9cda720..fdf5d4b583 100644 --- a/include/librealsense2/h/rs_internal.h +++ b/include/librealsense2/h/rs_internal.h @@ -22,10 +22,8 @@ extern "C" { /** * Firmware size constants */ - const int signed_fw_size = 0x18031C; - const int signed_sr300_size = 0x0C025C; - const int unsigned_fw_size = 0x200000; - const int unsigned_sr300_size = 0x100000; + const unsigned int signed_fw_size = 0x18031C; + const unsigned int unsigned_fw_size = 0x200000; /** * librealsense Recorder is intended for effective unit-testing diff --git a/src/ds/d400/d400-device.cpp b/src/ds/d400/d400-device.cpp index b19f8ac3df..83b2fd898b 100644 --- a/src/ds/d400/d400-device.cpp +++ b/src/ds/d400/d400-device.cpp @@ -1,6 +1,7 @@ // License: Apache 2.0. See LICENSE file in root directory. // Copyright(c) 2016 Intel Corporation. All Rights Reserved. +#include #include #include #include @@ -116,6 +117,11 @@ namespace librealsense bool d400_device::check_fw_compatibility( const std::vector< uint8_t > & image ) const { + // check if the given FW size matches the expected FW size + if( ( image.size() != signed_fw_size ) ) + throw librealsense::invalid_value_exception( + rsutils::string::from() << "Unsupported firmware binary image provided - " << image.size() << " bytes" ); + std::string fw_version = firmware_check_interface::extract_firmware_version_string( image ); auto it = ds::d400_device_to_fw_min_version.find( _pid ); diff --git a/src/ds/d400/d400-fw-update-device.cpp b/src/ds/d400/d400-fw-update-device.cpp index bbe85f9d88..3053fa4d45 100644 --- a/src/ds/d400/d400-fw-update-device.cpp +++ b/src/ds/d400/d400-fw-update-device.cpp @@ -4,25 +4,28 @@ #include "d400-fw-update-device.h" #include "d400-private.h" +#include + namespace librealsense { -ds_update_device::ds_update_device( std::shared_ptr< const device_info > const & dev_info, - std::shared_ptr< platform::usb_device > const & usb_device ) - : update_device( dev_info, usb_device ) - , _product_line( "D400" ) +ds_d400_update_device::ds_d400_update_device( + std::shared_ptr< const device_info > const & dev_info, + std::shared_ptr< platform::usb_device > const & usb_device ) + : update_device( dev_info, usb_device, "D400" ) { - auto info = usb_device->get_info(); - _name = ds::rs400_sku_names.find(info.pid) != ds::rs400_sku_names.end() ? ds::rs400_sku_names.at(info.pid) : "unknown"; + auto info = usb_device->get_info(); + _name = ds::rs400_sku_names.find(info.pid) != ds::rs400_sku_names.end() ? ds::rs400_sku_names.at(info.pid) : "unknown"; _serial_number = parse_serial_number(_serial_number_buffer); } - void ds_update_device::update(const void* fw_image, int fw_image_size, rs2_update_progress_callback_sptr callback) const - { - update_device::update(fw_image, fw_image_size, callback); - } - bool ds_update_device::check_fw_compatibility(const std::vector& image) const + bool ds_d400_update_device::check_fw_compatibility(const std::vector& image) const { + // check if the given FW size matches the expected FW size + if( image.size() != signed_fw_size ) + throw librealsense::invalid_value_exception( + rsutils::string::from() << "Unsupported firmware binary image provided - " << image.size() << " bytes" ); + std::string fw_version = extract_firmware_version_string(image); auto it = ds::d400_device_to_fw_min_version.find(_usb_device->get_info().pid); if (it == ds::d400_device_to_fw_min_version.end()) @@ -36,7 +39,7 @@ ds_update_device::ds_update_device( std::shared_ptr< const device_info > const & return result; } - std::string ds_update_device::parse_serial_number(const std::vector& buffer) const + std::string ds_d400_update_device::parse_serial_number(const std::vector& buffer) const { if (buffer.size() != sizeof(serial_number_data)) throw std::runtime_error("DFU - failed to parse serial number!"); diff --git a/src/ds/d400/d400-fw-update-device.h b/src/ds/d400/d400-fw-update-device.h index 91d9b3869a..ee9de524e5 100644 --- a/src/ds/d400/d400-fw-update-device.h +++ b/src/ds/d400/d400-fw-update-device.h @@ -7,25 +7,16 @@ namespace librealsense { - class ds_update_device : public update_device + class ds_d400_update_device : public update_device { public: - ds_update_device( std::shared_ptr< const device_info > const &, - std::shared_ptr< platform::usb_device > const & usb_device ); - virtual ~ds_update_device() = default; + ds_d400_update_device( std::shared_ptr< const device_info > const &, + std::shared_ptr< platform::usb_device > const & usb_device ); + virtual ~ds_d400_update_device() = default; - void update(const void* fw_image, int fw_image_size, rs2_update_progress_callback_sptr = nullptr) const override; virtual bool check_fw_compatibility(const std::vector& image) const override; - protected: - virtual const std::string& get_name() const override { return _name; } - virtual const std::string& get_product_line() const override { return _product_line; } - virtual const std::string& get_serial_number() const override { return _serial_number; } - std::string parse_serial_number(const std::vector& buffer) const; - private: - std::string _name; - std::string _product_line; - std::string _serial_number; + std::string parse_serial_number(const std::vector& buffer) const; }; } diff --git a/src/ds/d400/d400-private.h b/src/ds/d400/d400-private.h index ac942a7a37..423d7f4799 100644 --- a/src/ds/d400/d400-private.h +++ b/src/ds/d400/d400-private.h @@ -18,8 +18,8 @@ namespace librealsense const uint16_t RS430_PID = 0x0ad4; // AWG const uint16_t RS430_MM_PID = 0x0ad5; // AWGT const uint16_t RS_USB2_PID = 0x0ad6; // USB2 - const uint16_t RS_RECOVERY_PID = 0x0adb; - const uint16_t RS_USB2_RECOVERY_PID = 0x0adc; + const uint16_t RS_D400_RECOVERY_PID = 0x0adb; + const uint16_t RS_D400_USB2_RECOVERY_PID = 0x0adc; const uint16_t RS400_IMU_PID = 0x0af2; // IMU const uint16_t RS420_PID = 0x0af6; // PWG const uint16_t RS420_MM_PID = 0x0afe; // PWGT @@ -111,8 +111,8 @@ namespace librealsense { RS430_PID, "Intel RealSense D430"}, { RS430_MM_PID, "Intel RealSense D430 with Tracking Module"}, { RS_USB2_PID, "Intel RealSense USB2" }, - { RS_RECOVERY_PID, "Intel RealSense D4XX Recovery"}, - { RS_USB2_RECOVERY_PID, "Intel RealSense D4XX USB2 Recovery"}, + { RS_D400_RECOVERY_PID, "Intel RealSense D4XX Recovery"}, + { RS_D400_USB2_RECOVERY_PID, "Intel RealSense D4XX USB2 Recovery"}, { RS400_IMU_PID, "Intel RealSense IMU" }, { RS420_PID, "Intel RealSense D420"}, { RS420_MM_PID, "Intel RealSense D420 with Tracking Module"}, @@ -139,8 +139,8 @@ namespace librealsense {RS430_PID, "5.8.15.0"}, {RS430_MM_PID, "5.8.15.0"}, {RS_USB2_PID, "5.8.15.0"}, - {RS_RECOVERY_PID, "5.8.15.0"}, - {RS_USB2_RECOVERY_PID, "5.8.15.0"}, + {RS_D400_RECOVERY_PID, "5.8.15.0"}, + {RS_D400_USB2_RECOVERY_PID, "5.8.15.0"}, {RS400_IMU_PID, "5.8.15.0"}, {RS420_PID, "5.8.15.0"}, {RS420_MM_PID, "5.8.15.0"}, diff --git a/src/ds/d500/CMakeLists.txt b/src/ds/d500/CMakeLists.txt index eb38c43606..253217d7ae 100644 --- a/src/ds/d500/CMakeLists.txt +++ b/src/ds/d500/CMakeLists.txt @@ -10,6 +10,7 @@ target_sources(${LRS_TARGET} "${CMAKE_CURRENT_LIST_DIR}/d500-factory.cpp" "${CMAKE_CURRENT_LIST_DIR}/hw_monitor_extended_buffers.cpp" "${CMAKE_CURRENT_LIST_DIR}/d500-options.cpp" + "${CMAKE_CURRENT_LIST_DIR}/d500-fw-update-device.cpp" "${CMAKE_CURRENT_LIST_DIR}/d500-device.h" "${CMAKE_CURRENT_LIST_DIR}/d500-color.h" "${CMAKE_CURRENT_LIST_DIR}/d500-motion.h" @@ -18,4 +19,5 @@ target_sources(${LRS_TARGET} "${CMAKE_CURRENT_LIST_DIR}/hw_monitor_extended_buffers.h" "${CMAKE_CURRENT_LIST_DIR}/d500-options.h" "${CMAKE_CURRENT_LIST_DIR}/d500-info.h" + "${CMAKE_CURRENT_LIST_DIR}/d500-fw-update-device.h" ) diff --git a/src/ds/d500/d500-device.cpp b/src/ds/d500/d500-device.cpp index c7e4851fbf..c1e8f4bcdf 100644 --- a/src/ds/d500/d500-device.cpp +++ b/src/ds/d500/d500-device.cpp @@ -114,7 +114,7 @@ namespace librealsense void d500_device::update_flash(const std::vector& image, rs2_update_progress_callback_sptr callback, int update_mode) { - _ds_device_common->update_flash(image, callback, update_mode); + throw not_implemented_exception("D500 device does not support unsigned FW update"); } class d500_depth_sensor : public synthetic_sensor, public video_sensor_interface, public depth_stereo_sensor, public roi_sensor_base @@ -583,21 +583,7 @@ namespace librealsense if ((_device_capabilities & ds_caps::CAP_INTERCAM_HW_SYNC) == ds_caps::CAP_INTERCAM_HW_SYNC) { - if ((_device_capabilities & ds_caps::CAP_GLOBAL_SHUTTER) == ds_caps::CAP_GLOBAL_SHUTTER) - { - depth_sensor.register_option(RS2_OPTION_INTER_CAM_SYNC_MODE, - std::make_shared(*_hw_monitor, &raw_depth_sensor, 3)); - } - else if ((_device_capabilities & ds_caps::CAP_GLOBAL_SHUTTER) == ds_caps::CAP_GLOBAL_SHUTTER) - { - depth_sensor.register_option(RS2_OPTION_INTER_CAM_SYNC_MODE, - std::make_shared(*_hw_monitor, &raw_depth_sensor, 2)); - } - else - { - depth_sensor.register_option(RS2_OPTION_INTER_CAM_SYNC_MODE, - std::make_shared(*_hw_monitor, &raw_depth_sensor, 1)); - } + // Register RS2_OPTION_INTER_CAM_SYNC_MODE here if needed } roi_sensor_interface* roi_sensor = dynamic_cast(&depth_sensor); diff --git a/src/ds/d500/d500-fw-update-device.cpp b/src/ds/d500/d500-fw-update-device.cpp new file mode 100644 index 0000000000..9becfc3eb4 --- /dev/null +++ b/src/ds/d500/d500-fw-update-device.cpp @@ -0,0 +1,59 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2023 Intel Corporation. All Rights Reserved. + +#include "d500-fw-update-device.h" +#include "d500-private.h" + + +namespace librealsense +{ +ds_d500_update_device::ds_d500_update_device( std::shared_ptr< const device_info > const & dev_info, + std::shared_ptr< platform::usb_device > const & usb_device ) + : update_device( dev_info, usb_device, "D500" ) + { + auto info = usb_device->get_info(); + _name = ds::rs500_sku_names.find(info.pid) != ds::rs500_sku_names.end() ? ds::rs500_sku_names.at(info.pid) : "unknown"; + _serial_number = parse_serial_number(_serial_number_buffer); + } + + + bool ds_d500_update_device::check_fw_compatibility(const std::vector& image) const + { + // Currently we cannot extract FW version from HKR FW image + bool result = true; + + // TODO::: Once verified we can check against the minimal FW version map + std::string fw_version = extract_firmware_version_string(image); + LOG_INFO( "FW version extracted from the FW image is" + fw_version ); + + return result; + } + + std::string ds_d500_update_device::parse_serial_number(const std::vector& buffer) const + { + if (buffer.size() != sizeof(serial_number_data)) + throw std::runtime_error("DFU - failed to parse serial number!"); + + std::stringstream rv; + for (auto i = 0; i < ds::module_serial_size; i++) + rv << std::setfill('0') << std::setw(2) << std::hex << static_cast(buffer[i]); + + return rv.str(); + } + + 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))); + } + } +} diff --git a/src/ds/d500/d500-fw-update-device.h b/src/ds/d500/d500-fw-update-device.h new file mode 100644 index 0000000000..e856313fa8 --- /dev/null +++ b/src/ds/d500/d500-fw-update-device.h @@ -0,0 +1,23 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2023 Intel Corporation. All Rights Reserved. + +#pragma once + +#include "fw-update/fw-update-device.h" + +namespace librealsense +{ + class ds_d500_update_device : public update_device + { + public: + ds_d500_update_device( std::shared_ptr< const device_info > const &, + std::shared_ptr< platform::usb_device > const & usb_device ); + virtual ~ds_d500_update_device() = default; + + 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; + + private: + std::string parse_serial_number(const std::vector& buffer) const; + }; +} diff --git a/src/ds/ds-device-common.cpp b/src/ds/ds-device-common.cpp index 6663153e84..c6ad95632c 100644 --- a/src/ds/ds-device-common.cpp +++ b/src/ds/ds-device-common.cpp @@ -19,6 +19,7 @@ #include "proc/temporal-filter.h" #include +#include namespace librealsense { @@ -256,6 +257,15 @@ namespace librealsense void ds_device_common::update_flash(const std::vector& image, rs2_update_progress_callback_sptr callback, int update_mode) { + // check if the given FW size matches the expected FW size + if( image.size() != unsigned_fw_size ) + { + throw librealsense::invalid_value_exception( rsutils::string::from() + << "Unsupported firmware binary image (unsigned) provided - " + << image.size() << " bytes" ); + } + + if (_is_locked) throw std::runtime_error("this camera is locked and doesn't allow direct flash write, for firmware update use rs2_update_firmware method (DFU)"); diff --git a/src/fw-update/fw-update-device.cpp b/src/fw-update/fw-update-device.cpp index 08ac976776..a81ee234b4 100644 --- a/src/fw-update/fw-update-device.cpp +++ b/src/fw-update/fw-update-device.cpp @@ -113,11 +113,13 @@ namespace librealsense } update_device::update_device( std::shared_ptr< const device_info > const & dev_info, - std::shared_ptr< platform::usb_device > const & usb_device ) + std::shared_ptr< platform::usb_device > const & usb_device, + const std::string & product_line ) : _dev_info( dev_info ) , _usb_device( usb_device ) , _physical_port( usb_device->get_info().id ) - , _pid( rsutils::string::from() << std::uppercase << rsutils::string::hexdump( usb_device->get_info().pid ) ) + , _pid( rsutils::string::from() << std::uppercase << rsutils::string::hexdump( usb_device->get_info().pid )) + , _product_line( product_line ) { if (auto messenger = _usb_device->open(FW_UPDATE_INTERFACE_NUMBER)) { diff --git a/src/fw-update/fw-update-device.h b/src/fw-update/fw-update-device.h index 60c81008b1..9ed8a3e5b9 100644 --- a/src/fw-update/fw-update-device.h +++ b/src/fw-update/fw-update-device.h @@ -98,7 +98,8 @@ namespace librealsense { public: update_device( std::shared_ptr< const device_info > const &, - std::shared_ptr< platform::usb_device > const & usb_device ); + std::shared_ptr< platform::usb_device > const & usb_device, + const std::string & _product_line ); virtual ~update_device(); virtual void update(const void* fw_image, int fw_image_size, rs2_update_progress_callback_sptr = nullptr) const override; @@ -144,6 +145,9 @@ 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; void read_device_info(std::shared_ptr messenger); + virtual const std::string& get_name() const override { return _name; } + virtual const std::string& get_product_line() const override { return _product_line; } + virtual const std::string& get_serial_number() const override { return _serial_number; } const std::shared_ptr< const device_info > _dev_info; @@ -154,5 +158,8 @@ namespace librealsense std::string _physical_port; std::string _pid; bool _is_dfu_locked = false; + std::string _name; + std::string _product_line; + std::string _serial_number; }; } diff --git a/src/fw-update/fw-update-factory.cpp b/src/fw-update/fw-update-factory.cpp index 0dae4753ca..9e7477c608 100644 --- a/src/fw-update/fw-update-factory.cpp +++ b/src/fw-update/fw-update-factory.cpp @@ -5,7 +5,9 @@ #include "fw-update-device.h" #include "usb/usb-enumerator.h" #include "ds/d400/d400-private.h" +#include "ds/d500/d500-private.h" #include "ds/d400/d400-fw-update-device.h" +#include "ds/d500/d500-fw-update-device.h" #include @@ -17,9 +19,9 @@ namespace librealsense { int get_product_line(const platform::usb_device_info &usb_info) { - if( ds::RS_RECOVERY_PID == usb_info.pid ) + if( ds::RS_D400_RECOVERY_PID == usb_info.pid ) return RS2_PRODUCT_LINE_D400; - if( ds::RS_USB2_RECOVERY_PID == usb_info.pid ) + if( ds::RS_D400_USB2_RECOVERY_PID == usb_info.pid ) return RS2_PRODUCT_LINE_D400; return 0; } @@ -50,10 +52,15 @@ namespace librealsense auto usb = platform::usb_enumerator::create_usb_device(info); if (!usb) continue; - if (ds::RS_RECOVERY_PID == info.pid) - return std::make_shared< ds_update_device >( shared_from_this(), usb ); - if (ds::RS_USB2_RECOVERY_PID == info.pid) - return std::make_shared< ds_update_device >( shared_from_this(), usb ); + switch( info.pid ) + { + case ds::RS_D400_RECOVERY_PID: + case ds::RS_D400_USB2_RECOVERY_PID: + return std::make_shared< ds_d400_update_device >( shared_from_this(), usb ); + default: + // Do nothing + break; + } } } throw std::runtime_error( rsutils::string::from() diff --git a/src/rs.cpp b/src/rs.cpp index 0ec196deee..a4ba7823bb 100644 --- a/src/rs.cpp +++ b/src/rs.cpp @@ -3122,11 +3122,8 @@ void rs2_update_firmware_cpp(const rs2_device* device, const void* fw_image, int callback_ptr.reset( callback, []( rs2_update_progress_callback * p ) { p->release(); } ); VALIDATE_NOT_NULL(device); + VALIDATE_NOT_NULL(device->device); VALIDATE_NOT_NULL(fw_image); - // check if the given FW size matches the expected FW size - if (!val_in_range(fw_image_size, { signed_fw_size, signed_sr300_size })) - throw librealsense::invalid_value_exception( - rsutils::string::from() << "Unsupported firmware binary image provided - " << fw_image_size << " bytes" ); auto fwu = VALIDATE_INTERFACE(device->device, librealsense::update_device_interface); fwu->update( fw_image, fw_image_size, callback_ptr ); @@ -3136,11 +3133,8 @@ HANDLE_EXCEPTIONS_AND_RETURN(, device, fw_image) void rs2_update_firmware(const rs2_device* device, const void* fw_image, int fw_image_size, rs2_update_progress_callback_ptr callback, void* client_data, rs2_error** error) BEGIN_API_CALL { VALIDATE_NOT_NULL(device); + VALIDATE_NOT_NULL(device->device); VALIDATE_NOT_NULL(fw_image); - // check if the given FW size matches the expected FW size - if (!val_in_range(fw_image_size, { signed_fw_size, signed_sr300_size })) - throw librealsense::invalid_value_exception( - rsutils::string::from() << "Unsupported firmware binary image provided - " << fw_image_size << " bytes" ); auto fwu = VALIDATE_INTERFACE(device->device, librealsense::update_device_interface); @@ -3212,12 +3206,8 @@ void rs2_update_firmware_unsigned_cpp( const rs2_device * device, callback_ptr.reset( callback, []( rs2_update_progress_callback * p ) { p->release(); } ); VALIDATE_NOT_NULL(device); + VALIDATE_NOT_NULL(device->device); VALIDATE_NOT_NULL(image); - // check if the given FW size matches the expected FW size - if (!val_in_range(image_size, { unsigned_fw_size, unsigned_sr300_size })) - throw librealsense::invalid_value_exception( rsutils::string::from() - << "Unsupported firmware binary image (unsigned) provided - " - << image_size << " bytes" ); auto fwud = std::dynamic_pointer_cast(device->device); if (!fwud) @@ -3233,11 +3223,6 @@ void rs2_update_firmware_unsigned(const rs2_device* device, const void* image, i { VALIDATE_NOT_NULL(device); VALIDATE_NOT_NULL(image); - // check if the given FW size matches the expected FW size - if (!val_in_range(image_size, { unsigned_fw_size, unsigned_sr300_size })) - throw librealsense::invalid_value_exception( rsutils::string::from() - << "Unsupported firmware binary image (unsigned) provided - " - << image_size << " bytes" ); auto fwud = std::dynamic_pointer_cast(device->device); if (!fwud) @@ -3260,10 +3245,6 @@ int rs2_check_firmware_compatibility(const rs2_device* device, const void* fw_im { VALIDATE_NOT_NULL(device); VALIDATE_NOT_NULL(fw_image); - // check if the given FW size matches the expected FW size - if (!val_in_range(fw_image_size, { signed_fw_size, signed_sr300_size })) - throw librealsense::invalid_value_exception( - rsutils::string::from() << "Unsupported firmware binary image provided - " << fw_image_size << " bytes" ); auto fwud = std::dynamic_pointer_cast(device->device); if (!fwud) diff --git a/tools/fw-update/rs-fw-update.cpp b/tools/fw-update/rs-fw-update.cpp index 36019b3d35..0474646770 100644 --- a/tools/fw-update/rs-fw-update.cpp +++ b/tools/fw-update/rs-fw-update.cpp @@ -19,7 +19,7 @@ using namespace TCLAP; -#define WAIT_FOR_DEVICE_TIMEOUT 10 +#define WAIT_FOR_DEVICE_TIMEOUT 15 #if _WIN32 #include @@ -103,8 +103,8 @@ std::vector read_firmware_data(bool is_set, const std::string& file_pat void update(rs2::update_device fwu_dev, std::vector fw_image) { - std::cout << std::endl << "Firmware update started"<< std::endl << std::endl; - + std::cout << std::endl << "Firmware update started. Please don't disconnect device!"<< std::endl << std::endl; + if (ISATTY(FILENO(stdout))) { fwu_dev.update(fw_image, [&](const float progress) @@ -113,8 +113,9 @@ void update(rs2::update_device fwu_dev, std::vector fw_image) }); } else - fwu_dev.update(fw_image, [&](const float progress){}); - + { + fwu_dev.update(fw_image, [&](const float progress) {} ); + } std::cout << std::endl << std::endl << "Firmware update done" << std::endl; } @@ -140,7 +141,7 @@ void list_devices(rs2::context ctx) int write_fw_to_mipi_device( const rs2::device & dev, const std::vector< uint8_t > & fw_image ) { - // Write firmware to appropriate file descritptor + // Write firmware to appropriate file descriptor std::cout << std::endl << "Update can take up to 2 minutes" << std::endl; std::ofstream fw_path_in_device( dev.get_info( RS2_CAMERA_INFO_DFU_DEVICE_PATH ), std::ios::binary ); auto file_deleter = std::unique_ptr< std::ofstream, void ( * )( std::ofstream * ) >( &fw_path_in_device, @@ -151,11 +152,11 @@ int write_fw_to_mipi_device( const rs2::device & dev, const std::vector< uint8_t } ); if( fw_path_in_device ) { - bool done = false; + bool flush_done = false; std::thread show_progress_thread( - [&done]() + [&flush_done]() { - for( int i = 0; i < 101 && ! done; ++i ) // Show percentage [0-100] + for( int i = 0; i < 101 && ! flush_done; ++i ) // Show percentage [0-100] { printf( "%d%%\r", i ); std::cout.flush(); @@ -170,7 +171,7 @@ int write_fw_to_mipi_device( const rs2::device & dev, const std::vector< uint8_t { // Nothing to do, file goodbit is false } - done = true; + flush_done = true; show_progress_thread.join(); printf( " \r" ); // Delete progress, as it is not accurate, don't leave 85% when writing done if( ! fw_path_in_device.good() ) @@ -179,7 +180,7 @@ int write_fw_to_mipi_device( const rs2::device & dev, const std::vector< uint8_t return EXIT_FAILURE; } } - else + else { std::cout << std::endl << "Firmware Update failed - wrong path or permissions missing"; return EXIT_FAILURE; @@ -300,6 +301,7 @@ try { update_serial_number = recovery_device.get_info( RS2_CAMERA_INFO_FIRMWARE_UPDATE_ID ); ctx.set_devices_changed_callback( [&]( rs2::event_information & info ) { + std::lock_guard< std::mutex > lk( mutex ); for( auto && d : info.get_new_devices() ) { if( d.is< rs2::update_device >() ) @@ -308,7 +310,6 @@ try if( recovery_sn == update_serial_number ) { std::cout << "... found it" << std::endl; - std::lock_guard< std::mutex > lk( mutex ); cv.notify_one(); break; } @@ -320,7 +321,7 @@ try std::cout << "Waiting for new device..." << std::endl; { std::unique_lock< std::mutex > lk( mutex ); - if( cv.wait_for( lk, std::chrono::seconds( 5 ) ) == std::cv_status::timeout ) + if( cv.wait_for( lk, std::chrono::seconds( WAIT_FOR_DEVICE_TIMEOUT ) ) == std::cv_status::timeout ) { std::cout << "... timed out!" << std::endl; return EXIT_FAILURE; @@ -378,124 +379,132 @@ try bool device_found = false; - for (auto&& d : devs) + for( auto&& d : devs ) { - if (!d.is() || !(d.supports(RS2_CAMERA_INFO_SERIAL_NUMBER) && d.supports(RS2_CAMERA_INFO_FIRMWARE_UPDATE_ID))) + if( !d.is() || !( d.supports( RS2_CAMERA_INFO_SERIAL_NUMBER ) && d.supports( RS2_CAMERA_INFO_FIRMWARE_UPDATE_ID ) ) ) continue; - if (d.supports(RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR)) + if( d.supports( RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR ) ) { std::string usb_type = d.get_info( RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR ); - if (usb_type.find("2.") != std::string::npos) { + if( usb_type.find( "2." ) != std::string::npos ) { std::cout << std::endl << "Warning! the camera is connected via USB 2 port, in case the process fails, connect the camera to a USB 3 port and try again" << std::endl; } } - update_serial_number = d.get_info(RS2_CAMERA_INFO_FIRMWARE_UPDATE_ID); + update_serial_number = d.get_info( RS2_CAMERA_INFO_FIRMWARE_UPDATE_ID ); - auto sn = d.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER); - if (sn != selected_serial_number && devs.size() != 1) + auto sn = d.get_info( RS2_CAMERA_INFO_SERIAL_NUMBER ); + if( sn != selected_serial_number && devs.size() != 1 ) continue; device_found = true; - auto fw = d.get_info(RS2_CAMERA_INFO_FIRMWARE_VERSION); - if (backup_arg.isSet()) + if( backup_arg.isSet() ) { - std::cout << std::endl << "Backing-up device flash: " << std::endl; + std::cout << std::endl << "Trying to back-up device flash" << std::endl; std::vector< uint8_t > flash; - if( ISATTY( FILENO( stdout ))) + if( ISATTY( FILENO( stdout ) ) ) { flash = d.as< rs2::updatable >().create_flash_backup( [&]( const float progress ) { printf( "\rFlash backup progress: %d[%%]", (int)( progress * 100 ) ); - } ); + } ); } else - flash = d.as().create_flash_backup([&](const float progress){}); - - auto temp = backup_arg.getValue(); - std::ofstream file(temp.c_str(), std::ios::binary); - auto file_deleter = std::unique_ptr< std::ofstream, void ( * )( std::ofstream * ) >( &file, - []( std::ofstream * file ) - { - if( file ) - file->close(); - } ); - try - { - file.write( (const char *)flash.data(), flash.size() ); - } - catch( ... ) + flash = d.as().create_flash_backup( [&]( const float progress ) {} ); + + if( flash.empty() ) { - // Nothing to do, file goodbit is false + std::cout << std::endl << "Backup flash is not supported"; } - if( ! file.good() ) + else { - std::cout << std::endl << "Creating backup file failed"; + auto temp = backup_arg.getValue(); + std::ofstream file( temp.c_str(), std::ios::binary ); + auto file_deleter = std::unique_ptr< std::ofstream, void ( * )( std::ofstream* ) >( &file, + []( std::ofstream* file ) + { + if( file ) + file->close(); + } ); + try + { + file.write( (const char*)flash.data(), flash.size() ); + } + catch( ... ) + { + // Nothing to do, file goodbit is false + } + if( !file.good() ) + { + std::cout << std::endl << "Creating backup file failed"; + } } } - if (!file_arg.isSet()) - continue; - - std::vector fw_image = read_firmware_data(file_arg.isSet(), file_arg.getValue()); + // FW DFU + if( file_arg.isSet() ) + { + std::vector fw_image = read_firmware_data( file_arg.isSet(), file_arg.getValue() ); - std::cout << std::endl << "Updating device: " << std::endl; - print_device_info(d); + std::cout << std::endl << "Updating device FW: " << std::endl; + print_device_info( d ); - // If device is D457 connected by MIPI connector - if( is_mipi_device( d ) ) - { - if( unsigned_arg.isSet() ) + // If device is D457 connected by MIPI connector + if( is_mipi_device( d ) ) { - std::cout << std::endl << "Only signed FW is currently supported for MIPI devices" << std::endl; - return EXIT_FAILURE; + if( unsigned_arg.isSet() ) + { + std::cout << std::endl << "Only signed FW is currently supported for MIPI devices" << std::endl; + return EXIT_FAILURE; + } + + return write_fw_to_mipi_device( d, fw_image ); } - return write_fw_to_mipi_device( d, fw_image ); - } + if( unsigned_arg.isSet() ) + { + std::cout << std::endl << "Firmware update started. Please don't disconnect device!" << std::endl << std::endl; - if (unsigned_arg.isSet()) - { - std::cout << std::endl << "Firmware update started" << std::endl << std::endl; + if( ISATTY( FILENO( stdout ) ) ) + { + d.as().update_unsigned( fw_image, [&]( const float progress ) + { + printf( "\rFirmware update progress: %d[%%]", (int)( progress * 100 ) ); + } ); + } + else + d.as().update_unsigned( fw_image, [&]( const float progress ) {} ); - if (ISATTY(FILENO(stdout))) - { - d.as().update_unsigned(fw_image, [&](const float progress) - { - printf("\rFirmware update progress: %d[%%]", (int)(progress * 100)); - }); + std::cout << std::endl << std::endl << "Firmware update done" << std::endl; } else - d.as().update_unsigned(fw_image, [&](const float progress){}); - - std::cout << std::endl << std::endl << "Firmware update done" << std::endl; - } - else - { - auto upd = d.as(); - // checking compatibility bewtween firmware and device - if (!upd.check_firmware_compatibility(fw_image)) { - std::stringstream ss; - ss << "This firmware version is not compatible with "; - ss << d.get_info(RS2_CAMERA_INFO_NAME) << std::endl; - std::cout << std::endl << ss.str() << std::endl; - return EXIT_FAILURE; - } + auto upd = d.as(); + // checking compatibility bewtween firmware and device + if( !upd.check_firmware_compatibility( fw_image ) ) + { + std::stringstream ss; + ss << "This firmware version is not compatible with "; + ss << d.get_info( RS2_CAMERA_INFO_NAME ) << std::endl; + std::cout << std::endl << ss.str() << std::endl; + return EXIT_FAILURE; + } - upd.enter_update_state(); + upd.enter_update_state(); - std::unique_lock lk(mutex); - if (!cv.wait_for(lk, std::chrono::seconds(WAIT_FOR_DEVICE_TIMEOUT), [&] { return new_fw_update_device; })) - { - std::cout << std::endl << "Failed to locate a device in FW update mode" << std::endl; - return EXIT_FAILURE; - } + std::unique_lock lk( mutex ); + if( !cv.wait_for( lk, std::chrono::seconds( WAIT_FOR_DEVICE_TIMEOUT ), [&] { return new_fw_update_device; } ) ) + { + std::cout << std::endl << "Failed to locate a device in FW update mode" << std::endl; + return EXIT_FAILURE; + } + + update( new_fw_update_device, fw_image ); - update(new_fw_update_device, fw_image); - done = true; - break; + done = true; + break; + } } } @@ -510,6 +519,7 @@ try return EXIT_FAILURE; } + std::cout << std::endl << "Waiting for device to reconnect..." << std::endl; std::unique_lock lk(mutex); cv.wait_for(lk, std::chrono::seconds(WAIT_FOR_DEVICE_TIMEOUT), [&] { return !done || new_device; });