backend-hid.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 
4 #include "metadata.h"
5 #include "backend-hid.h"
6 #include "backend.h"
7 #include "types.h"
8 
9 #include <rsutils/string/from.h>
10 
11 #include <thread>
12 #include <chrono>
13 #include <ctime>
14 #include <dirent.h>
15 #include <fcntl.h>
16 #include <unistd.h>
17 
18 #pragma GCC diagnostic ignored "-Woverflow"
19 
20 const size_t MAX_DEV_PARENT_DIR = 10;
21 
22 const uint8_t HID_METADATA_SIZE = 8; // bytes
23 const size_t HID_DATA_ACTUAL_SIZE = 6; // bytes
24 
25 const std::string IIO_DEVICE_PREFIX("iio:device");
26 const std::string IIO_ROOT_PATH("/sys/bus/iio/devices");
27 const std::string HID_CUSTOM_PATH("/sys/bus/platform/drivers/hid_sensor_custom");
28 
29 //#define DEBUG_HID
30 #ifdef DEBUG_HID
31 #define LOG_DEBUG_HID(...) do { CLOG(DEBUG ,LIBREALSENSE_ELPP_ID) << __VA_ARGS__; } while(false)
32 #else
33 #define LOG_DEBUG_HID(...)
34 #endif //DEBUG_HID
35 
36 namespace librealsense
37 {
38  namespace platform
39  {
40  hid_input::hid_input(const std::string& iio_device_path, const std::string& input_name)
41  {
42  info.device_path = iio_device_path;
43  static const std::string input_prefix = "in_";
44  // validate if input includes th "in_" prefix. if it is . remove it.
45  if (input_name.substr(0,input_prefix.size()) == input_prefix)
46  {
47  info.input = input_name.substr(input_prefix.size(), input_name.size());
48  }
49  else
50  {
51  info.input = input_name;
52  }
53 
54  init();
55  }
56 
58  {
59  try
60  {
61  enable( false );
62  }
63  catch(...)
64  {
65  LOG_DEBUG( "Error while disabling a hid device" );
66  }
67  }
68 
69  // enable scan input. doing so cause the input to be part of the data provided in the polling.
70  void hid_input::enable(bool is_enable)
71  {
72  auto input_data = is_enable ? 1 : 0;
73  // open the element requested and enable and disable.
74  auto element_path = info.device_path + "/scan_elements/" + "in_" + info.input + "_en";
75  std::ofstream iio_device_file(element_path);
76 
77  if (!iio_device_file.is_open())
78  {
79  throw linux_backend_exception(rsutils::string::from() << "Failed to open scan_element " << element_path);
80  }
81  iio_device_file << input_data;
82  iio_device_file.close();
83 
84  info.enabled = is_enable;
85  }
86 
87  // initialize the input by reading the input parameters.
89  {
90  char buffer[1024] = {};
91 
92  static const std::string input_suffix = "_en";
93  // check if input contains the "en" suffix, if it is . remove it.
94  if (info.input.substr(info.input.size()-input_suffix.size(), input_suffix.size()) == input_suffix) {
95  info.input = info.input.substr(0, info.input.size()-input_suffix.size());
96  }
97 
98  // read scan type.
99  auto read_scan_type_path = std::string(info.device_path + "/scan_elements/in_" + info.input + "_type");
100  std::ifstream device_type_file(read_scan_type_path);
101  if (!device_type_file)
102  {
103  throw linux_backend_exception(rsutils::string::from() << "Failed to open read_scan_type " << read_scan_type_path);
104  }
105 
106  device_type_file.getline(buffer, sizeof(buffer));
107  uint32_t pad_int;
108  char sign_char, endia_nchar;
109  // TODO: parse with regex
110  auto ret = std::sscanf(buffer,
111  "%ce:%c%u/%u>>%u",
112  &endia_nchar,
113  &sign_char,
114  &info.bits_used,
115  &pad_int,
116  &info.shift);
117 
118  if (ret < 0)
119  {
120  throw linux_backend_exception(rsutils::string::from() << "Failed to parse device_type " << read_scan_type_path);
121  }
122 
123  device_type_file.close();
124 
125  info.big_endian = (endia_nchar == 'b');
126  info.bytes = pad_int / 8;
127  info.is_signed = (sign_char == 's');
128 
129  if (info.bits_used == 64)
130  info.mask = ~0;
131  else
132  info.mask = (1ULL << info.bits_used) - 1;
133 
134 
135  // read scan index.
136  auto read_scan_index_path = info.device_path + "/scan_elements/in_" + info.input + "_index";
137  std::ifstream device_index_file(read_scan_index_path);
138  if (!device_index_file)
139  {
140  throw linux_backend_exception(rsutils::string::from() << "Failed to open scan_index " << read_scan_index_path);
141  }
142 
143  device_index_file.getline(buffer, sizeof(buffer));
145 
146  device_index_file.close();
147 
148  // read enable state.
149  auto read_enable_state_path = info.device_path + "/scan_elements/in_" + info.input + "_en";
150  std::ifstream device_enabled_file(read_enable_state_path);
151  if (!device_enabled_file)
152  {
153  throw linux_backend_exception(rsutils::string::from() << "Failed to open scan_index " << read_enable_state_path);
154  }
155 
156  device_enabled_file.getline(buffer, sizeof(buffer));
157  info.enabled = (std::stoi(buffer) == 0) ? false : true;
158 
159  device_enabled_file.close();
160  }
161 
163  : _fd(0),
164  _stop_pipe_fd{},
165  _custom_device_path(device_path),
166  _custom_sensor_name(sensor_name),
167  _custom_device_name(""),
168  _callback(nullptr),
169  _is_capturing(false),
170  _hid_thread(nullptr)
171  {
172  init();
173  }
174 
176  {
177  try
178  {
179  if (_is_capturing)
180  stop_capture();
181  }
182  catch(...)
183  {
184  LOG_ERROR("An error has occurred while hid_custom_sensor dtor()!");
185  }
186  }
187 
188  std::vector<uint8_t> hid_custom_sensor::get_report_data(const std::string& report_name, custom_sensor_report_field report_field)
189  {
190  static const std::map<custom_sensor_report_field, std::string> report_fields = {{minimum, "-minimum"},
191  {maximum, "-maximum"},
192  {name, "-name"},
193  {size, "-size"},
194  {unit_expo, "-unit-expo"},
195  {units, "-units"},
196  {value, "-value"}};
197  try{
198  auto& report_folder = _reports.at(report_name);
199  auto report_path = _custom_device_path + "/" + report_folder + "/" + report_folder + report_fields.at(report_field);
200  return read_report(report_path);
201  }
202  catch(std::out_of_range)
203  {
204  throw invalid_value_exception(rsutils::string::from() << "report directory name " << report_name << " not found!");
205  }
206  }
207 
208 
209  // start capturing and polling.
211  {
212  if (_is_capturing)
213  return;
214 
215  std::ostringstream device_path;
216  device_path << "/dev/" << _custom_device_name;
217 
218  auto read_device_path_str = device_path.str();
219  std::ifstream device_file(read_device_path_str);
220 
221  // find device in file system.
222  if (!device_file.good())
223  {
224  throw linux_backend_exception("custom hid device is busy or not found!");
225  }
226 
227  device_file.close();
228 
229  enable(true);
230 
231  const auto max_retries = 10;
232  auto retries = 0;
233  while(++retries < max_retries)
234  {
235  if ((_fd = open(read_device_path_str.c_str(), O_RDONLY | O_NONBLOCK)) > 0)
236  break;
237 
238  LOG_WARNING("open() failed!");
239  std::this_thread::sleep_for(std::chrono::milliseconds(5));
240  }
241 
242  if ((retries == max_retries) && (_fd <= 0))
243  {
244  enable(false);
245  throw linux_backend_exception("open() failed with all retries!");
246  }
247 
248  if (pipe(_stop_pipe_fd) < 0)
249  {
250  close(_fd);
251  enable(false);
252  throw linux_backend_exception("hid_custom_sensor: Cannot create pipe!");
253  }
254 
255  _callback = sensor_callback;
256  _is_capturing = true;
257  _hid_thread = std::unique_ptr<std::thread>(new std::thread([this, read_device_path_str](){
258  const uint32_t channel_size = 24; // TODO: why 24?
259  std::vector<uint8_t> raw_data(channel_size * hid_buf_len);
260 
261  do {
262  fd_set fds;
263  FD_ZERO(&fds);
264  FD_SET(_fd, &fds);
265  FD_SET(_stop_pipe_fd[0], &fds);
266 
267  int max_fd = std::max(_stop_pipe_fd[0], _fd);
268  size_t read_size = 0;
269 
270  struct timeval tv = {5,0};
271  LOG_DEBUG_HID("HID Select initiated");
272  auto val = select(max_fd + 1, &fds, nullptr, nullptr, &tv);
273  LOG_DEBUG_HID("HID Select done, val = " << val);
274  if (val < 0)
275  {
276  // TODO: write to log?
277  continue;
278  }
279  else if (val > 0)
280  {
281  if(FD_ISSET(_stop_pipe_fd[0], &fds))
282  {
283  if(!_is_capturing)
284  {
285  LOG_INFO("hid_custom_sensor: Stream finished");
286  return;
287  }
288  }
289  else if (FD_ISSET(_fd, &fds))
290  {
291  read_size = read(_fd, raw_data.data(), raw_data.size());
292  if (read_size <= 0 )
293  continue;
294  }
295  else
296  {
297  // TODO: write to log?
298  LOG_WARNING("HID unresolved event : after select->FD_ISSET");
299  continue;
300  }
301 
302  auto sz= read_size / channel_size;
303  if (sz > 2)
304  {
305  LOG_DEBUG("HID: Going to handle " << sz << " packets");
306  }
307  for (auto i = 0; i < read_size / channel_size; ++i)
308  {
309  auto p_raw_data = raw_data.data() + channel_size * i;
310 
311  // TODO: code refactoring to reduce latency
312  sensor_data sens_data{};
313  sens_data.sensor = hid_sensor{get_sensor_name()};
314 
315  sens_data.fo = {channel_size, channel_size, p_raw_data, p_raw_data};
316  this->_callback(sens_data);
317  }
318  if (sz > 2)
319  {
320  LOG_DEBUG("HID: Finished to handle " << sz << " packets");
321  }
322  }
323  else
324  {
325  LOG_WARNING("hid_custom_sensor: Frames didn't arrived within 5 seconds");
326  }
327  } while(this->_is_capturing);
328  }));
329  }
330 
332  {
333  if (!_is_capturing)
334  {
335  enable(false);
336  return;
337  }
338 
339  _is_capturing = false;
340  signal_stop();
341  _hid_thread->join();
342  enable(false);
343  _callback = nullptr;
344 
345  if(::close(_fd) < 0)
346  throw linux_backend_exception("hid_custom_sensor: close(_fd) failed");
347 
348  if(::close(_stop_pipe_fd[0]) < 0)
349  throw linux_backend_exception("hid_custom_sensor: close(_stop_pipe_fd[0]) failed");
350  if(::close(_stop_pipe_fd[1]) < 0)
351  throw linux_backend_exception("hid_custom_sensor: close(_stop_pipe_fd[1]) failed");
352 
353  _fd = 0;
354  _stop_pipe_fd[0] = _stop_pipe_fd[1] = 0;
355  }
356 
357  std::vector<uint8_t> hid_custom_sensor::read_report(const std::string& name_report_path)
358  {
359  auto fd = open(name_report_path.c_str(), O_RDONLY | O_NONBLOCK);
360  if (fd < 0)
361  throw linux_backend_exception("Failed to open report!");
362 
363  std::vector<uint8_t> buffer;
364  buffer.resize(MAX_INPUT);
365  auto read_size = read(fd, buffer.data(), buffer.size());
366  close(fd);
367 
368  if (read_size <= 0)
369  throw linux_backend_exception("Failed to read custom report!");
370 
371  buffer.resize(read_size);
372  buffer[buffer.size() - 1] = '\0'; // Replace '\n' with '\0'
373  return buffer;
374  }
375 
377  {
378  static const char* prefix_feature_name = "feature";
379  static const char* prefix_input_name = "input";
380  static const char* suffix_name_field = "name";
381  DIR* dir = nullptr;
382  struct dirent* ent = nullptr;
383  if ((dir = opendir(_custom_device_path.c_str())) != nullptr)
384  {
385  while ((ent = readdir(dir)) != nullptr)
386  {
387  auto str = std::string(ent->d_name);
388  if (str.find(prefix_feature_name) != std::string::npos ||
389  str.find(prefix_input_name) != std::string::npos)
390  {
391  DIR* report_dir = nullptr;
392  struct dirent* report_ent = nullptr;
393  auto report_path = _custom_device_path + "/" + ent->d_name;
394  if ((report_dir = opendir(report_path.c_str())) != nullptr)
395  {
396  while ((report_ent = readdir(report_dir)) != nullptr)
397  {
398  auto report_str = std::string(report_ent->d_name);
399  if (report_str.find(suffix_name_field) != std::string::npos)
400  {
401  auto name_report_path = report_path + "/" + report_ent->d_name;
402  auto buffer = read_report(name_report_path);
403 
404  std::string name_report(reinterpret_cast<char const*>(buffer.data()));
405  _reports.insert(std::make_pair(name_report, ent->d_name));
406  }
407  }
408  closedir(report_dir);
409  }
410  }
411  }
412  closedir(dir);
413  }
414 
415  // get device name
416  auto pos = _custom_device_path.find_last_of("/");
417  if (pos < _custom_device_path.size())
418  _custom_device_name = _custom_device_path.substr(pos + 1);
419  }
420 
422  {
423  auto input_data = state ? 1 : 0;
424  auto element_path = _custom_device_path + "/enable_sensor";
425  std::ofstream custom_device_file(element_path);
426 
427  if (!custom_device_file.is_open())
428  {
429  throw linux_backend_exception(rsutils::string::from() << "Failed to enable_sensor " << element_path);
430  }
431  custom_device_file << input_data;
432  custom_device_file.close();
433 
434  // Work-around for the HID custom driver failing to release resources,
435  // preventing the device to enter idle U3 mode
436  // reading out the value will refresh the device tree in kernel
437 // if (!state)
438 // {
439 // std::string feat_val("default");
440 // if(!(std::ifstream(_custom_device_path + "/feature-0-200309/feature-0-200309-value") >> feat_val))
441 // throw linux_backend_exception("Failed to read feat_val");
442 // std::cout << "Feat value is " << feat_val << std::endl;
443 // }
444  }
445 
447  {
448  char buff[1];
449  buff[0] = 0;
450  if (write(_stop_pipe_fd[1], buff, 1) < 0)
451  {
452  throw linux_backend_exception("hid_custom_sensor: Could not signal video capture thread to stop. Error write to pipe.");
453  }
454  }
455 
456  iio_hid_sensor::iio_hid_sensor(const std::string& device_path, uint32_t frequency, float sensitivity)
457  : _stop_pipe_fd{},
458  _fd(0),
459  _iio_device_number(0),
460  _iio_device_path(device_path),
461  _sensor_name(""),
462  _sampling_frequency_name(""),
463  _callback(nullptr),
464  _is_capturing(false),
465  _pm_dispatcher(16) // queue for async power management commands
466  {
467  init(frequency, sensitivity);
468  }
469 
471  {
472  try
473  {
474  try {
475  // Ensure PM sync
477  stop_capture();
478  } catch(...){}
479 
480  clear_buffer();
481  }
482  catch(...){}
483 
484  // clear inputs.
485  _inputs.clear();
486  }
487 
488  // start capturing and polling.
490  {
491  if (_is_capturing)
492  return;
493 
494  set_power(true);
495  std::ostringstream iio_read_device_path;
496  iio_read_device_path << "/dev/" << IIO_DEVICE_PREFIX << _iio_device_number;
497 
498  auto iio_read_device_path_str = iio_read_device_path.str();
499  std::ifstream iio_device_file(iio_read_device_path_str);
500 
501  // find iio_device in file system.
502  if (!iio_device_file.good())
503  {
504  throw linux_backend_exception("iio hid device is busy or not found!");
505  }
506 
507  iio_device_file.close();
508 
509  // count number of enabled count elements and sort by their index.
511 
512  const auto max_retries = 10;
513  auto retries = 0;
514  while(++retries < max_retries)
515  {
516  if ((_fd = open(iio_read_device_path_str.c_str(), O_RDONLY | O_NONBLOCK)) > 0)
517  break;
518 
519  LOG_WARNING("open() failed!");
520  std::this_thread::sleep_for(std::chrono::milliseconds(5));
521  }
522 
523  if ((retries == max_retries) && (_fd <= 0))
524  {
525  _channels.clear();
526  throw linux_backend_exception("open() failed with all retries!");
527  }
528 
529  if (pipe(_stop_pipe_fd) < 0)
530  {
531  close(_fd);
532  _channels.clear();
533  throw linux_backend_exception("iio_hid_sensor: Cannot create pipe!");
534  }
535 
536  _callback = sensor_callback;
537  _is_capturing = true;
538  _hid_thread = std::unique_ptr<std::thread>(new std::thread([this](){
539  const uint32_t channel_size = get_channel_size();
540  size_t raw_data_size = channel_size*hid_buf_len;
541 
542  std::vector<uint8_t> raw_data(raw_data_size);
543  auto metadata = has_metadata();
544 
545  do {
546  fd_set fds;
547  FD_ZERO(&fds);
548  FD_SET(_fd, &fds);
549  FD_SET(_stop_pipe_fd[0], &fds);
550 
551  int max_fd = std::max(_stop_pipe_fd[0], _fd);
552 
553  ssize_t read_size = 0;
554  struct timeval tv = {5, 0};
555  LOG_DEBUG_HID("HID IIO Select initiated");
556  auto val = select(max_fd + 1, &fds, nullptr, nullptr, &tv);
557  LOG_DEBUG_HID("HID IIO Select done, val = " << val);
558 
559  if (val < 0)
560  {
561  // TODO: write to log?
562  LOG_WARNING("iio_hid_sensor: select failed, return val = " << val);
563  continue;
564  }
565  else if (val > 0)
566  {
567  if(FD_ISSET(_stop_pipe_fd[0], &fds))
568  {
569  if(!_is_capturing)
570  {
571  LOG_INFO("iio_hid_sensor: Stream finished");
572  return;
573  }
574  }
575  else if (FD_ISSET(_fd, &fds))
576  {
577  read_size = read(_fd, raw_data.data(), raw_data_size);
578  if (read_size < 0 )
579  continue;
580  }
581  else
582  {
583  // TODO: write to log?
584  LOG_WARNING("HID IIO unresolved event : after select->FD_ISSET");
585  continue;
586  }
587 
588  auto sz= read_size / channel_size;
589  if (sz > 2)
590  {
591  LOG_DEBUG("HID: Going to handle " << sz << " packets");
592  }
593  // TODO: code refactoring to reduce latency
594  for (auto i = 0; i < sz; ++i)
595  {
596  auto now_ts = std::chrono::duration<double, std::milli>(std::chrono::system_clock::now().time_since_epoch()).count();
597  auto p_raw_data = raw_data.data() + channel_size * i;
598  sensor_data sens_data{};
599  sens_data.sensor = hid_sensor{get_sensor_name()};
600 
601  auto hid_data_size = channel_size - (metadata ? HID_METADATA_SIZE : 0);
602  // Populate HID IMU data - Header
603  metadata_hid_raw meta_data{};
605  meta_data.header.length = hid_header_size + metadata_imu_report_size;
606  meta_data.header.timestamp = *(reinterpret_cast<uint64_t *>(&p_raw_data[16]));
607  // Payload:
608  meta_data.report_type.imu_report.header.md_type_id = md_type::META_DATA_HID_IMU_REPORT_ID;
609  meta_data.report_type.imu_report.header.md_size = metadata_imu_report_size;
610 // meta_data.report_type.imu_report.flags = static_cast<uint8_t>( md_hid_imu_attributes::custom_timestamp_attirbute |
611 // md_hid_imu_attributes::imu_counter_attribute |
612 // md_hid_imu_attributes::usb_counter_attribute);
613 // meta_data.report_type.imu_report.custom_timestamp = meta_data.header.timestamp;
614 // meta_data.report_type.imu_report.imu_counter = p_raw_data[30];
615 // meta_data.report_type.imu_report.usb_counter = p_raw_data[31];
616 
617  sens_data.fo = {hid_data_size, metadata? meta_data.header.length: uint8_t(0),
618  p_raw_data, metadata? &meta_data : nullptr, now_ts};
619  //Linux HID provides timestamps in nanosec. Convert to usec (FW default)
620  if (metadata)
621  {
622  //auto* ts_nsec = reinterpret_cast<uint64_t*>(const_cast<void*>(sens_data.fo.metadata));
623  //*ts_nsec /=1000;
624  meta_data.header.timestamp /=1000;
625  }
626 
627 // for (auto i=0ul; i<channel_size; i++)
628 // std::cout << std::hex << int(p_raw_data[i]) << " ";
629 // std::cout << std::dec << std::endl;
630 
631  this->_callback(sens_data);
632  }
633  if (sz > 2)
634  {
635  LOG_DEBUG("HID: Finished to handle " << sz << " packets");
636  }
637  }
638  else
639  {
640  LOG_WARNING("iio_hid_sensor: Frames didn't arrived within the predefined interval");
641  std::this_thread::sleep_for(std::chrono::milliseconds(2));
642  }
643  } while(this->_is_capturing);
644  }));
645  }
646 
648  {
649  if (!_is_capturing)
650  return;
651 
652  _is_capturing = false;
653  set_power(false);
654  signal_stop();
655  _hid_thread->join();
656  _callback = nullptr;
657  _channels.clear();
658 
659  if(::close(_fd) < 0)
660  throw linux_backend_exception("iio_hid_sensor: close(_fd) failed");
661 
662  if(::close(_stop_pipe_fd[0]) < 0)
663  throw linux_backend_exception("iio_hid_sensor: close(_stop_pipe_fd[0]) failed");
664  if(::close(_stop_pipe_fd[1]) < 0)
665  throw linux_backend_exception("iio_hid_sensor: close(_stop_pipe_fd[1]) failed");
666 
667  _fd = 0;
668  _stop_pipe_fd[0] = _stop_pipe_fd[1] = 0;
669  }
670 
672  {
673  std::ostringstream iio_read_device_path;
674  iio_read_device_path << "/dev/" << IIO_DEVICE_PREFIX << _iio_device_number;
675 
676  std::unique_ptr<int, std::function<void(int*)> > fd(
677  new int (_fd = open(iio_read_device_path.str().c_str(), O_RDONLY | O_NONBLOCK)),
678  [&](int* d){ if (d && (*d)) { _fd = ::close(*d); } delete d; });
679 
680  if (!(*fd > 0))
681  throw linux_backend_exception("open() failed with all retries!");
682 
683  // count enabled elements and sort by their index.
684  create_channel_array();
685 
686  const uint32_t channel_size = get_channel_size();
687  auto raw_data_size = channel_size*hid_buf_len;
688 
689  std::vector<uint8_t> raw_data(raw_data_size);
690 
691  auto read_size = read(_fd, raw_data.data(), raw_data_size);
692  while(read_size > 0)
693  read_size = read(_fd, raw_data.data(), raw_data_size);
694 
695  _channels.clear();
696  }
697 
698  void iio_hid_sensor::set_frequency(uint32_t frequency)
699  {
700  auto sampling_frequency_path = _iio_device_path + "/" + _sampling_frequency_name;
701  std::ofstream iio_device_file(sampling_frequency_path);
702 
703  if (!iio_device_file.is_open())
704  {
705  throw linux_backend_exception(rsutils::string::from() << "Failed to set frequency " << frequency <<
706  ". device path: " << sampling_frequency_path);
707  }
708  iio_device_file << frequency;
709  iio_device_file.close();
710  }
711 
712  void iio_hid_sensor::set_sensitivity( float sensitivity )
713  {
714  auto sensitivity_path = _iio_device_path + "/" + _sensitivity_name;
715  std::ofstream iio_device_file( sensitivity_path );
716 
717  if( ! iio_device_file.is_open() )
718  {
720  << "Failed to set sensitivity " << sensitivity
721  << ". device path: " << sensitivity_path );
722  }
723  iio_device_file << sensitivity;
724  iio_device_file.close();
725  }
726 
727  // Asynchronous power management
728  void iio_hid_sensor::set_power(bool on)
729  {
730  auto path = _iio_device_path + "/buffer/enable";
731 
732  // Enqueue power management change
733  _pm_dispatcher.invoke([path,on](dispatcher::cancellable_timer /*t*/)
734  {
735  //auto st = std::chrono::high_resolution_clock::now();
736 
737  if (!write_fs_attribute(path, on))
738  {
739  LOG_WARNING("HID set_power " << int(on) << " failed for " << path);
740  }
741  },true);
742  }
743 
744  void iio_hid_sensor::signal_stop()
745  {
746  char buff[1];
747  buff[0] = 0;
748  if (write(_stop_pipe_fd[1], buff, 1) < 0)
749  {
750  throw linux_backend_exception("iio_hid_sensor: Could not signal video capture thread to stop. Error write to pipe.");
751  }
752  }
753 
754  bool iio_hid_sensor::has_metadata()
755  {
756  //for FW>=5.16 HID_METADATA_SIZE is 12
757  if(get_output_size() >= HID_DATA_ACTUAL_SIZE + HID_METADATA_SIZE)
758  return true;
759  return false;
760  }
761 
762  bool iio_hid_sensor::sort_hids(hid_input* first, hid_input* second)
763  {
764  return (second->get_hid_input_info().index >= first->get_hid_input_info().index);
765  }
766 
767  void iio_hid_sensor::create_channel_array()
768  {
769  // build enabled channels.
770  for(auto& input : _inputs)
771  {
772  if (input->get_hid_input_info().enabled)
773  {
774  _channels.push_back(input);
775  }
776  }
777 
778  _channels.sort(sort_hids);
779  }
780 
781  // initialize the device sensor. reading its name and all of its inputs.
782  void iio_hid_sensor::init(uint32_t frequency, float sensitivity)
783  {
784  std::ifstream iio_device_file(_iio_device_path + "/name");
785 
786  // find iio_device in file system.
787  if (!iio_device_file.good())
788  {
789  throw linux_backend_exception(rsutils::string::from() << "Failed to open device sensor. " << _iio_device_path);
790  }
791 
792  char name_buffer[256] = {};
793  iio_device_file.getline(name_buffer,sizeof(name_buffer));
794  _sensor_name = std::string(name_buffer);
795 
796  iio_device_file.close();
797 
798  // get IIO device number
799  static const std::string suffix_iio_device_path("/" + IIO_DEVICE_PREFIX);
800  auto pos = _iio_device_path.find_last_of(suffix_iio_device_path);
801  if (pos == std::string::npos)
802  throw linux_backend_exception(rsutils::string::from() << "Wrong iio device path " << _iio_device_path);
803 
804  auto substr = _iio_device_path.substr(pos + 1);
805  if (std::all_of(substr.begin(), substr.end(), ::isdigit))
806  {
807  _iio_device_number = atoi(substr.c_str());
808  }
809  else
810  {
811  throw linux_backend_exception(rsutils::string::from() << "IIO device number is incorrect! Failed to open device sensor. " << _iio_device_path);
812  }
813 
814  _pm_dispatcher.start();
815 
816  // HID iio kernel driver async initialization may fail to map the kernel objects hierarchy (iio triggers) properly
817  // The patch will rectify this behaviour
818  std::string current_trigger = _sensor_name + "-dev" + _iio_device_path.back();
819  std::string path = _iio_device_path + "/trigger/current_trigger";
820  _pm_thread = std::unique_ptr<std::thread>(new std::thread([path,current_trigger](){
821  bool retry =true;
822  while (retry) {
823  try {
824  if (write_fs_attribute(path, current_trigger))
825  break;
826  else
827  std::this_thread::sleep_for(std::chrono::milliseconds(50));
828  }
829  catch(...){} // Device disconnect
830  retry = false;
831  }
832  }));
833  _pm_thread->detach();
834 
835  // read all available input of the iio_device
836  read_device_inputs();
837 
838  // get the specific name of sampling_frequency
839  _sampling_frequency_name = get_sampling_frequency_name();
840 
841  // get the specific name of sensitivity
842  _sensitivity_name = get_sensitivity_name();
843 
844  for (auto& input : _inputs)
845  input->enable(true);
846 
847  set_frequency(frequency);
848  set_sensitivity( sensitivity );
849  write_fs_attribute(_iio_device_path + "/buffer/length", hid_buf_len);
850  }
851 
852  // calculate the storage size of a scan
853  uint32_t iio_hid_sensor::get_channel_size() const
854  {
855  assert(!_channels.empty());
856  auto bytes = 0;
857 
858  for (auto& elem : _channels)
859  {
860  auto input_info = elem->get_hid_input_info();
861  if (bytes % input_info.bytes == 0)
862  {
863  input_info.location = bytes;
864  }
865  else
866  {
867  input_info.location = bytes - bytes % input_info.bytes
868  + input_info.bytes;
869  }
870 
871  bytes = input_info.location + input_info.bytes;
872  }
873 
874  return bytes;
875  }
876 
877  // calculate the actual size of data
878  uint32_t iio_hid_sensor::get_output_size() const
879  {
880  assert(!_channels.empty());
881  auto bits_used = 0.;
882 
883  for (auto& elem : _channels)
884  {
885  auto input_info = elem->get_hid_input_info();
886  bits_used += input_info.bits_used;
887  }
888 
889  return std::ceil(bits_used / CHAR_BIT);
890  }
891 
892  std::string iio_hid_sensor::get_sampling_frequency_name() const
893  {
894  std::string sampling_frequency_name = "";
895  DIR *dir = nullptr;
896  struct dirent *dir_ent = nullptr;
897 
898  // start enumerate the scan elemnts dir.
899  dir = opendir(_iio_device_path.c_str());
900  if (dir == nullptr)
901  {
902  throw linux_backend_exception(rsutils::string::from() << "Failed to open scan_element " << _iio_device_path);
903  }
904 
905  // verify file format. should include in_ (input) and _en (enable).
906  while ((dir_ent = readdir(dir)) != nullptr)
907  {
908  if (dir_ent->d_type != DT_DIR)
909  {
910  std::string file(dir_ent->d_name);
911  if (file.find("sampling_frequency") != std::string::npos)
912  {
913  sampling_frequency_name = file;
914  }
915  }
916  }
917  closedir(dir);
918  return sampling_frequency_name;
919  }
920 
921  /*The sensitivity value we need to transfer to FW is stored in a file named with "hysteresis" in its title.
922  Therefore, we are searching for a file that includes "hysteresis" in its name.*/
923  std::string iio_hid_sensor::get_sensitivity_name() const
924  {
925  std::string sensitivity_name = "";
926  DIR * dir = nullptr;
927  struct dirent * dir_ent = nullptr;
928 
929  // start enumerate the scan elemnts dir.
930  dir = opendir( _iio_device_path.c_str() );
931  if( dir == nullptr )
932  {
934  << "Failed to open scan_element " << _iio_device_path );
935  }
936 
937  // verify file format. should include in_ (input) and _en (enable).
938  while( ( dir_ent = readdir( dir ) ) != nullptr )
939  {
940  if( dir_ent->d_type != DT_DIR )
941  {
942  std::string file( dir_ent->d_name );
943  if( file.find( "hysteresis" ) != std::string::npos )
944  {
945  sensitivity_name = file;
946  }
947  }
948  }
949  closedir( dir );
950  return sensitivity_name;
951  }
952 
953 
954  // read the IIO device inputs.
955  void iio_hid_sensor::read_device_inputs()
956  {
957  DIR *dir = nullptr;
958  struct dirent *dir_ent = nullptr;
959 
960  auto scan_elements_path = _iio_device_path + "/scan_elements";
961  // start enumerate the scan elemnts dir.
962  dir = opendir(scan_elements_path.c_str());
963  if (dir == nullptr)
964  {
965  throw linux_backend_exception(rsutils::string::from() << "Failed to open scan_element " << _iio_device_path);
966  }
967 
968  // verify file format. should include in_ (input) and _en (enable).
969  while ((dir_ent = readdir(dir)) != nullptr)
970  {
971  if (dir_ent->d_type != DT_DIR)
972  {
973  std::string file(dir_ent->d_name);
974  std::string prefix = "in_";
975  std::string suffix = "_en";
976  if (file.substr(0,prefix.size()) == prefix &&
977  file.substr(file.size()-suffix.size(),suffix.size()) == suffix) {
978  // initialize input.
979 
980  try
981  {
982  auto* new_input = new hid_input(_iio_device_path, file);
983  // push to input list.
984  _inputs.push_front(new_input);
985  }
986  catch(...)
987  {
988  // fail to initialize this input. continue to the next one.
989  continue;
990  }
991  }
992  }
993  }
994  closedir(dir);
995  }
996 
997  v4l_hid_device::v4l_hid_device(const hid_device_info& info)
998  {
999  bool found = false;
1000  v4l_hid_device::foreach_hid_device([&](const hid_device_info& hid_dev_info){
1001  if (hid_dev_info.unique_id == info.unique_id)
1002  {
1003  _hid_device_infos.push_back(hid_dev_info);
1004  found = true;
1005  }
1006  });
1007 
1008  if (!found)
1009  throw linux_backend_exception("hid device is no longer connected!");
1010  }
1011 
1012  v4l_hid_device::~v4l_hid_device()
1013  {
1014  for (auto& elem : _streaming_iio_sensors)
1015  {
1016  try
1017  {
1018  elem->stop_capture();
1019  }
1020  catch(...)
1021  {
1022  LOG_DEBUG( "Error while stopping capture sensor" );
1023  }
1024  }
1025 
1026  for (auto& elem : _streaming_custom_sensors)
1027  {
1028  try
1029  {
1030  elem->stop_capture();
1031  }
1032  catch(...)
1033  {
1034  LOG_DEBUG( "Error while stopping capture sensor" );
1035  }
1036  }
1037  }
1038 
1039  void v4l_hid_device::open(const std::vector<hid_profile>& hid_profiles)
1040  {
1041  _hid_profiles = hid_profiles;
1042  for (auto& device_info : _hid_device_infos)
1043  {
1044  try
1045  {
1046  if (device_info.id == custom_id)
1047  {
1048  auto device = std::unique_ptr<hid_custom_sensor>(new hid_custom_sensor(device_info.device_path,
1049  device_info.id));
1050  _hid_custom_sensors.push_back(std::move(device));
1051  }
1052  else
1053  {
1054  uint32_t frequency = 0;
1055  float sensitivity = 0;
1056  for (auto& profile : hid_profiles)
1057  {
1058  if (profile.sensor_name == device_info.id)
1059  {
1060  frequency = profile.frequency;
1061  sensitivity = profile.sensitivity;
1062  break;
1063  }
1064  }
1065 
1066  if (frequency == 0)
1067  continue;
1068 
1069  auto device = std::unique_ptr<iio_hid_sensor>(new iio_hid_sensor(device_info.device_path, frequency, sensitivity));
1070  _iio_hid_sensors.push_back(std::move(device));
1071  }
1072  }
1073  catch(...)
1074  {
1075  for (auto& hid_sensor : _iio_hid_sensors)
1076  {
1077  hid_sensor.reset();
1078  }
1079  _iio_hid_sensors.clear();
1080  LOG_ERROR("Hid device is busy!");
1081  throw;
1082  }
1083  }
1084  }
1085 
1086  void v4l_hid_device::close()
1087  {
1088  for (auto& hid_iio_sensor : _iio_hid_sensors)
1089  {
1090  hid_iio_sensor.reset();
1091  }
1092  _iio_hid_sensors.clear();
1093 
1094  for (auto& hid_custom_sensor : _hid_custom_sensors)
1095  {
1096  hid_custom_sensor.reset();
1097  }
1098  _hid_custom_sensors.clear();
1099  }
1100 
1101  std::vector<hid_sensor> v4l_hid_device::get_sensors()
1102  {
1103  std::vector<hid_sensor> iio_sensors;
1104 
1105  for (auto& sensor : _hid_profiles)
1106  iio_sensors.push_back({ sensor.sensor_name });
1107 
1108 
1109  for (auto& elem : _hid_custom_sensors)
1110  {
1111  iio_sensors.push_back(hid_sensor{elem->get_sensor_name()});
1112  }
1113  return iio_sensors;
1114  }
1115 
1116  void v4l_hid_device::start_capture(hid_callback callback)
1117  {
1118  for (auto& profile : _hid_profiles)
1119  {
1120  for (auto& sensor : _iio_hid_sensors)
1121  {
1122  if (sensor->get_sensor_name() == profile.sensor_name)
1123  {
1124  _streaming_iio_sensors.push_back(sensor.get());
1125  }
1126  }
1127 
1128  for (auto& sensor : _hid_custom_sensors)
1129  {
1130  if (sensor->get_sensor_name() == profile.sensor_name)
1131  {
1132  _streaming_custom_sensors.push_back(sensor.get());
1133  }
1134  }
1135 
1136  if (_streaming_iio_sensors.empty() && _streaming_custom_sensors.empty())
1137  LOG_ERROR("sensor " + profile.sensor_name + " not found!");
1138  }
1139 
1140  if (!_streaming_iio_sensors.empty())
1141  {
1142  std::vector<iio_hid_sensor*> captured_sensors;
1143  try{
1144  for (auto& elem : _streaming_iio_sensors)
1145  {
1146  elem->start_capture(callback);
1147  captured_sensors.push_back(elem);
1148  }
1149  }
1150  catch(...)
1151  {
1152  for (auto& elem : captured_sensors)
1153  elem->stop_capture();
1154 
1155  _streaming_iio_sensors.clear();
1156  throw;
1157  }
1158  }
1159 
1160  if (!_streaming_custom_sensors.empty())
1161  {
1162  std::vector<hid_custom_sensor*> captured_sensors;
1163  try{
1164  for (auto& elem : _streaming_custom_sensors)
1165  {
1166  elem->start_capture(callback);
1167  captured_sensors.push_back(elem);
1168  }
1169  }
1170  catch(...)
1171  {
1172  for (auto& elem : captured_sensors)
1173  elem->stop_capture();
1174 
1175  _streaming_custom_sensors.clear();
1176  throw;
1177  }
1178  }
1179 
1180  }
1181 
1182  void v4l_hid_device::stop_capture()
1183  {
1184  for (auto& sensor : _iio_hid_sensors)
1185  {
1186  sensor->stop_capture();
1187  }
1188 
1189  _streaming_iio_sensors.clear();
1190 
1191  for (auto& sensor : _hid_custom_sensors)
1192  {
1193  sensor->stop_capture();
1194  }
1195 
1196  _streaming_custom_sensors.clear();
1197  }
1198 
1199  std::vector<uint8_t> v4l_hid_device::get_custom_report_data(const std::string& custom_sensor_name,
1200  const std::string& report_name,
1201  custom_sensor_report_field report_field)
1202  {
1203  auto it = std::find_if(begin(_hid_custom_sensors), end(_hid_custom_sensors),
1204  [&](const std::unique_ptr<hid_custom_sensor>& hcs)
1205  {
1206  return hcs->get_sensor_name() == custom_sensor_name;
1207  });
1208  if (it != end(_hid_custom_sensors))
1209  {
1210  return (*it)->get_report_data(report_name, report_field);
1211  }
1212  throw linux_backend_exception(rsutils::string::from() << " custom sensor " << custom_sensor_name << " not found!");
1213  }
1214 
1215  void v4l_hid_device::foreach_hid_device(std::function<void(const hid_device_info&)> action)
1216  {
1217  // Common HID Sensors
1218  DIR* dir = nullptr;
1219  struct dirent* ent = nullptr;
1220  std::vector<std::string> common_sensors;
1221  if ((dir = opendir(IIO_ROOT_PATH.c_str())) != nullptr)
1222  {
1223  while ((ent = readdir(dir)) != nullptr)
1224  {
1225  auto str = std::string(ent->d_name);
1226  if (str.find(IIO_DEVICE_PREFIX) != std::string::npos)
1227  common_sensors.push_back(IIO_ROOT_PATH + "/" + str);
1228  }
1229  closedir(dir);
1230  }
1231 
1232  for (auto& elem : common_sensors)
1233  {
1234  hid_device_info hid_dev_info{};
1235  if(!get_hid_device_info(elem.c_str(), hid_dev_info))
1236  {
1237 #ifdef RS2_USE_CUDA
1238  /* On the Jetson TX, ina3221x is the power monitor (I2C bus)
1239  This code is checking the IIA device directory, but tries to compare as USB HID device
1240  The ina3221x is not a HID device. Check here to avoid spamming the console.
1241  Patch suggested by JetsonHacks: https://github.com/jetsonhacks/buildLibrealsense2TX */
1242  std::string device_path_str(elem.c_str());
1243  device_path_str+="/";
1244  std::string dev_name;
1245  std::ifstream(device_path_str + "name") >> dev_name;
1246  if (dev_name != std::string("ina3221x")) {
1247  LOG_WARNING("Failed to read busnum/devnum. Device Path: " << elem);
1248  }
1249 #else
1250  LOG_INFO("Failed to read busnum/devnum. Device Path: " << elem);
1251 #endif
1252  continue;
1253  }
1254  action(hid_dev_info);
1255  }
1256 
1257 
1258  // Custom HID Sensors
1259  static const char* prefix_custom_sensor_name = "HID-SENSOR-2000e1";
1260  std::vector<std::string> custom_sensors;
1261  dir = nullptr;
1262  ent = nullptr;
1263  if ((dir = opendir(HID_CUSTOM_PATH.c_str())) != nullptr)
1264  {
1265  while ((ent = readdir(dir)) != nullptr)
1266  {
1267  auto str = std::string(ent->d_name);
1268  if (str.find(prefix_custom_sensor_name) != std::string::npos)
1269  custom_sensors.push_back(HID_CUSTOM_PATH + "/" + str);
1270  }
1271  closedir(dir);
1272  }
1273 
1274 
1275  for (auto& elem : custom_sensors)
1276  {
1277  hid_device_info hid_dev_info{};
1278  if(!get_hid_device_info(elem.c_str(), hid_dev_info))
1279  {
1280  LOG_WARNING("Failed to read busnum/devnum. Custom HID Device Path: " << elem);
1281  continue;
1282  }
1283 
1284  hid_dev_info.id = custom_id;
1285  action(hid_dev_info);
1286  }
1287  }
1288 
1289  bool v4l_hid_device::get_hid_device_info(const char* dev_path, hid_device_info& device_info)
1290  {
1291  char device_path[PATH_MAX] = {};
1292  if (nullptr == realpath(dev_path, device_path))
1293  {
1294  LOG_WARNING("Could not resolve HID path: " << dev_path);
1295  return false;
1296  }
1297 
1298  std::string device_path_str(device_path);
1299  device_path_str+="/";
1300  std::string busnum, devnum, devpath, vid, pid, dev_id, dev_name;
1301  std::ifstream(device_path_str + "name") >> dev_name;
1302  auto valid = false;
1303  for(auto i=0UL; i < MAX_DEV_PARENT_DIR; ++i)
1304  {
1305  if(std::ifstream(device_path_str + "busnum") >> busnum)
1306  {
1307  if(std::ifstream(device_path_str + "devnum") >> devnum)
1308  {
1309  if(std::ifstream(device_path_str + "devpath") >> devpath)
1310  {
1311  if(std::ifstream(device_path_str + "idVendor") >> vid)
1312  {
1313  if(std::ifstream(device_path_str + "idProduct") >> pid)
1314  {
1315  if(std::ifstream(device_path_str + "dev") >> dev_id)
1316  {
1317  valid = true;
1318  break;
1319  }
1320  }
1321  }
1322  }
1323  }
1324  }
1325  device_path_str += "../";
1326  }
1327 
1328  if (valid)
1329  {
1330  device_info.vid = vid;
1331  device_info.pid = pid;
1332  device_info.unique_id = busnum + "-" + devpath + "-" + devnum;
1333  device_info.id = dev_name;
1334  device_info.device_path = device_path;
1335  }
1336 
1337  return valid;
1338  }
1339  }
1340 }
librealsense::platform::iio_hid_sensor::_inputs
std::list< hid_input * > _inputs
Definition: backend-hid.h:184
librealsense::platform::write_fs_attribute
bool write_fs_attribute(const std::string &path, const T &val)
Definition: backend-hid.h:39
librealsense::platform::hid_input::get_hid_input_info
const hid_input_info & get_hid_input_info() const
Definition: backend-hid.h:89
librealsense::platform::hid_callback
std::function< void(const sensor_data &) > hid_callback
Definition: platform/hid-device.h:56
librealsense::platform::iio_hid_sensor::_channels
std::list< hid_input * > _channels
Definition: backend-hid.h:185
unit-test-config.dir
dir
Definition: unit-test-config.py:81
librealsense::platform::hid_device_info::unique_id
std::string unique_id
Definition: hid-device-info.h:18
HID_METADATA_SIZE
const uint8_t HID_METADATA_SIZE
Definition: backend-hid.cpp:22
librealsense
Definition: algo.h:18
librealsense::platform::hid_custom_sensor::read_report
std::vector< uint8_t > read_report(const std::string &name_report_path)
Definition: backend-hid.cpp:357
uint8_t
unsigned char uint8_t
Definition: stdint.h:78
librealsense::platform::hid_custom_sensor::_custom_device_name
std::string _custom_device_name
Definition: backend-hid.h:126
librealsense::platform::sensor_data::sensor
hid_sensor sensor
Definition: platform/hid-device.h:40
dispatcher::cancellable_timer
Definition: concurrency.h:279
librealsense::platform::hid_custom_sensor::_is_capturing
std::atomic< bool > _is_capturing
Definition: backend-hid.h:128
LOG_DEBUG_HID
#define LOG_DEBUG_HID(...)
Definition: backend-hid.cpp:33
librealsense::platform::hid_custom_sensor::_reports
std::map< std::string, std::string > _reports
Definition: backend-hid.h:123
librealsense::md_type::META_DATA_HID_IMU_REPORT_ID
@ META_DATA_HID_IMU_REPORT_ID
librealsense::platform::hid_custom_sensor::signal_stop
void signal_stop()
Definition: backend-hid.cpp:446
librealsense::invalid_value_exception
Definition: librealsense-exception.h:114
librealsense::hid_header::report_type
uint8_t report_type
Definition: src/metadata.h:798
librealsense::platform::hid_input_info::big_endian
uint32_t big_endian
Definition: backend-hid.h:24
rs-imu-calibration.input
input
Definition: rs-imu-calibration.py:35
librealsense::platform::minimum
@ minimum
Definition: platform/hid-device.h:61
librealsense::device_info
Definition: device-info.h:21
librealsense::platform::hid_device_info
Definition: hid-device-info.h:13
librealsense::platform::iio_hid_sensor::_iio_device_number
int _iio_device_number
Definition: backend-hid.h:179
librealsense::platform::hid_custom_sensor::_callback
hid_callback _callback
Definition: backend-hid.h:127
librealsense::platform::hid_custom_sensor::_hid_thread
std::unique_ptr< std::thread > _hid_thread
Definition: backend-hid.h:129
librealsense::platform::hid_custom_sensor::stop_capture
void stop_capture()
Definition: backend-hid.cpp:331
librealsense::platform::iio_hid_sensor::signal_stop
void signal_stop()
Definition: backend-hid.cpp:744
librealsense::platform::iio_hid_sensor::get_channel_size
uint32_t get_channel_size() const
Definition: backend-hid.cpp:853
rspy.devices.path
path
Definition: unit-tests/py/rspy/devices.py:47
test-librs-device-properties.sensor
sensor
Definition: test-librs-device-properties.py:40
librealsense::platform::size
@ size
Definition: platform/hid-device.h:64
librealsense::platform::iio_hid_sensor::create_channel_array
void create_channel_array()
Definition: backend-hid.cpp:767
librealsense::platform::hid_input_info::is_signed
uint32_t is_signed
Definition: backend-hid.h:27
librealsense::platform::iio_hid_sensor::stop_capture
void stop_capture()
Definition: backend-hid.cpp:647
librealsense::platform::hid_input_info::enabled
bool enabled
Definition: backend-hid.h:22
librealsense::metadata_hid_raw
metadata_hid_raw - HID metadata structure layout populated by backend
Definition: src/metadata.h:807
string
GLsizei const GLchar *const * string
Definition: glad/glad/glad.h:2861
void
typedef void(APIENTRY *GLDEBUGPROC)(GLenum source
librealsense::bytes
Definition: align.cpp:22
LOG_DEBUG
#define LOG_DEBUG(...)
Definition: easyloggingpp.h:70
from.h
librealsense::platform::iio_hid_sensor::iio_hid_sensor
iio_hid_sensor(const std::string &device_path, uint32_t frequency, float sensitivity)
Definition: backend-hid.cpp:456
librealsense::platform::units
@ units
Definition: platform/hid-device.h:66
librealsense::platform::hid_input::init
void init()
Definition: backend-hid.cpp:88
librealsense::hid_report_imu
@ hid_report_imu
Definition: src/metadata.h:250
librealsense::platform::hid_input::hid_input
hid_input(const std::string &iio_device_path, const std::string &input_name)
Definition: backend-hid.cpp:40
librealsense::platform::iio_hid_sensor
Definition: backend-hid.h:133
IIO_DEVICE_PREFIX
const std::string IIO_DEVICE_PREFIX("iio:device")
librealsense::platform::hid_buf_len
const uint32_t hid_buf_len
Definition: backend-hid.h:15
librealsense::platform::iio_hid_sensor::has_metadata
bool has_metadata()
Definition: backend-hid.cpp:754
librealsense::platform::iio_hid_sensor::get_sensor_name
const std::string & get_sensor_name() const
Definition: backend-hid.h:144
read_bag_example.str
str
Definition: read_bag_example.py:21
librealsense::platform::hid_input_info::bits_used
uint32_t bits_used
Definition: backend-hid.h:25
LOG_WARNING
#define LOG_WARNING(...)
Definition: easyloggingpp.h:72
librealsense::platform::hid_custom_sensor::start_capture
void start_capture(hid_callback sensor_callback)
Definition: backend-hid.cpp:210
librealsense::platform::iio_hid_sensor::start_capture
void start_capture(hid_callback sensor_callback)
Definition: backend-hid.cpp:489
test-d405-calibration-stream.pid
pid
Definition: test-d405-calibration-stream.py:12
val
GLuint GLfloat * val
Definition: glad/glad/glad.h:3411
librealsense::metadata_hid_raw::header
hid_header header
Definition: src/metadata.h:809
librealsense::platform::hid_custom_sensor::hid_custom_sensor
hid_custom_sensor(const std::string &device_path, const std::string &sensor_name)
Definition: backend-hid.cpp:162
librealsense::platform::hid_input::~hid_input
~hid_input()
Definition: backend-hid.cpp:57
HID_CUSTOM_PATH
const std::string HID_CUSTOM_PATH("/sys/bus/platform/drivers/hid_sensor_custom")
librealsense::platform::hid_custom_sensor::~hid_custom_sensor
~hid_custom_sensor()
Definition: backend-hid.cpp:175
uint32_t
unsigned int uint32_t
Definition: stdint.h:80
backend-hid.h
librealsense::platform::iio_hid_sensor::_fd
int _fd
Definition: backend-hid.h:178
buffer
GLenum GLfloat * buffer
Definition: glad/glad/glad.h:2066
librealsense::platform::hid_input_info::input
std::string input
Definition: backend-hid.h:19
librealsense::platform::unit_expo
@ unit_expo
Definition: platform/hid-device.h:65
uint64_t
unsigned __int64 uint64_t
Definition: stdint.h:90
i
int i
Definition: rs-pcl-color.cpp:54
librealsense::platform::value
@ value
Definition: platform/hid-device.h:67
librealsense::platform::hid_custom_sensor::get_sensor_name
const std::string & get_sensor_name() const
Definition: backend-hid.h:106
realdds::topics::notification::stream_header::key::sensor_name
const std::string sensor_name
librealsense::platform::iio_hid_sensor::clear_buffer
void clear_buffer()
Definition: backend-hid.cpp:671
librealsense::platform::hid_custom_sensor
Definition: backend-hid.h:98
devices.action
action
Definition: third-party/realdds/scripts/devices.py:6
librealsense::platform::hid_custom_sensor::_stop_pipe_fd
int _stop_pipe_fd[2]
Definition: backend-hid.h:122
librealsense::platform::hid_custom_sensor::enable
void enable(bool state)
Definition: backend-hid.cpp:421
librealsense::platform::hid_custom_sensor::_fd
int _fd
Definition: backend-hid.h:121
backend.h
librealsense::platform::hid_custom_sensor::_custom_device_path
std::string _custom_device_path
Definition: backend-hid.h:124
librealsense::platform::iio_hid_sensor::_hid_thread
std::unique_ptr< std::thread > _hid_thread
Definition: backend-hid.h:188
opencv_pointcloud_viewer.now
now
Definition: opencv_pointcloud_viewer.py:314
librealsense::platform::hid_input_info::bytes
uint32_t bytes
Definition: backend-hid.h:26
librealsense::platform::hid_custom_sensor::get_report_data
std::vector< uint8_t > get_report_data(const std::string &report_name, custom_sensor_report_field report_field)
Definition: backend-hid.cpp:188
fps.info
info
Definition: fps.py:50
librealsense::hid_header_size
constexpr uint8_t hid_header_size
Definition: src/metadata.h:803
librealsense::platform::iio_hid_sensor::_pm_dispatcher
dispatcher _pm_dispatcher
Definition: backend-hid.h:190
MAX_DEV_PARENT_DIR
const size_t MAX_DEV_PARENT_DIR
Definition: backend-hid.cpp:20
librealsense::platform::hid_input
Definition: backend-hid.h:80
librealsense::platform::custom_sensor_report_field
custom_sensor_report_field
Definition: platform/hid-device.h:59
librealsense::platform::name
@ name
Definition: platform/hid-device.h:63
assert
#define assert(condition)
Definition: lz4.c:245
realsense_legacy_msgs::metadata
::realsense_legacy_msgs::metadata_< std::allocator< void > > metadata
Definition: third-party/realsense-file/rosbag/msgs/realsense_legacy_msgs/metadata.h:52
librealsense::platform::hid_input_info::shift
uint32_t shift
Definition: backend-hid.h:29
librealsense::platform::buffer
Definition: backend-v4l2.h:122
rsutils::string::from
Definition: from.h:19
librealsense::platform::hid_input_info::index
int index
Definition: backend-hid.h:21
std::stoi
int stoi(const std::string &value)
Definition: android_helpers.h:42
librealsense::platform::hid_custom_sensor::init
void init()
Definition: backend-hid.cpp:376
librealsense::platform::hid_sensor
Definition: platform/hid-device.h:27
first
GLint first
Definition: glad/glad/glad.h:2301
state
Definition: rs-measure.cpp:80
librealsense::linux_backend_exception
Definition: librealsense-exception.h:87
librealsense::platform::maximum
@ maximum
Definition: platform/hid-device.h:62
librealsense::platform::iio_hid_sensor::set_power
void set_power(bool on)
Definition: backend-hid.cpp:728
librealsense::platform::iio_hid_sensor::_is_capturing
std::atomic< bool > _is_capturing
Definition: backend-hid.h:187
librealsense::platform::hid_input_info::mask
uint64_t mask
Definition: backend-hid.h:30
IIO_ROOT_PATH
const std::string IIO_ROOT_PATH("/sys/bus/iio/devices")
librealsense::metadata_imu_report_size
constexpr uint8_t metadata_imu_report_size
Definition: src/metadata.h:772
dispatcher::flush
bool flush(std::chrono::steady_clock::duration timeout=std::chrono::seconds(10))
Definition: dispatcher.cpp:106
init
void init(void)
Definition: boing.c:180
end
GLuint GLuint end
Definition: glad/glad/glad.h:2395
librealsense::platform::iio_hid_sensor::~iio_hid_sensor
~iio_hid_sensor()
Definition: backend-hid.cpp:470
it
static auto it
Definition: openvino-face-detection.cpp:375
librealsense::platform::hid_input_info::device_path
std::string device_path
Definition: backend-hid.h:20
librealsense::device
Definition: device.h:35
librealsense::platform::hid_input::info
hid_input_info info
Definition: backend-hid.h:95
librealsense::platform::iio_hid_sensor::_callback
hid_callback _callback
Definition: backend-hid.h:186
LOG_INFO
LOG_INFO("Log message using LOG_INFO()")
test-hdr-long.pipe
pipe
Definition: test-hdr-long.py:88
profile
Definition: unit-tests-common.h:58
rmse.d
d
Definition: rmse.py:171
librealsense::platform::sensor_data
Definition: platform/hid-device.h:38
LOG_ERROR
#define LOG_ERROR(...)
Definition: easyloggingpp.h:73
librealsense::platform::hid_input::enable
void enable(bool is_enable)
Definition: backend-hid.cpp:70
librealsense::platform::iio_hid_sensor::_stop_pipe_fd
int _stop_pipe_fd[2]
Definition: backend-hid.h:177
HID_DATA_ACTUAL_SIZE
const size_t HID_DATA_ACTUAL_SIZE
Definition: backend-hid.cpp:23


librealsense2
Author(s): LibRealSense ROS Team
autogenerated on Fri Aug 2 2024 08:30:01