Main MRPT website > C++ reference for MRPT 1.5.6
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-2017, 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 
12 #include <mrpt/utils/utils_defs.h>
13 #include <cstring>
14 
15 using namespace mrpt;
16 using namespace mrpt::utils;
17 
18 #if defined(MRPT_OS_LINUX) || defined(MRPT_OS_APPLE)
19 
20 #if MRPT_HAS_FTDI
21  #include <ftdi.h>
22 # if MRPT_FTDI_VERSION>=0x120
23  #include <libusb-1.0/libusb.h>
24 #else
25  #include <usb.h>
26 # endif
27 #endif
28 
30 
31 #include <iostream>
32 
33 using namespace mrpt::hwdrivers;
34 using namespace std;
35 
36 /*-------------------------------------------------------------
37  CInterfaceFTDI
38 -------------------------------------------------------------*/
39 CInterfaceFTDI::CInterfaceFTDI() :
40  m_readBuffer(4096)
41 {
43 
44 #if MRPT_HAS_FTDI
45  // Alloc mem:
46  ftdi_context *newCtx = new ftdi_context[1];
47  ASSERT_(newCtx);
48 
49  // Init:
50  int ret = ftdi_init(newCtx);
51  if (ret) THROW_EXCEPTION("There was a problem initializing ftdi_context.");
52 
53  // Save in member:
54  m_ftdi_context = static_cast<void*>(newCtx);
55 #else
56  THROW_EXCEPTION("MRPT has been compiled without FTDI support. Please, reconfigure and recompile MRPT.")
57 #endif
58 
59 #if MRPT_FTDI_VERSION>=0x120
60  libusb_init(NULL);
61 #endif
63 }
64 
65 /*-------------------------------------------------------------
66  ~CInterfaceFTDI
67 -------------------------------------------------------------*/
69 {
70 #if MRPT_HAS_FTDI
71  // Close USB:
72  if (isOpen())
73  Close();
74  ftdi_context *ctx = static_cast<ftdi_context *>(m_ftdi_context);
75 
76  // Close context:
77  ftdi_deinit( ctx );
78 
79  // Free mem:
80  delete[] ctx;
81  ctx = NULL;
82 #endif
83 #if MRPT_FTDI_VERSION>=0x120
84  libusb_exit(NULL);
85 #endif
86 }
87 
88 /** This object cannot be copied */
90  m_readBuffer(4096)
91 {
93  THROW_EXCEPTION("This object cannot be copied");
95 }
97 {
99  THROW_EXCEPTION("This object cannot be copied");
101 }
102 
103 /*-------------------------------------------------------------
104  OpenBySerialNumber
105 -------------------------------------------------------------*/
106 void CInterfaceFTDI::OpenBySerialNumber( const std::string &serialNumber )
107 {
108 #if MRPT_HAS_FTDI
110 
112 
113  // Close previous connection:
114  Close();
115 
116 
117  // ftdi_usb_open_desc ...
118 
119  // Create a list of all the devices:
120  TFTDIDeviceList lstDevs;
121  ListAllDevices( lstDevs );
122 
123  // Look for the one we want:
124  void *myDev = NULL;
125 
126  for (TFTDIDeviceList::iterator it=lstDevs.begin();it!=lstDevs.end();++it)
127  {
128  if (it->ftdi_serial == serialNumber)
129  {
130  myDev = it->usb_device_struct;
131  break;
132  }
133  }
134 
135  if (!myDev)
136  THROW_EXCEPTION_FMT("USB device with serial number '%s' not found.",serialNumber.c_str());
137 
138  // Open it:
139  ftdi_context *ctx = static_cast<ftdi_context *>(m_ftdi_context);
140 
141  int ret=ftdi_usb_open_dev( ctx,
142 # if MRPT_FTDI_VERSION>=0x120
143  (struct libusb_device*) myDev
144 #else
145  (struct usb_device*) myDev
146 #endif
147  );
148 
149  if (ret) THROW_EXCEPTION( string(ftdi_get_error_string(ctx)) );
150 
152 #else
153  MRPT_UNUSED_PARAM(serialNumber);
154 #endif
155 }
156 
157 /*-------------------------------------------------------------
158  ListAllDevices
159 -------------------------------------------------------------*/
161 {
163 #if MRPT_HAS_FTDI
164 
165  outList.clear();
166 
167 #if MRPT_FTDI_VERSION>=0x120
168  // For new libftdi1-dev
169  // Use libusb-1.0
170 
171  libusb_device **list;
172  ssize_t nDevices = libusb_get_device_list(NULL,&list);
173 
174  for (unsigned int i = 0; i < nDevices; i++) {
175  libusb_device *device = list[i];
176  struct libusb_device_descriptor desc;
177  if (0!=libusb_get_device_descriptor(device,&desc))
178  continue;
179  if (!desc.idVendor) continue;
180 
181  TFTDIDevice newEntry;
182  newEntry.usb_device_struct = (void*)device;
183  newEntry.usb_idProduct = desc.idProduct;
184  newEntry.usb_idVendor = desc.idVendor;
185  newEntry.usb_serialNumber = desc.iSerialNumber;
186 
187  // Open the device temporally so we can get more info:
188  libusb_device_handle *handle;
189  if (0!=libusb_open(device,&handle))
190  continue;
191 
192  char buf[1024];
193  int ret;
194  // manufacturer
195  ret=libusb_get_string_descriptor_ascii(handle,desc.iManufacturer,(unsigned char*)buf,sizeof(buf)-1);
196  if (ret<0) continue;
197  buf[ret]='\0';
198  newEntry.ftdi_manufacturer = buf;
199 
200  // description
201  ret=libusb_get_string_descriptor_ascii(handle,desc.iProduct,(unsigned char*)buf,sizeof(buf)-1);
202  if (ret<0) continue;
203  buf[ret]='\0';
204  newEntry.ftdi_description = buf;
205 
206  // serial
207  ret=libusb_get_string_descriptor_ascii(handle,desc.iSerialNumber,(unsigned char*)buf,sizeof(buf)-1);
208  if (ret<0) continue;
209  buf[ret]='\0';
210  newEntry.ftdi_serial = buf;
211 
212  outList.push_back(newEntry);
213  }
214 
215 #else
216  // For old libftdi-dev
217  // Use old usb.h interface
218  struct usb_bus *bus;
219  struct usb_device *dev;
220 
221  usb_init();
222  if (usb_find_busses() < 0)
223  THROW_EXCEPTION("usb_find_busses() failed");
224  if (usb_find_devices() < 0)
225  THROW_EXCEPTION("usb_find_devices() failed");
226 
227  for (bus = usb_busses; bus; bus = bus->next)
228  for (dev = bus->devices; dev; dev = dev->next)
229  recursive_fill_list_devices( dev, outList ); // Process this node and its children:
230 
231 #endif
232  if (getenv("VERBOSE")!=NULL)
233  {
234  printf("[CInterfaceFTDI::ListAllDevices] List: \n");
235  for (std::deque<TFTDIDevice>::const_iterator i=outList.begin();i!=outList.end();++i)
236  printf("USB DEV: V=%04X P=%04X S=%s\n",i->usb_idVendor,i->usb_idProduct, i->ftdi_serial.c_str());
237  }
238 
239 #else
240  MRPT_UNUSED_PARAM(outList);
241 #endif
243 }
244 
245 
246 void CInterfaceFTDI::recursive_fill_list_devices( void *usb_device_structure , TFTDIDeviceList &outList )
247 {
248 #if MRPT_HAS_FTDI
249 #if MRPT_FTDI_VERSION>=0x120
250  // For new libftdi1-dev
251  throw std::runtime_error("Should not have got to this function!");
252 #else
253  // For old libftdi-dev
254  struct usb_device *dev = (struct usb_device *) usb_device_structure;
255 
256  if (dev->descriptor.idProduct && dev->descriptor.idVendor)
257  {
258  TFTDIDevice newEntry;
259  newEntry.usb_idProduct = dev->descriptor.idProduct;
260  newEntry.usb_idVendor = dev->descriptor.idVendor;
261  newEntry.usb_device_struct = (void*)dev;
262 
263  int strLen;
264 
265  // Open the device temporally so we can get more info:
266  usb_dev_handle * hUSB = usb_open(dev);
267 
268  if (hUSB)
269  {
270  char manufacturer[3000];
271  if ((strLen=usb_get_string_simple(hUSB, dev->descriptor.iManufacturer, manufacturer, sizeof(manufacturer))) <=0)
272  {
273  cerr << "Couldn't open " << (int)dev->descriptor.iManufacturer << endl;
274  //usb_close(hUSB); hUSB=NULL;
275  }
276  else
277  {
278  manufacturer[strLen]='\0';
279  //cout << "Manuf: " << manufacturer << endl;
280  newEntry.ftdi_manufacturer = manufacturer;
281  }
282  }
283 
284  if (hUSB)
285  {
286  char description[3000];
287  if ((strLen=usb_get_string_simple(hUSB, dev->descriptor.iProduct, description, sizeof(description))) <=0)
288  {
289  //usb_close(hUSB); hUSB=NULL;
290  }
291  else
292  {
293  description[strLen]='\0';
294  newEntry.ftdi_description = description;
295  }
296  }
297 
298  if (hUSB)
299  {
300  char serial[300];
301  if ((strLen=usb_get_string_simple(hUSB, dev->descriptor.iSerialNumber, serial, sizeof(serial))) <=0)
302  {
303  //usb_close(hUSB); hUSB=NULL;
304  }
305  else
306  {
307  serial[strLen]='\0';
308  newEntry.ftdi_serial = serial;
309  }
310  }
311 
312  if (hUSB)
313  {
314  outList.push_back( newEntry );
315  usb_close( hUSB );
316  }
317 
318  // And now its children:
319  // -----------------------------------
320  for (unsigned char j=0;j<dev->num_children;j++)
321  recursive_fill_list_devices( (void*)dev->children[j], outList );
322  }
323 #endif
324 #else
325  MRPT_UNUSED_PARAM(usb_device_structure); MRPT_UNUSED_PARAM(outList);
326 #endif
327 }
328 
329 /*-------------------------------------------------------------
330  ftdi_read
331 -------------------------------------------------------------*/
332 void CInterfaceFTDI::ftdi_read(void *lpvBuffer, unsigned long dwBuffSize, unsigned long *lpdwBytesRead)
333 {
334 #if MRPT_HAS_FTDI
336  ftdi_context *ctx = static_cast<ftdi_context *>(m_ftdi_context);
337 
338  int ret = ftdi_read_data(ctx,(unsigned char*)lpvBuffer, dwBuffSize );
339  if (ret>=0)
340  *lpdwBytesRead = ret;
341  else
342  {
343  if (!strcmp("usb bulk read failed",ctx->error_str))
344  {
345  *lpdwBytesRead = 0;
346  return;
347  }
348  THROW_EXCEPTION( string(ftdi_get_error_string(ctx)) );
349  }
350 
352 #else
353  MRPT_UNUSED_PARAM(lpvBuffer); MRPT_UNUSED_PARAM(dwBuffSize); MRPT_UNUSED_PARAM(lpdwBytesRead);
354 #endif
355 }
356 
357 /*-------------------------------------------------------------
358  ftdi_write
359 -------------------------------------------------------------*/
360 void CInterfaceFTDI::ftdi_write(const void *lpvBuffer, unsigned long dwBuffSize, unsigned long *lpdwBytes)
361 {
362 #if MRPT_HAS_FTDI
364  ftdi_context *ctx = static_cast<ftdi_context *>(m_ftdi_context);
365 
366  int ret = ftdi_write_data(ctx,(unsigned char*)lpvBuffer, dwBuffSize );
367  if (ret>=0)
368  *lpdwBytes = ret;
369  else
370  THROW_EXCEPTION( string(ftdi_get_error_string(ctx)) );
371 
373 #else
374  MRPT_UNUSED_PARAM(lpvBuffer); MRPT_UNUSED_PARAM(dwBuffSize); 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 != NULL;
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 = NULL;
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)
422  THROW_EXCEPTION("Error resetting device");
423 
425 #endif
426 }
427 
428 /*-------------------------------------------------------------
429  Purge
430 -------------------------------------------------------------*/
432 {
433 #if MRPT_HAS_FTDI
434  ftdi_context *ctx = static_cast<ftdi_context *>(m_ftdi_context);
435  ASSERT_(ctx->usb_dev);
436 
437  if (ftdi_usb_purge_buffers(ctx)<0)
438  THROW_EXCEPTION("Error purging device buffers");
439 
441 #endif
442 }
443 
444 /*-------------------------------------------------------------
445  SetLatencyTimer
446 -------------------------------------------------------------*/
447 void CInterfaceFTDI::SetLatencyTimer (unsigned char latency_ms)
448 {
449 #if MRPT_HAS_FTDI
450  ftdi_context *ctx = static_cast<ftdi_context *>(m_ftdi_context);
451  ASSERT_(ctx->usb_dev);
452 
453  if (ftdi_set_latency_timer(ctx, latency_ms)<0)
454  THROW_EXCEPTION("Error setting latency timer");
455 #else
456  MRPT_UNUSED_PARAM(latency_ms);
457 #endif
458 }
459 
460 /*-------------------------------------------------------------
461  SetTimeouts
462 -------------------------------------------------------------*/
463 void CInterfaceFTDI::SetTimeouts(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); MRPT_UNUSED_PARAM(dwWriteTimeout_ms);
474 #endif
475 }
476 
477 
478 /*-------------------------------------------------------------
479  OpenByDescription
480 -------------------------------------------------------------*/
481 std::ostream & mrpt::hwdrivers::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) : " << format("%04X / %04X", d.usb_idVendor, d.usb_idProduct) << endl
487  << "USB serial : " << d.usb_serialNumber << endl;
488 
489  return o;
490 }
491 
492 #endif
493 
494 
495 
496 
void SetTimeouts(unsigned long dwReadTimeout_ms, unsigned long dwWriteTimeout_ms)
Change read & write timeouts, in milliseconds.
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
Definition: zip.h:16
std::ostream HWDRIVERS_IMPEXP & operator<<(std::ostream &o, const TFTDIDevice &d)
Print out all the information of a FTDI device in textual form.
void ftdi_write(const void *lpvBuffer, unsigned long dwBuffSize, unsigned long *lpdwBytes)
void clear()
Delete all the stored data, if any.
#define THROW_EXCEPTION(msg)
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
void OpenBySerialNumber(const std::string &serialNumber)
Open by device serial number.
Scalar * iterator
Definition: eigen_plugins.h:23
bool isOpen()
Checks whether the chip has been successfully open.
Contains classes for various device interfaces.
STL namespace.
const Scalar * const_iterator
Definition: eigen_plugins.h:24
void Purge()
Purge the I/O buffers.
#define MRPT_TRY_END
CInterfaceFTDI()
Constructor, which loads driver interface (the DLL under Windows).
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
CInterfaceFTDI & operator=(const CInterfaceFTDI &o)
This object cannot be copied.
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:21
void ftdi_read(void *lpvBuffer, unsigned long dwBuffSize, unsigned long *lpdwBytesRead)
GLsizei const GLchar ** string
Definition: glext.h:3919
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void SetLatencyTimer(unsigned char latency_ms)
Change the latency timer (in milliseconds) implemented on the FTDI chip: for a few ms...
#define MRPT_TRY_START
#define ASSERT_(f)
void recursive_fill_list_devices(void *usb_device_structure, TFTDIDeviceList &outList)
Process recursively a USB device and its children:
void ListAllDevices(TFTDIDeviceList &outList)
Generates a list with all FTDI devices connected right now.
std::deque< TFTDIDevice > TFTDIDeviceList
Used in CInterfaceFTDI::ListAllDevices.
A list of FTDI devices and their descriptors.
A definition of a CStream actually representing a USB connection to a FTDI chip.
void ResetDevice()
Reset the USB device.
virtual int printf(const char *fmt,...) MRPT_printf_format_check(2
Writes a string to the stream in a textual form.
Definition: CStream.cpp:507
mrpt::utils::circular_buffer< uint8_t > m_readBuffer
Used in Read.
virtual ~CInterfaceFTDI()
Destructor, which closes the connection with the chip and unloads the driver interface.
void Close()
Close the USB device.



Page generated by Doxygen 1.8.14 for MRPT 1.5.6 Git: 4c65e8431 Tue Apr 24 08:18:17 2018 +0200 at lun oct 28 01:35:26 CET 2019