From b9cb41c22b5fd0ddacd65e44fc9e6399b737f3bf Mon Sep 17 00:00:00 2001 From: Dmitry Perchanov Date: Tue, 16 Apr 2024 15:58:50 +0300 Subject: [PATCH] DFU for D457 recovery device --- include/librealsense2/hpp/rs_device.hpp | 2 + src/CMakeLists.txt | 1 + src/backend-device-factory.cpp | 10 +- src/backend.h | 5 + src/ds/d400/d400-fw-update-device.cpp | 17 ++- src/ds/d400/d400-fw-update-device.h | 2 + src/ds/d400/d400-private.h | 7 +- src/fw-update/fw-update-device.cpp | 80 +++++++++++++- src/fw-update/fw-update-device.h | 11 +- src/fw-update/fw-update-factory.cpp | 55 ++++++++-- src/fw-update/fw-update-factory.h | 6 ++ src/linux/backend-v4l2.cpp | 134 +++++++++++++++++++++++- src/linux/backend-v4l2.h | 17 +++ src/platform/backend-device-group.h | 31 ++++++ src/platform/mipi-device-info.h | 60 +++++++++++ src/platform/platform-device-info.h | 2 + src/platform/platform-utils.h | 1 + 17 files changed, 420 insertions(+), 21 deletions(-) create mode 100644 src/platform/mipi-device-info.h diff --git a/include/librealsense2/hpp/rs_device.hpp b/include/librealsense2/hpp/rs_device.hpp index f5dbd6e3f3c..bae55ce8938 100644 --- a/include/librealsense2/hpp/rs_device.hpp +++ b/include/librealsense2/hpp/rs_device.hpp @@ -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 {}; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4269fed0c0a..467dbe9672d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -116,6 +116,7 @@ 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-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" diff --git a/src/backend-device-factory.cpp b/src/backend-device-factory.cpp index d033b95c955..a867c14adf5 100644 --- a/src/backend-device-factory.cpp +++ b/src/backend-device-factory.cpp @@ -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() }; @@ -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 @@ -225,4 +233,4 @@ backend_device_factory::create_devices_from_group( platform::backend_device_grou } -} // namespace librealsense \ No newline at end of file +} // namespace librealsense diff --git a/src/backend.h b/src/backend.h index 7674300c7d9..8c5552322b3 100644 --- a/src/backend.h +++ b/src/backend.h @@ -5,6 +5,7 @@ #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" @@ -27,6 +28,7 @@ namespace librealsense class device_watcher; class hid_device; class uvc_device; + class mipi_device; class command_transfer; @@ -42,6 +44,9 @@ namespace librealsense virtual std::shared_ptr create_hid_device(hid_device_info info) const = 0; virtual std::vector query_hid_devices() const = 0; + virtual std::shared_ptr create_mipi_device(mipi_device_info info) const = 0; + virtual std::vector query_mipi_devices() const = 0; + virtual std::shared_ptr 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 diff --git a/src/ds/d400/d400-fw-update-device.cpp b/src/ds/d400/d400-fw-update-device.cpp index 822faa6ddd3..4a103c8f87e 100644 --- a/src/ds/d400/d400-fw-update-device.cpp +++ b/src/ds/d400/d400-fw-update-device.cpp @@ -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& image) const { @@ -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: " diff --git a/src/ds/d400/d400-fw-update-device.h b/src/ds/d400/d400-fw-update-device.h index ee9de524e58..4cff50fb86c 100644 --- a/src/ds/d400/d400-fw-update-device.h +++ b/src/ds/d400/d400-fw-update-device.h @@ -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& image) const override; diff --git a/src/ds/d400/d400-private.h b/src/ds/d400/d400-private.h index efd58cde693..10ae7f790b1 100644 --- a/src/ds/d400/d400-private.h +++ b/src/ds/d400/d400-private.h @@ -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 rs400_sku_pid = { @@ -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 d400_device_to_fw_min_version = { @@ -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 filter_d400_device_by_capability( @@ -330,4 +333,4 @@ namespace librealsense }; } // namespace ds -} // namespace librealsense \ No newline at end of file +} // namespace librealsense diff --git a/src/fw-update/fw-update-device.cpp b/src/fw-update/fw-update-device.cpp index 9455a4719e6..910df8a3495 100644 --- a/src/fw-update/fw-update-device.cpp +++ b/src/fw-update/fw-update-device.cpp @@ -13,7 +13,8 @@ #include #include #include - +#include +#include #define DEFAULT_TIMEOUT 100 #define FW_UPDATE_INTERFACE_NUMBER 0 namespace librealsense @@ -140,12 +141,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); + 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 buffer((uint8_t*)fw_image, (uint8_t*)fw_image + fw_image_size); @@ -223,6 +243,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 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, 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(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"); diff --git a/src/fw-update/fw-update-device.h b/src/fw-update/fw-update-device.h index 143358b1651..14ee39a3368 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 "src/platform/mipi-device-info.h" namespace librealsense { @@ -102,10 +103,15 @@ namespace librealsense update_device( std::shared_ptr< const device_info > const &, std::shared_ptr< platform::usb_device > const & usb_device, const std::string & _product_line ); + + update_device( std::shared_ptr< const device_info > const &, + std::shared_ptr< platform::mipi_device > const & mipi_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; - + virtual sensor_interface& get_sensor(size_t i) override; virtual const sensor_interface& get_sensor(size_t i) const override; @@ -143,6 +149,8 @@ namespace librealsense virtual void enable_recording(std::function recording_function) override; protected: + void update_usb(const void* fw_image, int fw_image_size, rs2_update_progress_callback_sptr = nullptr) const; + void update_mipi(const void* fw_image, int fw_image_size, rs2_update_progress_callback_sptr = nullptr) const; 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; @@ -155,6 +163,7 @@ namespace librealsense const std::shared_ptr< const device_info > _dev_info; const platform::rs_usb_device _usb_device; + const platform::rs_mipi_device _mipi_device; std::vector _serial_number_buffer; std::string _highest_fw_version; std::string _last_fw_version; diff --git a/src/fw-update/fw-update-factory.cpp b/src/fw-update/fw-update-factory.cpp index bc1e380e144..591d16ed2c1 100644 --- a/src/fw-update/fw-update-factory.cpp +++ b/src/fw-update/fw-update-factory.cpp @@ -42,25 +42,57 @@ namespace librealsense return list; } + std::vector< std::shared_ptr< fw_update_info > > fw_update_info::pick_recovery_devices( + std::shared_ptr< context > ctx, const std::vector< platform::mipi_device_info > & mipi_devices, int mask ) + { + std::vector< std::shared_ptr< fw_update_info > > list; + for (auto&& mipi : mipi_devices) + { + list.push_back(std::make_shared(ctx, mipi)); + } + return list; + } + std::shared_ptr fw_update_info::create_device() { auto devices = platform::usb_enumerator::query_devices_info(); - auto const & dfu_id = get_group().usb_devices.front().id; - for (auto&& info : devices) - { - if( info.id == dfu_id ) + auto & dfu_id = get_group().usb_devices.front().id; + + auto const & mipi_id = get_group().mipi_devices.front().id; + + if (&dfu_id != nullptr) { + for (auto&& info : devices) + { + if( info.id == dfu_id ) + { + auto usb = platform::usb_enumerator::create_usb_device(info); + if (!usb) + continue; + 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 ); + case ds::D555E_RECOVERY_PID: + return std::make_shared< ds_d500_update_device >( shared_from_this(), usb ); + default: + // Do nothing + break; + } + } + } + } + else { + for (auto&& info: get_group().mipi_devices) { - auto usb = platform::usb_enumerator::create_usb_device(info); - if (!usb) + auto mipi = platform::mipi_device::create_mipi_device(info); + if (!mipi) continue; 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 ); - case ds::D555E_RECOVERY_PID: - return std::make_shared< ds_d500_update_device >( shared_from_this(), usb ); + case 0xbbcd: + return std::make_shared< ds_d400_update_device >( shared_from_this(), mipi ); default: // Do nothing break; @@ -70,4 +102,5 @@ namespace librealsense throw std::runtime_error( rsutils::string::from() << "Failed to create FW update device, device id: " << dfu_id ); } + } diff --git a/src/fw-update/fw-update-factory.h b/src/fw-update/fw-update-factory.h index 7d0dcaf5f90..76c69a6ad30 100644 --- a/src/fw-update/fw-update-factory.h +++ b/src/fw-update/fw-update-factory.h @@ -19,9 +19,15 @@ namespace librealsense static std::vector< std::shared_ptr< fw_update_info > > pick_recovery_devices( std::shared_ptr< context > ctx, const std::vector< platform::usb_device_info > & usb_devices, int mask ); + static std::vector< std::shared_ptr< fw_update_info > > pick_recovery_devices( + std::shared_ptr< context > ctx, const std::vector< platform::mipi_device_info > & mipi_devices, int mask ); + explicit fw_update_info(std::shared_ptr ctx, platform::usb_device_info const & dfu) : platform_device_info( ctx, { { dfu } } ) {} + explicit fw_update_info(std::shared_ptr ctx, platform::mipi_device_info const & dfu) + : platform_device_info( ctx, { { dfu } } ) {} + std::string get_address() const override { return "recovery:" + super::get_address(); } private: diff --git a/src/linux/backend-v4l2.cpp b/src/linux/backend-v4l2.cpp index 974827d488c..366905536b9 100644 --- a/src/linux/backend-v4l2.cpp +++ b/src/linux/backend-v4l2.cpp @@ -696,6 +696,64 @@ namespace librealsense return video_paths; } + std::vector v4l_uvc_device::get_mipi_dfu_paths() + { + std::vector dfu_paths; + static const std::regex dfu_dev_pattern("./d4xx-dfu."); + // Enumerate all d4xx dfu devices present on the system + DIR * dir = opendir("/sys/class/d4xx-class"); + if(!dir) + { + LOG_INFO("Cannot access /sys/class/d4xx-class"); + return dfu_paths; + } + while (dirent * entry = readdir(dir)) + { + std::string name = entry->d_name; + if(name == "." || name == "..") continue; + std::string path = "/sys/class/d4xx-class/" + name; + std::string real_path{}; + char buff[PATH_MAX] = {0}; + if (realpath(path.c_str(), buff) != nullptr) + { + real_path = std::string(buff); + if (real_path.find("virtual") == std::string::npos) + continue; + if (!std::regex_search(real_path, dfu_dev_pattern)) + { + continue; + } + // if (get_devname_from_video_path(real_path, name)) + std::ifstream uevent_file(real_path + "/uevent"); + if (!uevent_file) + { + LOG_ERROR("Cannot access " + real_path + "/uevent"); + continue; + } + std::string uevent_line, devname; + while (std::getline(uevent_file, uevent_line) && (devname.empty())) + { + if (uevent_line.find("DEVNAME=") != std::string::npos) + { + devname = uevent_line.substr(uevent_line.find_last_of('=') + 1); + } + } + uevent_file.close(); + if (devname.empty()) + { + LOG_ERROR("No DEVNAME found for " + real_path); + continue; + } + if ( std::find(dfu_paths.begin(), dfu_paths.end(), devname) == dfu_paths.end() ) + { + dfu_paths.push_back(devname); + } + } + } + closedir(dir); + return dfu_paths; + } + bool v4l_uvc_device::is_usb_path_valid(const std::string& usb_video_path, const std::string& dev_name, std::string& busnum, std::string& devnum, std::string& devpath) { @@ -887,7 +945,8 @@ namespace librealsense // Note - jetson can use only bus_info, as card is different for each sensor and metadata node. info.unique_id = bus_info + "-" + std::to_string(cam_id); // use bus_info as per camera unique id for mipi // Get DFU node for MIPI camera - std::array dfu_device_paths = {"/dev/d4xx-dfu504", "/dev/d4xx-dfu-30-0010"}; + std::vector dfu_device_paths = get_mipi_dfu_paths(); + for (const auto& dfu_device_path: dfu_device_paths) { int vfd = open(dfu_device_path.c_str(), O_RDONLY | O_NONBLOCK); if (vfd >= 0) { @@ -909,11 +968,64 @@ namespace librealsense return std::regex_search(video_path, uvc_pattern); } + void v4l_mipi_device::foreach_mipi_device( + std::function action) + { + typedef std::pair node_info; + std::vector mipi_devices; + + std::vector mipi_dfu_paths = get_mipi_dfu_paths(); + for(auto it = mipi_dfu_paths.begin(); mipi_dfu_paths.size() && it != mipi_dfu_paths.end(); ++it) + { + auto mipi_dfu_path = "/dev/" + *it; + std::string dfu_ver; + for (int retry = 10; retry; retry--) { + std::ifstream fw_path_in_device(mipi_dfu_path); + std::getline(fw_path_in_device, dfu_ver); + if (dfu_ver.size()) { + fw_path_in_device.close(); + break; + } + fw_path_in_device.close(); + } + // look for "recovery" string, if no - skip. + if (dfu_ver.find("recovery") == std::string::npos) + continue; + mipi_device_info info{}; + info.pid = 0xbbcd; + info.vid = 0x8086; + info.id = *it; + info.device_path = mipi_dfu_path; + info.unique_id = *it; + info.dfu_device_path = mipi_dfu_path; + // The expected string is "DFU info: recovery: 209443110028" + std::string delimiter = ":"; + dfu_ver.erase(0, dfu_ver.find(delimiter) + delimiter.length()); + dfu_ver.erase(0, dfu_ver.find(delimiter) + delimiter.length()); + // Trim leading whitespace + dfu_ver.erase(0, dfu_ver.find_first_not_of(' ')); + info.serial_number = dfu_ver; + mipi_devices.emplace_back(info, *it); + } + try + { + // Dispatch registration for enumerated MIPI Recovery devices + for (auto&& dev : mipi_devices) + action(dev.first, dev.second); + } + catch(const std::exception & e) + { + LOG_ERROR("Registration of MIPI recovery device failed: " << e.what()); + } + } + void v4l_uvc_device::foreach_uvc_device( std::function action) { std::vector video_paths = get_video_paths(); + std::vector mipi_dfu_paths = get_mipi_dfu_paths(); typedef std::pair node_info; std::vector uvc_nodes,uvc_devices; std::vector mipi_rs_enum_nodes; @@ -991,8 +1103,6 @@ namespace librealsense uvc_nodes.insert(uvc_nodes.end(), mipi_rs_enum_nodes.begin(), mipi_rs_enum_nodes.end()); } - // Collect UVC nodes info to bundle metadata and video - for(auto&& video_path : video_paths) { // following line grabs video0 from @@ -2769,6 +2879,7 @@ namespace librealsense std::vector v4l_backend::query_uvc_devices() const { std::vector uvc_nodes; + v4l_uvc_device::foreach_uvc_device( [&uvc_nodes](const uvc_device_info& i, const std::string&) { @@ -2792,6 +2903,23 @@ namespace librealsense return device_infos; } + std::shared_ptr v4l_backend::create_mipi_device(mipi_device_info info) const + { + return nullptr; + } + + std::vector v4l_backend::query_mipi_devices() const + { + std::vector mipi_nodes; + + v4l_mipi_device::foreach_mipi_device( + [&mipi_nodes](const mipi_device_info& i, const std::string&) + { + mipi_nodes.push_back(i); + }); + + return mipi_nodes; + } std::shared_ptr v4l_backend::create_hid_device(hid_device_info info) const { return std::make_shared(info); diff --git a/src/linux/backend-v4l2.h b/src/linux/backend-v4l2.h index 6eb46b8851b..7a405ac3c2e 100644 --- a/src/linux/backend-v4l2.h +++ b/src/linux/backend-v4l2.h @@ -318,6 +318,7 @@ namespace librealsense const std::string&)> action); static std::vector get_video_paths(); + static std::vector get_mipi_dfu_paths(); static bool is_usb_path_valid(const std::string& usb_video_path, const std::string &dev_name, std::string &busnum, std::string &devnum, std::string &devpath); @@ -473,6 +474,19 @@ namespace librealsense { public: v4l_mipi_device(const uvc_device_info& info, bool use_memory_map = true); + v4l_mipi_device(const mipi_device_info& info, bool use_memory_map = true); + + static void foreach_mipi_device( + std::function action); + + static std::vector get_video_paths(); + + static mipi_device_info get_info_from_mipi_device_path( + const std::string& video_path, const std::string& name); + + static void get_mipi_device_info(const std::string& dev_name, + std::string& bus_info, std::string& card); virtual ~v4l_mipi_device(); @@ -501,6 +515,9 @@ namespace librealsense std::shared_ptr create_hid_device(hid_device_info info) const override; std::vector query_hid_devices() const override; + std::shared_ptr create_mipi_device(mipi_device_info info) const override; + std::vector query_mipi_devices() const override; + std::shared_ptr create_device_watcher() const override; }; } diff --git a/src/platform/backend-device-group.h b/src/platform/backend-device-group.h index 24a535cf353..13ef7bacdad 100644 --- a/src/platform/backend-device-group.h +++ b/src/platform/backend-device-group.h @@ -8,6 +8,7 @@ #include "hid-device-info.h" #include "uvc-device-info.h" +#include "mipi-device-info.h" #include #include @@ -60,6 +61,22 @@ struct backend_device_group { } + backend_device_group( const std::vector< uvc_device_info > & uvc_devices, + const std::vector< usb_device_info > & usb_devices, + const std::vector< mipi_device_info > & mipi_devices, + const std::vector< hid_device_info > & hid_devices ) + : uvc_devices( uvc_devices ) + , usb_devices( usb_devices ) + , mipi_devices( mipi_devices ) + , hid_devices( hid_devices ) + { + } + + backend_device_group( const std::vector< mipi_device_info > & mipi_devices ) + : mipi_devices( mipi_devices ) + { + } + backend_device_group( const std::vector< usb_device_info > & usb_devices ) : usb_devices( usb_devices ) { @@ -74,6 +91,7 @@ struct backend_device_group std::vector< uvc_device_info > uvc_devices; std::vector< usb_device_info > usb_devices; + std::vector< mipi_device_info > mipi_devices; std::vector< hid_device_info > hid_devices; bool operator==( const backend_device_group & other ) const @@ -98,6 +116,13 @@ struct backend_device_group s += "\n\n"; } + s += mipi_devices.size() > 0 ? "mipi devices:\n" : ""; + for( auto mipi : mipi_devices ) + { + s += mipi; + s += "\n\n"; + } + s += hid_devices.size() > 0 ? "hid devices: \n" : ""; for( auto hid : hid_devices ) { @@ -125,6 +150,12 @@ struct backend_device_group == second_data.usb_devices.end() ) return false; } + for( auto & mipi : mipi_devices ) + { + if( std::find( second_data.mipi_devices.begin(), second_data.mipi_devices.end(), mipi ) + == second_data.mipi_devices.end() ) + return false; + } for( auto & hid : hid_devices ) { if( std::find( second_data.hid_devices.begin(), second_data.hid_devices.end(), hid ) diff --git a/src/platform/mipi-device-info.h b/src/platform/mipi-device-info.h new file mode 100644 index 00000000000..80b42ab6f09 --- /dev/null +++ b/src/platform/mipi-device-info.h @@ -0,0 +1,60 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2024 Intel Corporation. All Rights Reserved. + +#pragma once + +#include +#include + + +namespace librealsense { +namespace platform { + + +struct mipi_device_info +{ + std::string id; + uint16_t vid; + uint16_t pid; + std::string unique_id; + std::string device_path; + std::string dfu_device_path; + std::string serial_number; + + operator std::string() + { + std::ostringstream s; + s << "id- " << id << "\nvid- " << std::hex << vid << "\npid- " << std::hex << pid << "\nunique_id- " + << unique_id << "\npath- " << device_path; + + return s.str(); + } +}; + + +inline bool operator==( const mipi_device_info & a, const mipi_device_info & b ) +{ + return ( a.id == b.id ) && ( a.vid == b.vid ) && ( a.pid == b.pid ) && ( a.unique_id == b.unique_id ) + && ( a.device_path == b.device_path ); +} + +class mipi_device; +typedef std::shared_ptr rs_mipi_device; + +class mipi_device +{ +public: + mipi_device(const mipi_device_info& info) : _info(info) {} + virtual ~mipi_device() = default; + static rs_mipi_device create_mipi_device(const mipi_device_info& info) + { + return std::make_shared(info); + } + const mipi_device_info get_info() const { return _info; }; +private: + const mipi_device_info _info; +}; + + +} // namespace platform +} // namespace librealsense diff --git a/src/platform/platform-device-info.h b/src/platform/platform-device-info.h index 0f4afb2c99b..265bf7352f3 100644 --- a/src/platform/platform-device-info.h +++ b/src/platform/platform-device-info.h @@ -39,6 +39,8 @@ class platform_device_info : public device_info return _group.uvc_devices.front().device_path; if( ! _group.usb_devices.empty() ) return _group.usb_devices.front().id; + if( ! _group.mipi_devices.empty() ) + return _group.mipi_devices.front().id; throw std::runtime_error( "non-standard platform-device-info" ); } diff --git a/src/platform/platform-utils.h b/src/platform/platform-utils.h index 1eb20e77f3b..bb3db5748aa 100644 --- a/src/platform/platform-utils.h +++ b/src/platform/platform-utils.h @@ -15,6 +15,7 @@ namespace platform { struct uvc_device_info; struct hid_device_info; struct usb_device_info; +struct mipi_device_info; // Helper functions for device list manipulation: