mf-backend.cpp
Go to the documentation of this file.
1 // License: Apache 2.0. See LICENSE file in root directory.
2 // Copyright(c) 2015 Intel Corporation. All Rights Reserved.
3 #if (_MSC_FULL_VER < 180031101)
4  #error At least Visual Studio 2013 Update 4 is required to compile this backend
5 #endif
6 
7 #include "mf-backend.h"
8 #include "mf-uvc.h"
9 #include "mf-hid.h"
10 #include "usb/usb-device.h"
11 #include "usb/usb-enumerator.h"
12 #include "../types.h"
13 #include <mfapi.h>
14 #include <chrono>
15 #include <Windows.h>
16 #include <dbt.h>
17 #include <cctype> // std::tolower
18 
19 #include "../tm2/tm-boot.h"
20 
21 namespace librealsense
22 {
23  namespace platform
24  {
26  {
27  // In applications that have COM initializations on other threads using
28  // COINIT_APARTMENTTHREADED (like the Qt framework, for example), using
29  // COINIT_MULTITHREADED can lead to a deadlock inside COM functions.
30 #ifdef COM_MULTITHREADED
31  CoInitializeEx(nullptr, COINIT_MULTITHREADED); // when using COINIT_APARTMENTTHREADED, calling _pISensor->SetEventSink(NULL) to stop sensor can take several seconds
32 #else
33  CoInitializeEx( nullptr, COINIT_APARTMENTTHREADED ); // Apartment model
34 #endif
35 
36  MFStartup(MF_VERSION, MFSTARTUP_NOSOCKET);
37  }
38 
40  {
41  try {
42  MFShutdown();
43  CoUninitialize();
44  }
45  catch(...)
46  {
47  // TODO: Write to log
48  }
49  }
50 
51  std::shared_ptr<uvc_device> wmf_backend::create_uvc_device(uvc_device_info info) const
52  {
53  return std::make_shared<retry_controls_work_around>(
54  std::make_shared<wmf_uvc_device>(info, shared_from_this()));
55  }
56 
57  std::shared_ptr<backend> create_backend()
58  {
59  return std::make_shared<wmf_backend>();
60  }
61 
62  std::vector<uvc_device_info> wmf_backend::query_uvc_devices() const
63  {
64  std::vector<uvc_device_info> devices;
65 
66  auto action = [&devices, this](const uvc_device_info& info, IMFActivate*)
67  {
69  device_info.serial = this->get_device_serial(info.vid, info.pid, info.unique_id);
70  devices.push_back(device_info);
71  };
72 
74 
75  return devices;
76  }
77 
78  std::shared_ptr<command_transfer> wmf_backend::create_usb_device(usb_device_info info) const
79  {
81  if(dev)
82  return std::make_shared<platform::command_transfer_usb>(dev);
83  return nullptr;
84  }
85 
86  std::vector<usb_device_info> wmf_backend::query_usb_devices() const
87  {
88  auto device_infos = usb_enumerator::query_devices_info();
89  // Give the device a chance to restart, if we don't catch
90  // it, the watcher will find it later.
91  if(tm_boot(device_infos)) {
92  std::this_thread::sleep_for(std::chrono::milliseconds(2000));
93  device_infos = usb_enumerator::query_devices_info();
94  }
95  return device_infos;
96  }
97 
99  std::shared_ptr<const wmf_backend> backend)
100  : _backend(std::move(backend)),
101  _cb(nullptr)
102  {
103  bool found = false;
104 
105  wmf_hid_device::foreach_hid_device([&](const hid_device_info& hid_dev_info, CComPtr<ISensor> sensor) {
106  if (hid_dev_info.unique_id == info.unique_id)
107  {
108  _connected_sensors.push_back(std::make_shared<wmf_hid_sensor>(hid_dev_info, sensor));
109  found = true;
110  }
111  });
112 
113  if (!found)
114  {
115  LOG_ERROR("hid device is no longer connected!");
116  }
117  }
118 
119  std::shared_ptr<hid_device> wmf_backend::create_hid_device(hid_device_info info) const
120  {
121  return std::make_shared<wmf_hid_device>(info, shared_from_this());
122  }
123 
124  std::vector<hid_device_info> wmf_backend::query_hid_devices() const
125  {
126  std::vector<hid_device_info> devices;
127 
128  auto action = [&devices](const hid_device_info& info, CComPtr<ISensor>)
129  {
130  devices.push_back(info);
131  };
132 
134 
135  return devices;
136  }
137 
138  std::shared_ptr<time_service> wmf_backend::create_time_service() const
139  {
140  return std::make_shared<os_time_service>();
141  }
142 
144  {
145  public:
147  {
148  _data._backend = backend;
149  _data._stopped = false;
150  _data._last = backend_device_group(backend->query_uvc_devices(), backend->query_usb_devices(), backend->query_hid_devices());
151  }
153 
155  {
156  std::lock_guard<std::mutex> lock(_m);
157  if (!_data._stopped) throw wrong_api_call_sequence_exception("Cannot start a running device_watcher");
158  _data._stopped = false;
159  _data._callback = std::move(callback);
160  _thread = std::thread([this]() { run(); });
161  }
162 
163  void stop() override
164  {
165  std::lock_guard<std::mutex> lock(_m);
166  if (!_data._stopped)
167  {
168  _data._stopped = true;
169  if (_thread.joinable()) _thread.join();
170  }
171  }
172  private:
173  std::thread _thread;
174  std::mutex _m;
175 
176  struct extra_data {
177  const backend * _backend;
180 
181  bool _stopped;
182  HWND hWnd;
183  HDEVNOTIFY hdevnotifyHW, hdevnotifyUVC, hdevnotify_sensor, hdevnotifyUSB;
184  } _data;
185 
186  void run()
187  {
188  WNDCLASS windowClass = {};
189  LPCWSTR SzWndClass = TEXT("MINWINAPP");
190  windowClass.lpfnWndProc = &on_win_event;
191  windowClass.lpszClassName = SzWndClass;
192  UnregisterClass(SzWndClass, nullptr);
193 
194  if (!RegisterClass(&windowClass))
195  LOG_WARNING("RegisterClass failed.");
196 
197  _data.hWnd = CreateWindow(SzWndClass, nullptr, 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, nullptr, &_data);
198  if (!_data.hWnd)
199  throw winapi_error("CreateWindow failed");
200 
201  MSG msg;
202 
203  while (!_data._stopped)
204  {
205  if (PeekMessage(&msg, _data.hWnd, 0, 0, PM_REMOVE))
206  {
207  TranslateMessage(&msg);
208  DispatchMessage(&msg);
209  }
210  else // Yield CPU resources, as this is required for connect/disconnect events only
211  std::this_thread::sleep_for(std::chrono::milliseconds(50));
212  }
213 
214  UnregisterDeviceNotification(_data.hdevnotifyHW);
215  UnregisterDeviceNotification(_data.hdevnotifyUVC);
216  UnregisterDeviceNotification(_data.hdevnotify_sensor);
217  DestroyWindow(_data.hWnd);
218  }
219 
220  static LRESULT CALLBACK on_win_event(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
221  {
222  LRESULT lRet = 1;
223 
224  switch (message)
225  {
226  case WM_CREATE:
227  SetWindowLongPtr(hWnd, GWLP_USERDATA, LONG_PTR(reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams));
228  if (!DoRegisterDeviceInterfaceToHwnd(hWnd))
229  case WM_QUIT:
230  {
231  auto data = reinterpret_cast<extra_data*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
232  data->_stopped = true;
233  break;
234  }
235  case WM_DEVICECHANGE:
236  {
237  //PDEV_BROADCAST_DEVICEINTERFACE b = (PDEV_BROADCAST_DEVICEINTERFACE)lParam;
238  // Output some messages to the window.
239  switch (wParam)
240  {
241  case DBT_DEVICEARRIVAL:
242  {
243  auto data = reinterpret_cast<extra_data*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
244  backend_device_group next(data->_backend->query_uvc_devices(), data->_backend->query_usb_devices(), data->_backend->query_hid_devices());
245  /*if (data->_last != next)*/ data->_callback(data->_last, next);
246  data->_last = next;
247  }
248  break;
249 
250  case DBT_DEVICEREMOVECOMPLETE:
251  {
252  auto data = reinterpret_cast<extra_data*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
253  auto next = data->_last;
254  std::wstring temp = reinterpret_cast<DEV_BROADCAST_DEVICEINTERFACE*>(lParam)->dbcc_name;
256  path.reserve(temp.length());
257  for (wchar_t ch : temp) {
258  if (ch != L'{') path.push_back(std::tolower(((char*)&ch)[0]));
259  else break;
260  }
261 
262  next.uvc_devices.erase(std::remove_if(next.uvc_devices.begin(), next.uvc_devices.end(), [&path](const uvc_device_info& info)
263  { return info.device_path.substr(0, info.device_path.find_first_of("{")) == path; }), next.uvc_devices.end());
264  // next.usb_devices.erase(std::remove_if(next.usb_devices.begin(), next.usb_devices.end(), [&path](const usb_device_info& info)
265  // { return info.device_path.substr(0, info.device_path.find_first_of("{")) == path; }), next.usb_devices.end());
266  next.usb_devices = data->_backend->query_usb_devices();
267  next.hid_devices.erase(std::remove_if(next.hid_devices.begin(), next.hid_devices.end(), [&path](const hid_device_info& info)
268  {
269  auto sub = info.device_path.substr(0, info.device_path.find_first_of("{"));
270  std::transform(sub.begin(), sub.end(), sub.begin(), ::tolower);
271  return sub == path;
272 
273  }), next.hid_devices.end());
274 
275  /*if (data->_last != next)*/ data->_callback(data->_last, next);
276  data->_last = next;
277  }
278  break;
279  }
280  break;
281  }
282 
283  default:
284  // Send all other messages on to the default windows handler.
285  lRet = DefWindowProc(hWnd, message, wParam, lParam);
286  break;
287  }
288 
289  return lRet;
290  }
291 
292  static BOOL DoRegisterDeviceInterfaceToHwnd(HWND hWnd)
293  {
294  auto data = reinterpret_cast<extra_data*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
295 
296  //===========================register HWmonitor events==============================
297  const GUID classGuid = { 0x175695cd, 0x30d9, 0x4f87, 0x8b, 0xe3, 0x5a, 0x82, 0x70, 0xf4, 0x9a, 0x31 };
298  DEV_BROADCAST_DEVICEINTERFACE devBroadcastDeviceInterface;
299  devBroadcastDeviceInterface.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
300  devBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
301  devBroadcastDeviceInterface.dbcc_classguid = classGuid;
302  devBroadcastDeviceInterface.dbcc_reserved = 0;
303 
304  data->hdevnotifyHW = RegisterDeviceNotification(hWnd,
305  &devBroadcastDeviceInterface,
306  DEVICE_NOTIFY_WINDOW_HANDLE);
307  if (data->hdevnotifyHW == NULL)
308  {
309  LOG_WARNING("Register HW events Failed!\n");
310  return FALSE;
311  }
312 
314  DEV_BROADCAST_DEVICEINTERFACE di = { 0 };
315  di.dbcc_size = sizeof(di);
316  di.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
317  di.dbcc_classguid = KSCATEGORY_CAPTURE;
318 
319  data->hdevnotifyUVC = RegisterDeviceNotification(hWnd,
320  &di,
321  DEVICE_NOTIFY_WINDOW_HANDLE);
322  if (data->hdevnotifyUVC == nullptr)
323  {
324  UnregisterDeviceNotification(data->hdevnotifyHW);
325  LOG_WARNING("Register UVC events Failed!\n");
326  return FALSE;
327  }
328 
330  DEV_BROADCAST_DEVICEINTERFACE di_sensor = { 0 };
331  di_sensor.dbcc_size = sizeof(di_sensor);
332  di_sensor.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
333  di_sensor.dbcc_classguid = KSCATEGORY_SENSOR_CAMERA;
334 
335  data->hdevnotify_sensor = RegisterDeviceNotification(hWnd,
336  &di_sensor,
337  DEVICE_NOTIFY_WINDOW_HANDLE);
338  if (data->hdevnotify_sensor == nullptr)
339  {
340  UnregisterDeviceNotification(data->hdevnotify_sensor);
341  LOG_WARNING("Register UVC events Failed!\n");
342  return FALSE;
343  }
344 
346  static const GUID GUID_DEVINTERFACE_HID =
347  { 0x4d1e55b2,0xf16f,0x11cf,{0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30} };
348 
349  DEV_BROADCAST_DEVICEINTERFACE hid_sensor = { 0 };
350  hid_sensor.dbcc_size = sizeof(hid_sensor);
351  hid_sensor.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
352  hid_sensor.dbcc_classguid = GUID_DEVINTERFACE_HID;
353 
354  data->hdevnotify_sensor = RegisterDeviceNotification(hWnd,
355  &hid_sensor,
356  DEVICE_NOTIFY_WINDOW_HANDLE);
357  if (data->hdevnotify_sensor == nullptr)
358  {
359  UnregisterDeviceNotification(data->hdevnotify_sensor);
360  LOG_WARNING("Register UVC events Failed!\n");
361  return FALSE;
362  }
363 
364  //===========================register FW Update device events==============================
365  const GUID usbClassGuid = { 0xa5dcbf10, 0x6530, 0x11d2, 0x90, 0x1f, 0x00, 0xc0, 0x4f, 0xb9, 0x51, 0xed };
366  DEV_BROADCAST_DEVICEINTERFACE usvDevBroadcastDeviceInterface;
367  usvDevBroadcastDeviceInterface.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
368  usvDevBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
369  usvDevBroadcastDeviceInterface.dbcc_classguid = usbClassGuid;
370  usvDevBroadcastDeviceInterface.dbcc_reserved = 0;
371 
372  data->hdevnotifyUSB = RegisterDeviceNotification(hWnd,
373  &usvDevBroadcastDeviceInterface,
374  DEVICE_NOTIFY_WINDOW_HANDLE);
375  if (data->hdevnotifyUSB == NULL)
376  {
377  LOG_WARNING("Register HW events Failed!\n");
378  return FALSE;
379  }
380 
381  return TRUE;
382  }
383  };
384 
385  std::shared_ptr<device_watcher> wmf_backend::create_device_watcher() const
386  {
387  return std::make_shared<win_event_device_watcher>(this);
388  }
389 
390  std::string wmf_backend::get_device_serial(uint16_t device_vid, uint16_t device_pid, const std::string& device_uid) const
391  {
392  std::string device_serial = "";
393  std::string location = "";
394  usb_spec spec = usb_undefined;
395 
396  platform::get_usb_descriptors(device_vid, device_pid, device_uid, location, spec, device_serial);
397 
398  return device_serial;
399  }
400  }
401 }
static const textual_icon lock
Definition: model-views.h:218
GLenum GLuint GLenum GLsizei const GLchar * message
virtual std::vector< uvc_device_info > query_uvc_devices() const =0
static rs_usb_device create_usb_device(const usb_device_info &info)
virtual std::vector< hid_device_info > query_hid_devices() const =0
static std::vector< usb_device_info > query_devices_info()
#define LOG_WARNING(...)
Definition: src/types.h:241
GLint location
GLsizei const GLchar *const * path
Definition: glext.h:4276
unsigned short uint16_t
Definition: stdint.h:79
GLsizei const GLchar *const * string
std::shared_ptr< command_transfer > create_usb_device(usb_device_info info) const override
Definition: mf-backend.cpp:78
std::vector< usb_device_info > query_usb_devices() const override
Definition: mf-backend.cpp:86
static const textual_icon stop
Definition: model-views.h:225
bool tm_boot(const std::vector< usb_device_info > &devices)
Definition: tm-boot.h:48
std::shared_ptr< backend > create_backend()
def info(name, value, persistent=False)
Definition: test.py:301
#define GUID_DEVINTERFACE_HID
Definition: win32_init.c:36
std::shared_ptr< device_watcher > create_device_watcher() const override
Definition: mf-backend.cpp:385
#define KSCATEGORY_SENSOR_CAMERA
Definition: mf-uvc.h:20
std::function< void(backend_device_group old, backend_device_group curr)> device_changed_callback
Definition: backend.h:574
devices
Definition: test-fg.py:9
std::shared_ptr< uvc_device > create_uvc_device(uvc_device_info info) const override
Definition: mf-backend.cpp:51
def run(include_folder_path, addon_folder_path)
Definition: enums.py:46
def callback(frame)
Definition: t265_stereo.py:91
wmf_hid_device(const hid_device_info &info, std::shared_ptr< const wmf_backend > backend)
Definition: mf-backend.cpp:98
#define LOG_ERROR(...)
Definition: src/types.h:242
std::vector< uvc_device_info > query_uvc_devices() const override
Definition: mf-backend.cpp:62
action
Definition: enums.py:62
virtual std::shared_ptr< time_service > create_time_service() const override
Definition: mf-backend.cpp:138
void next(auto_any_t cur, type2type< T, C > *)
Definition: foreach.hpp:757
std::string get_device_serial(uint16_t device_vid, uint16_t device_pid, const std::string &device_uid) const override
Definition: mf-backend.cpp:390
static const FGuid GUID
typename::boost::move_detail::remove_reference< T >::type && move(T &&t) BOOST_NOEXCEPT
static LRESULT CALLBACK on_win_event(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
Definition: mf-backend.cpp:220
virtual std::vector< usb_device_info > query_usb_devices() const =0
#define NULL
Definition: tinycthread.c:47
std::shared_ptr< hid_device > create_hid_device(hid_device_info info) const override
Definition: mf-backend.cpp:119
#define TRUE
Definition: tinycthread.c:50
std::vector< hid_device_info > query_hid_devices() const override
Definition: mf-backend.cpp:124
void start(device_changed_callback callback) override
Definition: mf-backend.cpp:154
static void foreach_hid_device(std::function< void(hid_device_info, CComPtr< ISensor >)> action)
Definition: mf-hid.cpp:365
GLuint GLenum GLenum transform
Definition: glext.h:11553
static BOOL DoRegisterDeviceInterfaceToHwnd(HWND hWnd)
Definition: mf-backend.cpp:292
#define FALSE
Definition: tinycthread.c:53
static void foreach_uvc_device(enumeration_callback action)
Definition: mf-uvc.cpp:710
Definition: parser.hpp:150
bool get_usb_descriptors(uint16_t device_vid, uint16_t device_pid, const std::string &device_uid, std::string &location, usb_spec &spec, std::string &serial)


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:47:21