CMake: bump the minimal required version to 3.5
[libftdi.git] / ftdipp / ftdi.cpp
blobafb84fb9367ef8e26eb39b8ef1247522ce80a0c7
1 /***************************************************************************
2 ftdi.cpp - C++ wrapper for libftdi
3 -------------------
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 ***************************************************************************/
8 /*
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.
29 #include <libusb.h>
30 #define _FTDI_DISABLE_DEPRECATED
31 #include "ftdi.hpp"
32 #include "ftdi_i.h"
33 #include "ftdi.h"
35 namespace Ftdi
38 class Context::Private
40 public:
41 Private()
42 : open(false), ftdi(0), dev(0)
44 ftdi = ftdi_new();
47 ~Private()
49 if (open)
50 ftdi_usb_close(ftdi);
52 ftdi_free(ftdi);
55 bool open;
57 struct ftdi_context* ftdi;
58 struct libusb_device* dev;
60 std::string vendor;
61 std::string description;
62 std::string serial;
65 /*! \brief Constructor.
67 Context::Context()
68 : d( new Private() )
72 /*! \brief Destructor.
74 Context::~Context()
78 bool Context::is_open()
80 return d->open;
83 int Context::open(int vendor, int product)
85 // Open device
86 int ret = ftdi_usb_open(d->ftdi, vendor, product);
88 if (ret < 0)
89 return ret;
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();
102 if (!serial.empty())
103 c_serial=serial.c_str();
105 int ret = ftdi_usb_open_desc_index(d->ftdi, vendor, product, c_description, c_serial, index);
107 if (ret < 0)
108 return ret;
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());
117 if (ret < 0)
118 return ret;
120 return get_strings_and_reopen(false,true,false);
123 int Context::open(struct libusb_device *dev)
125 if (dev != 0)
126 d->dev = dev;
128 if (d->dev == 0)
129 return -1;
131 return get_strings_and_reopen();
134 int Context::close()
136 d->open = false;
137 d->dev = 0;
138 return ftdi_usb_close(d->ftdi);
141 int Context::reset()
143 return ftdi_usb_reset(d->ftdi);
146 int Context::flush(int mask)
148 int ret;
150 switch (mask & (Input | Output)) {
151 case Input:
152 ret = ftdi_usb_purge_rx_buffer(d->ftdi);
153 break;
155 case Output:
156 ret = ftdi_usb_purge_tx_buffer(d->ftdi);
157 break;
159 case Input | Output:
160 ret = ftdi_usb_purge_buffers(d->ftdi);
161 break;
163 default:
164 // Emulate behavior of previous version.
165 ret = 1;
166 break;
169 return ret;
172 int Context::tcflush(int mask)
174 int ret;
176 switch (mask & (Input | Output)) {
177 case Input:
178 ret = ftdi_tciflush(d->ftdi);
179 break;
181 case Output:
182 ret = ftdi_tcoflush(d->ftdi);
183 break;
185 case Input | Output:
186 ret = ftdi_tcioflush(d->ftdi);
187 break;
189 default:
190 // Emulate behavior of previous version.
191 ret = 1;
192 break;
195 return ret;
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()
256 unsigned chunk = -1;
257 if (ftdi_read_data_get_chunksize(d->ftdi, &chunk) < 0)
258 return -1;
260 return chunk;
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()
275 unsigned chunk = -1;
276 if (ftdi_write_data_get_chunksize(d->ftdi, &chunk) < 0)
277 return -1;
279 return chunk;
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;
291 if (mask & Dtr)
292 dtr = 1;
293 if (mask & Rts)
294 rts = 1;
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);
318 return latency;
321 unsigned short Context::poll_modem_status()
323 unsigned short status = 0;
324 ftdi_poll_modem_status(d->ftdi, &status);
325 return 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)
365 // Prepare buffers
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);
370 if (ret < 0)
371 return -1;
373 d->vendor = ivendor;
374 d->description = idesc;
375 d->serial = iserial;
377 return 1;
380 int Context::get_strings_and_reopen(bool vendor, bool description, bool serial)
382 int ret = 0;
384 if(vendor || description || serial)
386 if (d->dev == 0)
388 d->dev = libusb_get_device(d->ftdi->usb_dev);
391 // Get device strings (closes device)
392 ret=get_strings(vendor, description, serial);
393 if (ret < 0)
395 d->open = 0;
396 return ret;
399 // Reattach device
400 ret = ftdi_usb_open_dev(d->ftdi, d->dev);
401 d->open = (ret >= 0);
404 return ret;
407 /*! \brief Device strings properties.
409 const std::string& Context::vendor()
411 if(d->vendor.empty())
412 get_strings_and_reopen(true,false,false);
413 return d->vendor;
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);
431 return d->serial;
434 void Context::set_context(struct ftdi_context* context)
436 ftdi_free(d->ftdi);
437 d->ftdi = context;
440 void Context::set_usb_device(struct libusb_device *dev)
442 d->dev = dev;
445 struct ftdi_context* Context::context()
447 return d->ftdi;
450 class Eeprom::Private
452 public:
453 Private()
454 : context(0)
457 struct ftdi_eeprom eeprom;
458 struct ftdi_context* context;
461 Eeprom::Eeprom(Context* parent)
462 : d ( new Private() )
464 d->context = parent->context();
467 Eeprom::~Eeprom()
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);
506 int Eeprom::erase()
508 return ftdi_erase_eeprom(d->context);
511 class List::Private
513 public:
514 Private(struct ftdi_device_list* _devlist)
515 : devlist(_devlist)
518 ~Private()
520 if(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) )
531 if (devlist != 0)
533 // Iterate list
534 for (; devlist != 0; devlist = devlist->next)
536 Context c;
537 c.set_usb_device(devlist->dev);
538 c.get_strings();
539 d->list.push_back(c);
544 List::~List()
549 * Return begin iterator for accessing the contained list elements
550 * @return Iterator
552 List::iterator List::begin()
554 return d->list.begin();
558 * Return end iterator for accessing the contained list elements
559 * @return Iterator
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.
644 void List::clear()
646 ListType().swap(d->list);
648 // Free device list
649 if (d->devlist)
651 ftdi_list_free(&d->devlist);
652 d->devlist = 0;
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);