backend-device-factory.cpp
Go to the documentation of this file.
1 // License: Apache 2.0. See LICENSE file in root directory.
2 // Copyright(c) 2023 Intel Corporation. All Rights Reserved.
3 
5 #include "context.h"
6 #include "backend.h"
9 
10 #include "backend-device.h"
11 #include "ds/d400/d400-info.h"
12 #include "ds/d500/d500-info.h"
14 #include "platform-camera.h"
15 
17 
20 #include <rsutils/signal.h>
21 #include <rsutils/json.h>
22 
23 
24 namespace librealsense {
25 namespace platform {
26 std::shared_ptr< backend > create_backend();
27 } // namespace platform
28 } // namespace librealsense
29 
30 
31 namespace librealsense {
32 
33 
34 std::vector< std::shared_ptr< platform::platform_device_info > >
35 subtract_sets( const std::vector< std::shared_ptr< platform::platform_device_info > > & first,
36  const std::vector< std::shared_ptr< platform::platform_device_info > > & second )
37 {
38  std::vector< std::shared_ptr< platform::platform_device_info > > results;
39  std::for_each(
40  first.begin(),
41  first.end(),
42  [&]( std::shared_ptr< platform::platform_device_info > const & data )
43  {
44  if( std::find_if(
45  second.begin(),
46  second.end(),
47  [&]( std::shared_ptr< platform::platform_device_info > const & new_dev )
48  {
49  return data->get_group().is_contained_in( new_dev->get_group() );
50  } )
51  == second.end() )
52  {
53  results.push_back( data );
54  }
55  } );
56  return results;
57 }
58 
59 
60 // This singleton creates the actual backend; as long as someone holds it, the backend will stay alive.
61 // The instance is held below by the device-watcher. I.e., the device-watcher triggers creation of the
62 // backend!
63 //
65 {
66  std::shared_ptr< platform::backend > const _backend;
67 
68 public:
70  : _backend( platform::create_backend() )
71  {
72  }
73 
74  std::shared_ptr< platform::backend > get() const { return _backend; }
75 };
76 
77 
79 
80 
81 // The device-watcher is also a singleton: we don't need multiple agents of notifications. It is held alive by the
82 // device-factory below, which is held per context. I.e., as long as the context is alive, we'll stay alive and the
83 // backend-singleton will stay alive.
84 //
85 // We are responsible for exposing the single notification from the platform-device-watcher to several subscribers:
86 // one device-watcher, but many contexts, each with further subscriptions.
87 //
89 {
90  // The device-watcher keeps a direct pointer to the backend instance, so we have to make sure it stays alive!
91  std::shared_ptr< backend_singleton > const _backend;
92  std::shared_ptr< platform::device_watcher > const _device_watcher;
94 
95 public:
97  : _backend( the_backend.instance() )
98  , _device_watcher( _backend->get()->create_device_watcher() )
99  {
100  assert( _device_watcher->is_stopped() );
101  _device_watcher->start(
102  [this]( platform::backend_device_group const & old, platform::backend_device_group const & curr )
103  { _callbacks.raise( old, curr ); } );
104  }
105 
107  {
108  return _callbacks.subscribe( std::move( cb ) );
109  }
110 
111  std::shared_ptr< platform::backend > const get_backend() const { return _backend->get(); }
112 };
113 
114 
116 
117 
118 std::shared_ptr< platform::backend > backend_device::get_backend()
119 {
120  auto singleton = the_backend.get();
121  if( ! singleton )
122  // Whoever is calling us, they are expecting a backend to exist, but it does not!
123  throw std::runtime_error( "backend not created yet!" );
124 
125  return singleton->get();
126 }
127 
128 
129 backend_device_factory::backend_device_factory( std::shared_ptr< context > const & ctx, callback && cb )
130  : super( ctx )
131  , _device_watcher( backend_device_watcher.instance() )
132  , _dtor( _device_watcher->subscribe(
133  [this, liveliness = std::weak_ptr< context >( ctx ), cb = std::move( cb )](
134  platform::backend_device_group const & old, platform::backend_device_group const & curr )
135  {
136  // the factory should be alive as long as the context is alive
137  auto live_ctx = liveliness.lock();
138  if( ! live_ctx )
139  return;
140 
141  auto old_list = create_devices_from_group( old, RS2_PRODUCT_LINE_ANY );
142  auto new_list = create_devices_from_group( curr, RS2_PRODUCT_LINE_ANY );
143 
144  std::vector< std::shared_ptr< device_info > > devices_removed;
145  for( auto & device_removed : subtract_sets( old_list, new_list ) )
146  {
147  devices_removed.push_back( device_removed );
148  LOG_DEBUG( "Device disconnected: " << device_removed->get_address() );
149  }
150 
151  std::vector< std::shared_ptr< device_info > > devices_added;
152  for( auto & device_added : subtract_sets( new_list, old_list ) )
153  {
154  devices_added.push_back( device_added );
155  LOG_DEBUG( "Device connected: " << device_added->get_address() );
156  }
157 
158  if( devices_removed.size() + devices_added.size() )
159  {
161  }
162  } ) )
163 {
164 }
165 
166 
168 {
169 }
170 
171 
172 std::vector< std::shared_ptr< device_info > > backend_device_factory::query_devices( unsigned requested_mask ) const
173 {
174  auto ctx = get_context();
175  if( ! ctx )
176  return {};
177 
178  if( ( requested_mask & RS2_PRODUCT_LINE_SW_ONLY ) || ( ctx->get_device_mask() & RS2_PRODUCT_LINE_SW_ONLY ) )
179  return {}; // We don't carry any software devices
180 
181  auto backend = _device_watcher->get_backend();
182  platform::backend_device_group group( backend->query_uvc_devices(),
183  backend->query_usb_devices(),
184  backend->query_hid_devices() );
185  auto devices = create_devices_from_group( group, requested_mask );
186  return { devices.begin(), devices.end() };
187 }
188 
189 
190 std::vector< std::shared_ptr< platform::platform_device_info > >
192 {
193  auto ctx = get_context();
194  std::vector< std::shared_ptr< platform::platform_device_info > > list;
195  unsigned const mask = context::combine_device_masks( requested_mask, ctx->get_device_mask() );
196  if( ! ( mask & RS2_PRODUCT_LINE_SW_ONLY ) )
197  {
199  {
200  auto d400_devices = d400_info::pick_d400_devices( ctx, devices );
201  std::copy( std::begin( d400_devices ), end( d400_devices ), std::back_inserter( list ) );
202  }
203 
205  {
206  auto d500_devices = d500_info::pick_d500_devices( ctx, devices );
207  std::copy( begin( d500_devices ), end( d500_devices ), std::back_inserter( list ) );
208  }
209 
210  // Supported recovery devices
211  {
212  auto recovery_devices
214  std::copy( begin( recovery_devices ), end( recovery_devices ), std::back_inserter( list ) );
215  }
216 
218  {
219  auto uvc_devices
221  std::copy( begin( uvc_devices ), end( uvc_devices ), std::back_inserter( list ) );
222  }
223  }
224  return list;
225 }
226 
227 
228 } // namespace librealsense
librealsense
Definition: algo.h:18
librealsense::platform_camera_info::pick_uvc_devices
static std::vector< std::shared_ptr< platform_camera_info > > pick_uvc_devices(const std::shared_ptr< context > &ctx, const std::vector< platform::uvc_device_info > &uvc_devices)
Definition: platform-camera.cpp:147
easyloggingpp.h
librealsense::backend_singleton::get
std::shared_ptr< platform::backend > get() const
Definition: backend-device-factory.cpp:74
rsutils::signal::raise
bool raise(Args... args)
Definition: signal.h:91
RS2_PRODUCT_LINE_ANY
#define RS2_PRODUCT_LINE_ANY
Definition: rs_context.h:116
test-device-discovery.devices_removed
int devices_removed
Definition: test-device-discovery.py:119
RS2_PRODUCT_LINE_D400
#define RS2_PRODUCT_LINE_D400
Definition: rs_context.h:119
librealsense::platform::device_changed_callback
std::function< void(backend_device_group old, backend_device_group curr) > device_changed_callback
Definition: device-watcher.h:15
librealsense::device_watcher_singleton::device_watcher_singleton
device_watcher_singleton()
Definition: backend-device-factory.cpp:96
librealsense::device_factory
Definition: device-factory.h:26
rsutils::shared_ptr_singleton
Definition: shared-ptr-singleton.h:29
librealsense::subtract_sets
std::vector< std::shared_ptr< platform::platform_device_info > > subtract_sets(const std::vector< std::shared_ptr< platform::platform_device_info > > &first, const std::vector< std::shared_ptr< platform::platform_device_info > > &second)
Definition: backend-device-factory.cpp:35
data
Definition: parser.hpp:153
devices
Definition: third-party/realdds/scripts/devices.py:1
LOG_DEBUG
#define LOG_DEBUG(...)
Definition: easyloggingpp.h:70
librealsense::platform::backend_device_group
Definition: backend-device-group.h:50
rsutils::signal::subscribe
subscription subscribe(callback &&func)
Definition: signal.h:80
librealsense::context
Definition: context.h:18
rsutils::signal
Definition: signal.h:35
librealsense::backend_device_factory::query_devices
std::vector< std::shared_ptr< device_info > > query_devices(unsigned mask) const override
Definition: backend-device-factory.cpp:172
librealsense::device_factory::get_context
std::shared_ptr< context > get_context() const
Definition: device-factory.h:44
RS2_PRODUCT_LINE_NON_INTEL
#define RS2_PRODUCT_LINE_NON_INTEL
Definition: rs_context.h:118
mask
GLint GLuint mask
Definition: glad/glad/glad.h:1460
librealsense::context::combine_device_masks
static unsigned combine_device_masks(unsigned requested_mask, unsigned mask_in_settings)
Definition: context.cpp:97
d500-info.h
librealsense::device_watcher_singleton::get_backend
const std::shared_ptr< platform::backend > get_backend() const
Definition: backend-device-factory.cpp:111
shared-ptr-singleton.h
librealsense::platform::create_backend
std::shared_ptr< backend > create_backend()
Definition: rsusb-backend-android.cpp:11
librealsense::device_watcher_singleton::_backend
const std::shared_ptr< backend_singleton > _backend
Definition: backend-device-factory.cpp:91
librealsense::d500_info::pick_d500_devices
static std::vector< std::shared_ptr< d500_info > > pick_d500_devices(std::shared_ptr< context > ctx, platform::backend_device_group &group)
Definition: d500-factory.cpp:129
librealsense::backend_device_watcher
static rsutils::shared_ptr_singleton< device_watcher_singleton > backend_device_watcher
Definition: backend-device-factory.cpp:115
librealsense::device_watcher_singleton
Definition: backend-device-factory.cpp:88
librealsense::device_watcher_singleton::_device_watcher
const std::shared_ptr< platform::device_watcher > _device_watcher
Definition: backend-device-factory.cpp:92
librealsense::backend_singleton
Definition: backend-device-factory.cpp:64
librealsense::backend_device_factory::_device_watcher
const std::shared_ptr< device_watcher_singleton > _device_watcher
Definition: backend-device-factory.h:36
librealsense::the_backend
static rsutils::shared_ptr_singleton< backend_singleton > the_backend
Definition: backend-device-factory.cpp:78
platform-camera.h
d400-info.h
librealsense::backend_device_factory::~backend_device_factory
~backend_device_factory()
Definition: backend-device-factory.cpp:167
backend.h
signal.h
librealsense::backend_device_factory::create_devices_from_group
std::vector< std::shared_ptr< platform::platform_device_info > > create_devices_from_group(platform::backend_device_group, int mask) const
Definition: backend-device-factory.cpp:191
device-watcher.h
librealsense::backend_singleton::backend_singleton
backend_singleton()
Definition: backend-device-factory.cpp:69
rspy.devices.get
def get(sn)
Definition: unit-tests/py/rspy/devices.py:466
assert
#define assert(condition)
Definition: lz4.c:245
librealsense::device_watcher_singleton::_callbacks
rsutils::signal< platform::backend_device_group const &, platform::backend_device_group const & > _callbacks
Definition: backend-device-factory.cpp:93
librealsense::fw_update_info::pick_recovery_devices
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)
Definition: fw-update-factory.cpp:32
std
Definition: android_helpers.h:13
first
GLint first
Definition: glad/glad/glad.h:2301
librealsense::device_watcher_singleton::subscribe
rsutils::subscription subscribe(platform::device_changed_callback &&cb)
Definition: backend-device-factory.cpp:106
librealsense::d400_info::pick_d400_devices
static std::vector< std::shared_ptr< d400_info > > pick_d400_devices(std::shared_ptr< context > ctx, platform::backend_device_group &gproup)
Definition: d400-factory.cpp:1103
rsutils::subscription
Definition: subscription.h:25
json.h
context.h
test-sanity.device_added
bool device_added
Definition: test-sanity.py:16
test-projection-from-recording.ctx
ctx
Definition: test-projection-from-recording.py:16
fw-update-factory.h
end
GLuint GLuint end
Definition: glad/glad/glad.h:2395
RS2_PRODUCT_LINE_SW_ONLY
#define RS2_PRODUCT_LINE_SW_ONLY
Definition: rs_context.h:124
test-device-discovery.devices_added
int devices_added
Definition: test-device-discovery.py:118
test-sanity.device_removed
bool device_removed
Definition: test-sanity.py:15
RS2_PRODUCT_LINE_D500
#define RS2_PRODUCT_LINE_D500
Definition: rs_context.h:123
platform-device-info.h
test-color_frame_frops.cb
def cb(frame, ts)
Definition: test-color_frame_frops.py:29
librealsense::backend_singleton::_backend
const std::shared_ptr< platform::backend > _backend
Definition: backend-device-factory.cpp:66
backend-device-factory.h
rs_context.h
Exposes RealSense context functionality for C compilers.
backend-device.h
librealsense::device_factory::callback
std::function< void(std::vector< std::shared_ptr< device_info > > const &devices_removed, std::vector< std::shared_ptr< device_info > > const &devices_added) > callback
Definition: device-factory.h:40


librealsense2
Author(s): LibRealSense ROS Team
autogenerated on Mon Apr 22 2024 02:12:55