Main MRPT website > C++ reference for MRPT 1.9.9
CInterfaceFTDI_LIN.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include <mrpt/config.h>
11 #include <mrpt/core/exceptions.h>
12 
13 #include <cstring>
14 
15 #if defined(MRPT_OS_LINUX) || defined(MRPT_OS_APPLE)
16 
17 #if MRPT_HAS_FTDI
18 #include <ftdi.h>
19 #if MRPT_FTDI_VERSION >= 0x120
20 #include <libusb-1.0/libusb.h>
21 #else
22 #include <usb.h>
23 #endif
24 #endif
25 
27 
28 #include <iostream>
29 
30 using namespace mrpt::comms;
31 using namespace std;
32 
33 /*-------------------------------------------------------------
34  CInterfaceFTDI
35 -------------------------------------------------------------*/
36 CInterfaceFTDI::CInterfaceFTDI() : m_readBuffer(4096)
37 {
39 
40 #if MRPT_HAS_FTDI
41  // Alloc mem:
42  ftdi_context* newCtx = new ftdi_context[1];
43  ASSERT_(newCtx);
44 
45  // Init:
46  int ret = ftdi_init(newCtx);
47  if (ret) THROW_EXCEPTION("There was a problem initializing ftdi_context.");
48 
49  // Save in member:
50  m_ftdi_context = static_cast<void*>(newCtx);
51 #else
53  "MRPT has been compiled without FTDI support. Please, reconfigure and "
54  "recompile MRPT.");
55 #endif
56 
57 #if MRPT_FTDI_VERSION >= 0x120
58  libusb_init(nullptr);
59 #endif
61 }
62 
63 /*-------------------------------------------------------------
64  ~CInterfaceFTDI
65 -------------------------------------------------------------*/
67 {
68 #if MRPT_HAS_FTDI
69  // Close USB:
70  if (isOpen()) Close();
71  ftdi_context* ctx = static_cast<ftdi_context*>(m_ftdi_context);
72 
73  // Close context:
74  ftdi_deinit(ctx);
75 
76  // Free mem:
77  delete[] ctx;
78  ctx = nullptr;
79 #endif
80 #if MRPT_FTDI_VERSION >= 0x120
81  libusb_exit(nullptr);
82 #endif
83 }
84 
85 void CInterfaceFTDI::OpenBySerialNumber(const std::string& serialNumber)
86 {
87 #if MRPT_HAS_FTDI
89 
91 
92  // Close previous connection:
93  Close();
94 
95  // ftdi_usb_open_desc ...
96 
97  // Create a list of all the devices:
98  TFTDIDeviceList lstDevs;
99  ListAllDevices(lstDevs);
100 
101  // Look for the one we want:
102  void* myDev = nullptr;
103 
104  for (TFTDIDeviceList::iterator it = lstDevs.begin(); it != lstDevs.end();
105  ++it)
106  {
107  if (it->ftdi_serial == serialNumber)
108  {
109  myDev = it->usb_device_struct;
110  break;
111  }
112  }
113 
114  if (!myDev)
116  "USB device with serial number '%s' not found.",
117  serialNumber.c_str());
118 
119  // Open it:
120  ftdi_context* ctx = static_cast<ftdi_context*>(m_ftdi_context);
121 
122  int ret = ftdi_usb_open_dev(
123  ctx,
124 #if MRPT_FTDI_VERSION >= 0x120
125  (struct libusb_device*)myDev
126 #else
127  (struct usb_device*)myDev
128 #endif
129  );
130 
131  if (ret) THROW_EXCEPTION(string(ftdi_get_error_string(ctx)));
132 
134 #else
135  MRPT_UNUSED_PARAM(serialNumber);
136 #endif
137 }
138 
139 /*-------------------------------------------------------------
140  ListAllDevices
141 -------------------------------------------------------------*/
143 {
145 #if MRPT_HAS_FTDI
146 
147  outList.clear();
148 
149 #if MRPT_FTDI_VERSION >= 0x120
150  // For new libftdi1-dev
151  // Use libusb-1.0
152 
153  libusb_device** list;
154  ssize_t nDevices = libusb_get_device_list(nullptr, &list);
155 
156  for (unsigned int i = 0; i < nDevices; i++)
157  {
158  libusb_device* device = list[i];
159  struct libusb_device_descriptor desc;
160  if (0 != libusb_get_device_descriptor(device, &desc)) continue;
161  if (!desc.idVendor) continue;
162 
163  TFTDIDevice newEntry;
164  newEntry.usb_device_struct = (void*)device;
165  newEntry.usb_idProduct = desc.idProduct;
166  newEntry.usb_idVendor = desc.idVendor;
167  newEntry.usb_serialNumber = desc.iSerialNumber;
168 
169  // Open the device temporally so we can get more info:
170  libusb_device_handle* handle;
171  if (0 != libusb_open(device, &handle)) continue;
172 
173  char buf[1024];
174  int ret;
175  // manufacturer
176  ret = libusb_get_string_descriptor_ascii(
177  handle, desc.iManufacturer, (unsigned char*)buf, sizeof(buf) - 1);
178  if (ret < 0) continue;
179  buf[ret] = '\0';
180  newEntry.ftdi_manufacturer = buf;
181 
182  // description
183  ret = libusb_get_string_descriptor_ascii(
184  handle, desc.iProduct, (unsigned char*)buf, sizeof(buf) - 1);
185  if (ret < 0) continue;
186  buf[ret] = '\0';
187  newEntry.ftdi_description = buf;
188 
189  // serial
190  ret = libusb_get_string_descriptor_ascii(
191  handle, desc.iSerialNumber, (unsigned char*)buf, sizeof(buf) - 1);
192  if (ret < 0) continue;
193  buf[ret] = '\0';
194  newEntry.ftdi_serial = buf;
195 
196  outList.push_back(newEntry);
197  }
198 
199 #else
200  // For old libftdi-dev
201  // Use old usb.h interface
202  struct usb_bus* bus;
203  struct usb_device* dev;
204 
205  usb_init();
206  if (usb_find_busses() < 0) THROW_EXCEPTION("usb_find_busses() failed");
207  if (usb_find_devices() < 0) THROW_EXCEPTION("usb_find_devices() failed");
208 
209  for (bus = usb_busses; bus; bus = bus->next)
210  for (dev = bus->devices; dev; dev = dev->next)
211  recursive_fill_list_devices(
212  dev, outList); // Process this node and its children:
213 
214 #endif
215  if (getenv("VERBOSE") != nullptr)
216  {
217  printf("[CInterfaceFTDI::ListAllDevices] List: \n");
218  for (std::deque<TFTDIDevice>::const_iterator i = outList.begin();
219  i != outList.end(); ++i)
220  printf(
221  "USB DEV: V=%04X P=%04X S=%s\n", i->usb_idVendor,
222  i->usb_idProduct, i->ftdi_serial.c_str());
223  }
224 
225 #else
226  MRPT_UNUSED_PARAM(outList);
227 #endif
229 }
230 
231 void CInterfaceFTDI::recursive_fill_list_devices(
232  void* usb_device_structure, TFTDIDeviceList& outList)
233 {
234 #if MRPT_HAS_FTDI
235 #if MRPT_FTDI_VERSION >= 0x120
236  // For new libftdi1-dev
237  throw std::runtime_error("Should not have got to this function!");
238 #else
239  // For old libftdi-dev
240  struct usb_device* dev = (struct usb_device*)usb_device_structure;
241 
242  if (dev->descriptor.idProduct && dev->descriptor.idVendor)
243  {
244  TFTDIDevice newEntry;
245  newEntry.usb_idProduct = dev->descriptor.idProduct;
246  newEntry.usb_idVendor = dev->descriptor.idVendor;
247  newEntry.usb_device_struct = (void*)dev;
248 
249  int strLen;
250 
251  // Open the device temporally so we can get more info:
252  usb_dev_handle* hUSB = usb_open(dev);
253 
254  if (hUSB)
255  {
256  char manufacturer[3000];
257  if ((strLen = usb_get_string_simple(
258  hUSB, dev->descriptor.iManufacturer, manufacturer,
259  sizeof(manufacturer))) <= 0)
260  {
261  cerr << "Couldn't open " << (int)dev->descriptor.iManufacturer
262  << endl;
263  // usb_close(hUSB); hUSB=nullptr;
264  }
265  else
266  {
267  manufacturer[strLen] = '\0';
268  // cout << "Manuf: " << manufacturer << endl;
269  newEntry.ftdi_manufacturer = manufacturer;
270  }
271  }
272 
273  if (hUSB)
274  {
275  char description[3000];
276  if ((strLen = usb_get_string_simple(
277  hUSB, dev->descriptor.iProduct, description,
278  sizeof(description))) <= 0)
279  {
280  // usb_close(hUSB); hUSB=nullptr;
281  }
282  else
283  {
284  description[strLen] = '\0';
285  newEntry.ftdi_description = description;
286  }
287  }
288 
289  if (hUSB)
290  {
291  char serial[300];
292  if ((strLen = usb_get_string_simple(
293  hUSB, dev->descriptor.iSerialNumber, serial,
294  sizeof(serial))) <= 0)
295  {
296  // usb_close(hUSB); hUSB=nullptr;
297  }
298  else
299  {
300  serial[strLen] = '\0';
301  newEntry.ftdi_serial = serial;
302  }
303  }
304 
305  if (hUSB)
306  {
307  outList.push_back(newEntry);
308  usb_close(hUSB);
309  }
310 
311  // And now its children:
312  // -----------------------------------
313  for (unsigned char j = 0; j < dev->num_children; j++)
314  recursive_fill_list_devices((void*)dev->children[j], outList);
315  }
316 #endif
317 #else
318  MRPT_UNUSED_PARAM(usb_device_structure);
319  MRPT_UNUSED_PARAM(outList);
320 #endif
321 }
322 
323 /*-------------------------------------------------------------
324  ftdi_read
325 -------------------------------------------------------------*/
327  void* lpvBuffer, unsigned long dwBuffSize, unsigned long* lpdwBytesRead)
328 {
329 #if MRPT_HAS_FTDI
331  ftdi_context* ctx = static_cast<ftdi_context*>(m_ftdi_context);
332 
333  int ret = ftdi_read_data(ctx, (unsigned char*)lpvBuffer, dwBuffSize);
334  if (ret >= 0)
335  *lpdwBytesRead = ret;
336  else
337  {
338  if (!strcmp("usb bulk read failed", ctx->error_str))
339  {
340  *lpdwBytesRead = 0;
341  return;
342  }
343  THROW_EXCEPTION(string(ftdi_get_error_string(ctx)));
344  }
345 
347 #else
348  MRPT_UNUSED_PARAM(lpvBuffer);
349  MRPT_UNUSED_PARAM(dwBuffSize);
350  MRPT_UNUSED_PARAM(lpdwBytesRead);
351 #endif
352 }
353 
354 /*-------------------------------------------------------------
355  ftdi_write
356 -------------------------------------------------------------*/
358  const void* lpvBuffer, unsigned long dwBuffSize, unsigned long* lpdwBytes)
359 {
360 #if MRPT_HAS_FTDI
362  ftdi_context* ctx = static_cast<ftdi_context*>(m_ftdi_context);
363 
364  int ret = ftdi_write_data(ctx, (unsigned char*)lpvBuffer, dwBuffSize);
365  if (ret >= 0)
366  *lpdwBytes = ret;
367  else
368  THROW_EXCEPTION(string(ftdi_get_error_string(ctx)));
369 
371 #else
372  MRPT_UNUSED_PARAM(lpvBuffer);
373  MRPT_UNUSED_PARAM(dwBuffSize);
374  MRPT_UNUSED_PARAM(lpdwBytes);
375 #endif
376 }
377 
378 /*-------------------------------------------------------------
379  isOpen
380 -------------------------------------------------------------*/
382 {
383 #if MRPT_HAS_FTDI
384  ftdi_context* ctx = static_cast<ftdi_context*>(m_ftdi_context);
385  return ctx->usb_dev != nullptr;
386 #else
387  return false;
388 #endif
389 }
390 
391 /*-------------------------------------------------------------
392  Close
393 -------------------------------------------------------------*/
395 {
396 #if MRPT_HAS_FTDI
397  ftdi_context* ctx = static_cast<ftdi_context*>(m_ftdi_context);
398  if (ctx->usb_dev)
399  {
400  ftdi_usb_close(ctx);
401  ctx->usb_dev = nullptr;
402  }
403 
404  // To assure this is as a "reset", re-init the ftdi context again:
405  ftdi_deinit(ctx);
406  ftdi_init(ctx);
407 
409 #endif
410 }
411 
412 /*-------------------------------------------------------------
413  ResetDevice
414 -------------------------------------------------------------*/
416 {
417 #if MRPT_HAS_FTDI
418  ftdi_context* ctx = static_cast<ftdi_context*>(m_ftdi_context);
419  ASSERT_(ctx->usb_dev);
420 
421  if (ftdi_usb_reset(ctx) < 0) THROW_EXCEPTION("Error resetting device");
422 
424 #endif
425 }
426 
427 /*-------------------------------------------------------------
428  Purge
429 -------------------------------------------------------------*/
431 {
432 #if MRPT_HAS_FTDI
433  ftdi_context* ctx = static_cast<ftdi_context*>(m_ftdi_context);
434  ASSERT_(ctx->usb_dev);
435 
436  if (ftdi_usb_purge_buffers(ctx) < 0)
437  THROW_EXCEPTION("Error purging device buffers");
438 
440 #endif
441 }
442 
443 /*-------------------------------------------------------------
444  SetLatencyTimer
445 -------------------------------------------------------------*/
446 void CInterfaceFTDI::SetLatencyTimer(unsigned char latency_ms)
447 {
448 #if MRPT_HAS_FTDI
449  ftdi_context* ctx = static_cast<ftdi_context*>(m_ftdi_context);
450  ASSERT_(ctx->usb_dev);
451 
452  if (ftdi_set_latency_timer(ctx, latency_ms) < 0)
453  THROW_EXCEPTION("Error setting latency timer");
454 #else
455  MRPT_UNUSED_PARAM(latency_ms);
456 #endif
457 }
458 
459 /*-------------------------------------------------------------
460  SetTimeouts
461 -------------------------------------------------------------*/
463  unsigned long dwReadTimeout_ms, unsigned long dwWriteTimeout_ms)
464 {
465 #if MRPT_HAS_FTDI
466  ftdi_context* ctx = static_cast<ftdi_context*>(m_ftdi_context);
467  ASSERT_(ctx->usb_dev);
468 
469 // JL: It seems it works worse with timeouts...
470 // ctx->usb_read_timeout = dwReadTimeout_ms;
471 // ctx->usb_write_timeout = dwWriteTimeout_ms;
472 #else
473  MRPT_UNUSED_PARAM(dwReadTimeout_ms);
474  MRPT_UNUSED_PARAM(dwWriteTimeout_ms);
475 #endif
476 }
477 
478 /*-------------------------------------------------------------
479  OpenByDescription
480 -------------------------------------------------------------*/
481 std::ostream& mrpt::comms::operator<<(std::ostream& o, const TFTDIDevice& d)
482 {
483  o << "Manufacturer : " << d.ftdi_manufacturer << endl
484  << "Description : " << d.ftdi_description << endl
485  << "FTDI serial : " << d.ftdi_serial << endl
486  << "USB ID (Vendor/Product) : "
487  << format("%04X / %04X", d.usb_idVendor, d.usb_idProduct) << endl
488  << "USB serial : " << d.usb_serialNumber << endl;
489 
490  return o;
491 }
492 
493 #endif
mrpt::comms::CInterfaceFTDI::Purge
void Purge()
Purge the I/O buffers.
Definition: CInterfaceFTDI_WIN.cpp:337
mrpt::comms::CInterfaceFTDI::ListAllDevices
void ListAllDevices(TFTDIDeviceList &outList)
Generates a list with all FTDI devices connected right now.
Definition: CInterfaceFTDI_WIN.cpp:242
mrpt::containers::circular_buffer::clear
void clear()
Delete all the stored data, if any.
Definition: circular_buffer.h:163
exceptions.h
const_iterator
const Scalar * const_iterator
Definition: eigen_plugins.h:27
mrpt::comms::CInterfaceFTDI::~CInterfaceFTDI
virtual ~CInterfaceFTDI()
Destructor, which closes the connection with the chip and unloads the driver interface.
Definition: CInterfaceFTDI_WIN.cpp:166
mrpt::comms::TFTDIDeviceList
std::deque< TFTDIDevice > TFTDIDeviceList
Used in CInterfaceFTDI::ListAllDevices.
Definition: CInterfaceFTDI.h:46
mrpt::comms::CInterfaceFTDI::isOpen
bool isOpen()
Checks whether the chip has been successfully open.
Definition: CInterfaceFTDI_WIN.cpp:179
MRPT_UNUSED_PARAM
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.
Definition: common.h:186
mrpt::comms
Serial and networking devices and utilities.
Definition: CClientTCPSocket.h:21
THROW_EXCEPTION_FMT
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
Definition: exceptions.h:43
THROW_EXCEPTION
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:41
ASSERT_
#define ASSERT_(f)
Defines an assertion mechanism.
Definition: exceptions.h:113
mrpt::comms::CInterfaceFTDI::ResetDevice
void ResetDevice()
Reset the USB device.
Definition: CInterfaceFTDI_WIN.cpp:325
MRPT_TRY_END
#define MRPT_TRY_END
The end of a standard MRPT "try...catch()" block that allows tracing throw the call stack after an ex...
Definition: exceptions.h:231
mrpt::comms::TFTDIDevice::ftdi_description
std::string ftdi_description
Definition: CInterfaceFTDI.h:28
mrpt::format
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:16
CInterfaceFTDI.h
mrpt::comms::TFTDIDevice::usb_idVendor
uint16_t usb_idVendor
Definition: CInterfaceFTDI.h:31
mrpt::comms::TFTDIDevice
A list of FTDI devices and their descriptors.
Definition: CInterfaceFTDI.h:25
mrpt::comms::CInterfaceFTDI::Close
void Close()
Close the USB device.
Definition: CInterfaceFTDI_WIN.cpp:285
MRPT_TRY_START
#define MRPT_TRY_START
The start of a standard MRPT "try...catch()" block that allows tracing throw the call stack after an ...
Definition: exceptions.h:224
mrpt::comms::CInterfaceFTDI::m_readBuffer
mrpt::containers::circular_buffer< uint8_t > m_readBuffer
Used in Read.
Definition: CInterfaceFTDI.h:176
mrpt::comms::CInterfaceFTDI::CInterfaceFTDI
CInterfaceFTDI()
Constructor, which loads driver interface (the DLL under Windows).
Definition: CInterfaceFTDI_WIN.cpp:153
mrpt::comms::TFTDIDevice::usb_serialNumber
uint8_t usb_serialNumber
Definition: CInterfaceFTDI.h:33
mrpt::comms::CInterfaceFTDI::ftdi_read
void ftdi_read(void *lpvBuffer, unsigned long dwBuffSize, unsigned long *lpdwBytesRead)
Definition: CInterfaceFTDI_WIN.cpp:301
mrpt::comms::TFTDIDevice::ftdi_manufacturer
std::string ftdi_manufacturer
Definition: CInterfaceFTDI.h:27
string
GLsizei const GLchar ** string
Definition: glext.h:4101
mrpt::comms::CInterfaceFTDI::OpenBySerialNumber
void OpenBySerialNumber(const std::string &serialNumber)
Open by device serial number.
Definition: CInterfaceFTDI_WIN.cpp:425
mrpt::comms::TFTDIDevice::usb_idProduct
uint16_t usb_idProduct
Definition: CInterfaceFTDI.h:32
mrpt::io::CStream::printf
virtual int printf(const char *fmt,...) MRPT_printf_format_check(2
Writes a string to the stream in a textual form.
Definition: CStream.cpp:30
iterator
Scalar * iterator
Definition: eigen_plugins.h:26
mrpt::comms::CInterfaceFTDI::SetLatencyTimer
void SetLatencyTimer(unsigned char latency_ms)
Change the latency timer (in milliseconds) implemented on the FTDI chip: for a few ms,...
Definition: CInterfaceFTDI_WIN.cpp:371
mrpt::comms::CInterfaceFTDI::SetTimeouts
void SetTimeouts(unsigned long dwReadTimeout_ms, unsigned long dwWriteTimeout_ms)
Change read & write timeouts, in milliseconds.
Definition: CInterfaceFTDI_WIN.cpp:349
mrpt::comms::CInterfaceFTDI::ftdi_write
void ftdi_write(const void *lpvBuffer, unsigned long dwBuffSize, unsigned long *lpdwBytes)
Definition: CInterfaceFTDI_WIN.cpp:313
mrpt::comms::TFTDIDevice::ftdi_serial
std::string ftdi_serial
Definition: CInterfaceFTDI.h:29
mrpt::comms::operator<<
std::ostream & operator<<(std::ostream &o, const TFTDIDevice &d)
Print out all the information of a FTDI device in textual form.
Definition: CInterfaceFTDI_WIN.cpp:449



Page generated by Doxygen 1.8.17 for MRPT 1.9.9 Git: ad3a9d8ae Tue May 1 23:10:22 2018 -0700 at miƩ 12 jul 2023 10:03:34 CEST