Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DFU for D457 recovery device #12944

Merged
merged 4 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 32 additions & 15 deletions common/fw-update-helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,29 +128,33 @@ namespace rs2

void firmware_update_manager::process_mipi()
{
bool is_mipi_recovery = !(strcmp(_dev.get_info(RS2_CAMERA_INFO_PRODUCT_ID), "BBCD"));
if (!_is_signed)
{
fail("Signed FW update for MIPI device - This FW file is not signed ");
return;
}
auto dev_updatable = _dev.as<updatable>();
if(!(dev_updatable && dev_updatable.check_firmware_compatibility(_fw)))
if (!is_mipi_recovery)
{
fail("Firmware Update failed - fw version must be newer than version 5.13.1.1");
return;
auto dev_updatable = _dev.as<updatable>();
if(!(dev_updatable && dev_updatable.check_firmware_compatibility(_fw)))
{
fail("Firmware Update failed - fw version must be newer than version 5.13.1.1");
return;
}
}

log("Burning Signed Firmware on MIPI device");

// Enter DFU mode
auto device_debug = _dev.as<rs2::debug_protocol>();
uint32_t dfu_opcode = 0x1e;
device_debug.build_command(dfu_opcode, 1);

if (!is_mipi_recovery)
{
// Enter DFU mode
auto device_debug = _dev.as<rs2::debug_protocol>();
uint32_t dfu_opcode = 0x1e;
device_debug.build_command(dfu_opcode, 1);
}
_progress = 30;

rs2_camera_info _dfu_port_info = (is_mipi_recovery)?(RS2_CAMERA_INFO_PHYSICAL_PORT):(RS2_CAMERA_INFO_DFU_DEVICE_PATH);
// 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);
std::ofstream fw_path_in_device(_dev.get_info(_dfu_port_info), std::ios::binary);
if (fw_path_in_device)
{
fw_path_in_device.write(reinterpret_cast<const char*>(_fw.data()), _fw.size());
Expand All @@ -160,10 +164,20 @@ namespace rs2
fail("Firmware Update failed - wrong path or permissions missing");
return;
}
LOG_INFO("Firmware Update for MIPI device done.");
log("FW update process completed successfully.");
LOG_INFO("FW update process completed successfully.");
fw_path_in_device.close();

_progress = 100;
if (is_mipi_recovery)
{
log("For GMSL MIPI device please reboot, or reload d4xx driver\n"\
"sudo rmmod d4xx && sudo modprobe d4xx\n"\
"and restart the realsense-viewer");
LOG_INFO("For GMSL MIPI device please reboot, or reload d4xx driver\n"\
"sudo rmmod d4xx && sudo modprobe d4xx\n"\
"and restart the realsense-viewer");
}
_done = true;
// need to find a way to update the fw version field in the viewer
}
Expand All @@ -173,7 +187,10 @@ namespace rs2
invoker invoke)
{
// if device is D457, and fw is signed - using mipi specific procedure
if (!strcmp(_dev.get_info(RS2_CAMERA_INFO_PRODUCT_ID), "ABCD") && _is_signed)
if (_is_signed
&& (!strcmp(_dev.get_info(RS2_CAMERA_INFO_PRODUCT_ID), "ABCD")
|| !strcmp(_dev.get_info(RS2_CAMERA_INFO_PRODUCT_ID), "BBCD"))
)
{
process_mipi();
return;
Expand Down
4 changes: 3 additions & 1 deletion include/librealsense2/hpp/rs_device.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2017 Intel Corporation. All Rights Reserved.
// Copyright(c) 2017-2024 Intel Corporation. All Rights Reserved.

#ifndef LIBREALSENSE_RS2_DEVICE_HPP
#define LIBREALSENSE_RS2_DEVICE_HPP
Expand Down Expand Up @@ -61,6 +61,8 @@ namespace rs2
std::string pid = get_info( RS2_CAMERA_INFO_PRODUCT_ID );
if( pid == "ABCD" ) // Specific for D457
return "GMSL";
if( pid == "BBCD" ) // Specific for D457 Recovery DFU
return "GMSL";
return pid; // for DDS devices, this will be "DDS"
}
return {};
Expand Down
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ target_sources(${LRS_TARGET}
"${CMAKE_CURRENT_LIST_DIR}/platform/hid-data.h"
"${CMAKE_CURRENT_LIST_DIR}/platform/hid-device.h"
"${CMAKE_CURRENT_LIST_DIR}/platform/hid-device-info.h"
"${CMAKE_CURRENT_LIST_DIR}/platform/mipi-device.h"
"${CMAKE_CURRENT_LIST_DIR}/platform/mipi-device-info.h"
"${CMAKE_CURRENT_LIST_DIR}/platform/playback-device-info.h"
"${CMAKE_CURRENT_LIST_DIR}/platform/platform-utils.h"
"${CMAKE_CURRENT_LIST_DIR}/platform/platform-utils.cpp"
Expand Down
12 changes: 10 additions & 2 deletions src/backend-device-factory.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2023 Intel Corporation. All Rights Reserved.
// Copyright(c) 2023-2024 Intel Corporation. All Rights Reserved.

#include "backend-device-factory.h"
#include "context.h"
Expand Down Expand Up @@ -181,6 +181,7 @@ std::vector< std::shared_ptr< device_info > > backend_device_factory::query_devi
auto backend = _device_watcher->get_backend();
platform::backend_device_group group( backend->query_uvc_devices(),
backend->query_usb_devices(),
backend->query_mipi_devices(),
backend->query_hid_devices() );
auto devices = create_devices_from_group( group, requested_mask );
return { devices.begin(), devices.end() };
Expand Down Expand Up @@ -214,6 +215,13 @@ backend_device_factory::create_devices_from_group( platform::backend_device_grou
std::copy( begin( recovery_devices ), end( recovery_devices ), std::back_inserter( list ) );
}

// Supported mipi recovery devices
{
auto recovery_devices
= fw_update_info::pick_recovery_devices( ctx, devices.mipi_devices, mask );
std::copy( begin( recovery_devices ), end( recovery_devices ), std::back_inserter( list ) );
}

if( mask & RS2_PRODUCT_LINE_NON_INTEL )
{
auto uvc_devices
Expand All @@ -225,4 +233,4 @@ backend_device_factory::create_devices_from_group( platform::backend_device_grou
}


} // namespace librealsense
} // namespace librealsense
6 changes: 5 additions & 1 deletion src/backend.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2015 Intel Corporation. All Rights Reserved.
// Copyright(c) 2015-2024 Intel Corporation. All Rights Reserved.

#pragma once

#include "platform/uvc-device-info.h"
#include "platform/hid-device-info.h"
#include "platform/mipi-device-info.h"
#include "platform/stream-profile.h"
#include "platform/frame-object.h"

Expand All @@ -27,6 +28,7 @@ namespace librealsense
class device_watcher;
class hid_device;
class uvc_device;
class mipi_device;
class command_transfer;


Expand All @@ -42,6 +44,8 @@ namespace librealsense
virtual std::shared_ptr<hid_device> create_hid_device(hid_device_info info) const = 0;
virtual std::vector<hid_device_info> query_hid_devices() const = 0;

virtual std::vector<mipi_device_info> query_mipi_devices() const = 0;

virtual std::shared_ptr<device_watcher> create_device_watcher() const = 0;

virtual std::string get_device_serial(uint16_t device_vid, uint16_t device_pid, const std::string& device_uid) const
Expand Down
19 changes: 17 additions & 2 deletions src/ds/d400/d400-fw-update-device.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2019 Intel Corporation. All Rights Reserved.
// Copyright(c) 2019-2024 Intel Corporation. All Rights Reserved.

#include "d400-fw-update-device.h"
#include "d400-private.h"
Expand All @@ -18,6 +18,16 @@ ds_d400_update_device::ds_d400_update_device(
_serial_number = parse_serial_number(_serial_number_buffer);
}

ds_d400_update_device::ds_d400_update_device(
std::shared_ptr< const device_info > const & dev_info,
std::shared_ptr< platform::mipi_device > const & mipi_device )
: update_device( dev_info, mipi_device, "D400" )
{
auto info = mipi_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 = info.serial_number;
}


bool ds_d400_update_device::check_fw_compatibility(const std::vector<uint8_t>& image) const
{
Expand All @@ -27,7 +37,12 @@ ds_d400_update_device::ds_d400_update_device(
rsutils::string::from() << "Unsupported firmware binary image provided - " << image.size() << " bytes" );

std::string fw_version = ds::extract_firmware_version_string(image);
auto it = ds::d400_device_to_fw_min_version.find(_usb_device->get_info().pid);
uint16_t pid;
if (_usb_device != nullptr )
pid = _usb_device->get_info().pid;
else if (_mipi_device != nullptr )
pid = _mipi_device->get_info().pid;
auto it = ds::d400_device_to_fw_min_version.find(pid);
if (it == ds::d400_device_to_fw_min_version.end())
throw librealsense::invalid_value_exception(
rsutils::string::from() << "Min and Max firmware versions have not been defined for this device: "
Expand Down
4 changes: 3 additions & 1 deletion src/ds/d400/d400-fw-update-device.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2019 Intel Corporation. All Rights Reserved.
// Copyright(c) 2019-2024 Intel Corporation. All Rights Reserved.

#pragma once

Expand All @@ -12,6 +12,8 @@ namespace librealsense
public:
ds_d400_update_device( std::shared_ptr< const device_info > const &,
std::shared_ptr< platform::usb_device > const & usb_device );
ds_d400_update_device( std::shared_ptr< const device_info > const &,
std::shared_ptr< platform::mipi_device > const & mipi_device );
virtual ~ds_d400_update_device() = default;

virtual bool check_fw_compatibility(const std::vector<uint8_t>& image) const override;
Expand Down
9 changes: 6 additions & 3 deletions src/ds/d400/d400-private.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2015 Intel Corporation. All Rights Reserved.
// Copyright(c) 2015-2024 Intel Corporation. All Rights Reserved.

#pragma once

Expand Down Expand Up @@ -37,6 +37,7 @@ namespace librealsense
const uint16_t RS405_PID = 0x0B5B; // D405
const uint16_t RS455_PID = 0x0B5C; // D455
const uint16_t RS457_PID = 0xabcd; // D457
const uint16_t RS457_RECOVERY_PID = 0xbbcd; // D457 DFU Recovery

// d400 Devices supported by the current version
static const std::set<std::uint16_t> rs400_sku_pid = {
Expand Down Expand Up @@ -124,6 +125,7 @@ namespace librealsense
{ RS405_PID, "Intel RealSense D405" },
{ RS455_PID, "Intel RealSense D455" },
{ RS457_PID, "Intel RealSense D457" },
{ RS457_RECOVERY_PID, "Intel RealSense D457 Recovery"},
};

static std::map<uint16_t, std::string> d400_device_to_fw_min_version = {
Expand All @@ -150,7 +152,8 @@ namespace librealsense
{RS416_RGB_PID, "5.8.15.0" },
{RS405_PID, "5.12.11.8" },
{RS455_PID, "5.13.0.50" },
{RS457_PID, "5.13.1.1" }
{RS457_PID, "5.13.1.1" },
{RS457_RECOVERY_PID, "5.13.1.1" }
};

std::vector<platform::uvc_device_info> filter_d400_device_by_capability(
Expand Down Expand Up @@ -330,4 +333,4 @@ namespace librealsense
};

} // namespace ds
} // namespace librealsense
} // namespace librealsense
84 changes: 82 additions & 2 deletions src/fw-update/fw-update-device.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2019 Intel Corporation. All Rights Reserved.
// Copyright(c) 2019-2024 Intel Corporation. All Rights Reserved.

#include "fw-update-device.h"
#include "../types.h"
Expand All @@ -13,7 +13,12 @@
#include <stdexcept>
#include <algorithm>
#include <thread>
#include <string>
#include <regex>
#include <fstream>

#define DEFAULT_TIMEOUT 100
#define FW_UPDATE_INTERFACE_NUMBER 0
namespace librealsense
{
std::string get_formatted_fw_version(uint32_t fw_last_version)
Expand Down Expand Up @@ -174,12 +179,31 @@ namespace librealsense
}
}

update_device::update_device( std::shared_ptr< const device_info > const & dev_info,
std::shared_ptr< platform::mipi_device > const & mipi_device,
const std::string & product_line )
: _dev_info( dev_info )
, _mipi_device( mipi_device )
, _physical_port( mipi_device->get_info().dfu_device_path )
, _pid( rsutils::string::from() << std::uppercase << rsutils::string::hexdump( mipi_device->get_info().pid ))
, _product_line( product_line )
, _serial_number( mipi_device->get_info().serial_number )
{
std::ifstream fw_path_in_device(_physical_port.c_str());
if (!fw_path_in_device)
{
throw std::runtime_error("Firmware Update failed - wrong path or permissions missing");
return;
}
fw_path_in_device.close();
}

update_device::~update_device()
{

}

void update_device::update(const void* fw_image, int fw_image_size, rs2_update_progress_callback_sptr update_progress_callback) const
void update_device::update_usb(const void* fw_image, int fw_image_size, rs2_update_progress_callback_sptr update_progress_callback) const
{
// checking fw compatibility (covering the case of recovery device with wrong product line fw )
std::vector<uint8_t> buffer((uint8_t*)fw_image, (uint8_t*)fw_image + fw_image_size);
Expand Down Expand Up @@ -265,6 +289,62 @@ namespace librealsense
throw std::runtime_error("Firmware manifest failed");
}

void update_device::update_mipi(const void* fw_image, int fw_image_size, rs2_update_progress_callback_sptr update_progress_callback) const
{
// checking fw compatibility (covering the case of recovery device with wrong product line fw )
std::vector<uint8_t> buffer((uint8_t*)fw_image, (uint8_t*)fw_image + fw_image_size);
const size_t transfer_size = 1024;

size_t remaining_bytes = fw_image_size;
uint16_t blocks_count = uint16_t( fw_image_size / transfer_size );
uint16_t block_number = 0;

size_t offset = 0;
uint32_t transferred = 0;

if (!check_fw_compatibility(buffer))
throw librealsense::invalid_value_exception("Device: " + get_serial_number() + " failed to update firmware\nImage is unsupported for this device or corrupted");
// Write signed firmware to appropriate file descriptor

std::ofstream fw_path_in_device(_physical_port.c_str(), std::ios::binary);
if (!fw_path_in_device)
{
throw std::runtime_error("Firmware Update failed - wrong path or permissions missing");
return;
}
while (remaining_bytes > 0)
{
size_t chunk_size = std::min(transfer_size, remaining_bytes);

auto curr_block = ((uint8_t*)fw_image + offset);

fw_path_in_device.write(reinterpret_cast<const char*>(curr_block), chunk_size);

block_number++;
remaining_bytes -= chunk_size;
offset += chunk_size;

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);
}
LOG_INFO("Firmware Update for MIPI device done.");
fw_path_in_device.close();
}

void update_device::update(const void* fw_image, int fw_image_size, rs2_update_progress_callback_sptr update_progress_callback) const
{
if(_pid == "ABCD" || _pid == "BBCD")
{
update_mipi(fw_image, fw_image_size, update_progress_callback);
}
else
{
update_usb(fw_image, fw_image_size, update_progress_callback);
}
}

sensor_interface& update_device::get_sensor(size_t i)
{
throw std::runtime_error("try to get sensor from fw loader device");
Expand Down
Loading
Loading