1 /***************************************************************************
2 ftdi.cpp - C++ wrapper for libftdi
4 begin : Mon Oct 13 2008
5 copyright : (C) 2008-2020 by Marek Vavruša / libftdi developers
6 email : opensource@intra2net.com and marek@vavrusa.com
7 ***************************************************************************/
9 Copyright (C) 2008-2017 by Marek Vavruša / libftdi developers
11 The software in this package is distributed under the GNU General
12 Public License version 2 (with a special exception described below).
14 A copy of GNU General Public License (GPL) is included in this distribution,
15 in the file COPYING.GPL.
17 As a special exception, if other files instantiate templates or use macros
18 or inline functions from this file, or you compile this file and link it
19 with other works to produce a work based on this file, this file
20 does not by itself cause the resulting work to be covered
21 by the GNU General Public License.
23 However the source code for this file must still be made available
24 in accordance with section (3) of the GNU General Public License.
26 This exception does not invalidate any other reasons why a work based
27 on this file might be covered by the GNU General Public License.
30 #define _FTDI_DISABLE_DEPRECATED
38 class Context::Private
42 : open(false), ftdi(0), dev(0)
57 struct ftdi_context
* ftdi
;
58 struct libusb_device
* dev
;
61 std::string description
;
65 /*! \brief Constructor.
72 /*! \brief Destructor.
78 bool Context::is_open()
83 int Context::open(int vendor
, int product
)
86 int ret
= ftdi_usb_open(d
->ftdi
, vendor
, product
);
91 return get_strings_and_reopen(false,false,false);
94 int Context::open(int vendor
, int product
, const std::string
& description
, const std::string
& serial
, unsigned int index
)
96 // translate empty strings to NULL
97 // -> do not use them to find the device (vs. require an empty string to be set in the EEPROM)
98 const char* c_description
=NULL
;
99 const char* c_serial
=NULL
;
100 if (!description
.empty())
101 c_description
=description
.c_str();
103 c_serial
=serial
.c_str();
105 int ret
= ftdi_usb_open_desc_index(d
->ftdi
, vendor
, product
, c_description
, c_serial
, index
);
110 return get_strings_and_reopen(false,!description
.empty(),!serial
.empty());
113 int Context::open(const std::string
& description
)
115 int ret
= ftdi_usb_open_string(d
->ftdi
, description
.c_str());
120 return get_strings_and_reopen(false,true,false);
123 int Context::open(struct libusb_device
*dev
)
131 return get_strings_and_reopen();
138 return ftdi_usb_close(d
->ftdi
);
143 return ftdi_usb_reset(d
->ftdi
);
146 int Context::flush(int mask
)
150 switch (mask
& (Input
| Output
)) {
152 ret
= ftdi_usb_purge_rx_buffer(d
->ftdi
);
156 ret
= ftdi_usb_purge_tx_buffer(d
->ftdi
);
160 ret
= ftdi_usb_purge_buffers(d
->ftdi
);
164 // Emulate behavior of previous version.
172 int Context::tcflush(int mask
)
176 switch (mask
& (Input
| Output
)) {
178 ret
= ftdi_tciflush(d
->ftdi
);
182 ret
= ftdi_tcoflush(d
->ftdi
);
186 ret
= ftdi_tcioflush(d
->ftdi
);
190 // Emulate behavior of previous version.
198 int Context::set_interface(enum ftdi_interface interface
)
200 return ftdi_set_interface(d
->ftdi
, interface
);
203 void Context::set_usb_device(struct libusb_device_handle
*dev
)
205 ftdi_set_usbdev(d
->ftdi
, dev
);
206 d
->dev
= libusb_get_device(dev
);
209 int Context::set_baud_rate(int baudrate
)
211 return ftdi_set_baudrate(d
->ftdi
, baudrate
);
214 int Context::set_line_property(enum ftdi_bits_type bits
, enum ftdi_stopbits_type sbit
, enum ftdi_parity_type parity
)
216 return ftdi_set_line_property(d
->ftdi
, bits
, sbit
, parity
);
219 int Context::set_line_property(enum ftdi_bits_type bits
, enum ftdi_stopbits_type sbit
, enum ftdi_parity_type parity
, enum ftdi_break_type break_type
)
221 return ftdi_set_line_property2(d
->ftdi
, bits
, sbit
, parity
, break_type
);
224 int Context::get_usb_read_timeout() const
226 return d
->ftdi
->usb_read_timeout
;
229 void Context::set_usb_read_timeout(int usb_read_timeout
)
231 d
->ftdi
->usb_read_timeout
= usb_read_timeout
;
234 int Context::get_usb_write_timeout() const
236 return d
->ftdi
->usb_write_timeout
;
239 void Context::set_usb_write_timeout(int usb_write_timeout
)
241 d
->ftdi
->usb_write_timeout
= usb_write_timeout
;
244 int Context::read(unsigned char *buf
, int size
)
246 return ftdi_read_data(d
->ftdi
, buf
, size
);
249 int Context::set_read_chunk_size(unsigned int chunksize
)
251 return ftdi_read_data_set_chunksize(d
->ftdi
, chunksize
);
254 int Context::read_chunk_size()
257 if (ftdi_read_data_get_chunksize(d
->ftdi
, &chunk
) < 0)
263 int Context::write(const unsigned char *buf
, int size
)
265 return ftdi_write_data(d
->ftdi
, buf
, size
);
268 int Context::set_write_chunk_size(unsigned int chunksize
)
270 return ftdi_write_data_set_chunksize(d
->ftdi
, chunksize
);
273 int Context::write_chunk_size()
276 if (ftdi_write_data_get_chunksize(d
->ftdi
, &chunk
) < 0)
282 int Context::set_flow_control(int flowctrl
)
284 return ftdi_setflowctrl(d
->ftdi
, flowctrl
);
287 int Context::set_modem_control(int mask
)
289 int dtr
= 0, rts
= 0;
296 return ftdi_setdtr_rts(d
->ftdi
, dtr
, rts
);
299 int Context::set_dtr(bool state
)
301 return ftdi_setdtr(d
->ftdi
, state
);
304 int Context::set_rts(bool state
)
306 return ftdi_setrts(d
->ftdi
, state
);
309 int Context::set_latency(unsigned char latency
)
311 return ftdi_set_latency_timer(d
->ftdi
, latency
);
314 unsigned Context::latency()
316 unsigned char latency
= 0;
317 ftdi_get_latency_timer(d
->ftdi
, &latency
);
321 unsigned short Context::poll_modem_status()
323 unsigned short status
= 0;
324 ftdi_poll_modem_status(d
->ftdi
, &status
);
328 int Context::set_event_char(unsigned char eventch
, unsigned char enable
)
330 return ftdi_set_event_char(d
->ftdi
, eventch
, enable
);
333 int Context::set_error_char(unsigned char errorch
, unsigned char enable
)
335 return ftdi_set_error_char(d
->ftdi
, errorch
, enable
);
338 int Context::set_bitmode(unsigned char bitmask
, unsigned char mode
)
340 return ftdi_set_bitmode(d
->ftdi
, bitmask
, mode
);
343 int Context::set_bitmode(unsigned char bitmask
, enum ftdi_mpsse_mode mode
)
345 return ftdi_set_bitmode(d
->ftdi
, bitmask
, mode
);
348 int Context::bitbang_disable()
350 return ftdi_disable_bitbang(d
->ftdi
);
353 int Context::read_pins(unsigned char *pins
)
355 return ftdi_read_pins(d
->ftdi
, pins
);
358 const char* Context::error_string()
360 return ftdi_get_error_string(d
->ftdi
);
363 int Context::get_strings(bool vendor
, bool description
, bool serial
)
366 char ivendor
[512], idesc
[512], iserial
[512];
368 int ret
= ftdi_usb_get_strings(d
->ftdi
, d
->dev
, vendor
?ivendor
:NULL
, 512, description
?idesc
:NULL
, 512, serial
?iserial
:NULL
, 512);
374 d
->description
= idesc
;
380 int Context::get_strings_and_reopen(bool vendor
, bool description
, bool serial
)
384 if(vendor
|| description
|| serial
)
388 d
->dev
= libusb_get_device(d
->ftdi
->usb_dev
);
391 // Get device strings (closes device)
392 ret
=get_strings(vendor
, description
, serial
);
400 ret
= ftdi_usb_open_dev(d
->ftdi
, d
->dev
);
401 d
->open
= (ret
>= 0);
407 /*! \brief Device strings properties.
409 const std::string
& Context::vendor()
411 if(d
->vendor
.empty())
412 get_strings_and_reopen(true,false,false);
416 /*! \brief Device strings properties.
418 const std::string
& Context::description()
420 if(d
->description
.empty())
421 get_strings_and_reopen(false,true,false);
422 return d
->description
;
425 /*! \brief Device strings properties.
427 const std::string
& Context::serial()
429 if(d
->serial
.empty())
430 get_strings_and_reopen(false,false,true);
434 void Context::set_context(struct ftdi_context
* context
)
440 void Context::set_usb_device(struct libusb_device
*dev
)
445 struct ftdi_context
* Context::context()
450 class Eeprom::Private
457 struct ftdi_eeprom eeprom
;
458 struct ftdi_context
* context
;
461 Eeprom::Eeprom(Context
* parent
)
462 : d ( new Private() )
464 d
->context
= parent
->context();
471 int Eeprom::init_defaults(char* manufacturer
, char *product
, char * serial
)
473 return ftdi_eeprom_initdefaults(d
->context
, manufacturer
, product
, serial
);
476 int Eeprom::chip_id(unsigned int *chipid
)
478 return ftdi_read_chipid(d
->context
, chipid
);
481 int Eeprom::build(unsigned char *output
)
483 return ftdi_eeprom_build(d
->context
);
486 int Eeprom::read(unsigned char *eeprom
)
488 return ftdi_read_eeprom(d
->context
);
491 int Eeprom::write(unsigned char *eeprom
)
493 return ftdi_write_eeprom(d
->context
);
496 int Eeprom::read_location(int eeprom_addr
, unsigned short *eeprom_val
)
498 return ftdi_read_eeprom_location(d
->context
, eeprom_addr
, eeprom_val
);
501 int Eeprom::write_location(int eeprom_addr
, unsigned short eeprom_val
)
503 return ftdi_write_eeprom_location(d
->context
, eeprom_addr
, eeprom_val
);
508 return ftdi_erase_eeprom(d
->context
);
514 Private(struct ftdi_device_list
* _devlist
)
521 ftdi_list_free(&devlist
);
524 std::list
<Context
> list
;
525 struct ftdi_device_list
* devlist
;
528 List::List(struct ftdi_device_list
* devlist
)
529 : d( new Private(devlist
) )
534 for (; devlist
!= 0; devlist
= devlist
->next
)
537 c
.set_usb_device(devlist
->dev
);
539 d
->list
.push_back(c
);
549 * Return begin iterator for accessing the contained list elements
552 List::iterator
List::begin()
554 return d
->list
.begin();
558 * Return end iterator for accessing the contained list elements
561 List::iterator
List::end()
563 return d
->list
.end();
567 * Return begin iterator for accessing the contained list elements
568 * @return Const iterator
570 List::const_iterator
List::begin() const
572 return d
->list
.begin();
576 * Return end iterator for accessing the contained list elements
577 * @return Const iterator
579 List::const_iterator
List::end() const
581 return d
->list
.end();
585 * Return begin reverse iterator for accessing the contained list elements
586 * @return Reverse iterator
588 List::reverse_iterator
List::rbegin()
590 return d
->list
.rbegin();
594 * Return end reverse iterator for accessing the contained list elements
595 * @return Reverse iterator
597 List::reverse_iterator
List::rend()
599 return d
->list
.rend();
603 * Return begin reverse iterator for accessing the contained list elements
604 * @return Const reverse iterator
606 List::const_reverse_iterator
List::rbegin() const
608 return d
->list
.rbegin();
612 * Return end reverse iterator for accessing the contained list elements
613 * @return Const reverse iterator
615 List::const_reverse_iterator
List::rend() const
617 return d
->list
.rend();
622 * Get number of elements stored in the list
623 * @return Number of elements
625 List::ListType::size_type
List::size() const
627 return d
->list
.size();
631 * Check if list is empty
632 * @return True if empty, false otherwise
634 bool List::empty() const
636 return d
->list
.empty();
640 * Removes all elements. Invalidates all iterators.
641 * Do it in a non-throwing way and also make
642 * sure we really free the allocated memory.
646 ListType().swap(d
->list
);
651 ftdi_list_free(&d
->devlist
);
657 * Appends a copy of the element as the new last element.
658 * @param element Value to copy and append
660 void List::push_back(const Context
& element
)
662 d
->list
.push_back(element
);
666 * Adds a copy of the element as the new first element.
667 * @param element Value to copy and add
669 void List::push_front(const Context
& element
)
671 d
->list
.push_front(element
);
675 * Erase one element pointed by iterator
676 * @param pos Element to erase
677 * @return Position of the following element (or end())
679 List::iterator
List::erase(iterator pos
)
681 return d
->list
.erase(pos
);
685 * Erase a range of elements
686 * @param beg Begin of range
687 * @param end End of range
688 * @return Position of the element after the erased range (or end())
690 List::iterator
List::erase(iterator beg
, iterator end
)
692 return d
->list
.erase(beg
, end
);
695 List
* List::find_all(Context
&context
, int vendor
, int product
)
697 struct ftdi_device_list
* dlist
= 0;
698 ftdi_usb_find_all(context
.context(), &dlist
, vendor
, product
);
699 return new List(dlist
);