1 /***************************************************************************
2 ftdi.cpp - C++ wraper for libftdi
4 begin : Mon Oct 13 2008
5 copyright : (C) 2008 by Marek Vavruša
6 email : opensource@intra2net.com and marek@vavrusa.com
7 ***************************************************************************/
9 Copyright (C) 2008 by Marek Vavruša
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.
35 class Context::Private
39 : ftdi(0), dev(0), open(false)
54 struct ftdi_context* ftdi;
55 struct libusb_device* dev;
58 std::string description;
62 /*! \brief Constructor.
69 /*! \brief Destructor.
75 bool Context::is_open()
80 int Context::open(int vendor, int product)
83 int ret = ftdi_usb_open(d->ftdi, vendor, product);
88 return get_strings_and_reopen();
91 int Context::open(int vendor, int product, const std::string& description, const std::string& serial, unsigned int index)
93 // translate empty strings to NULL
94 // -> do not use them to find the device (vs. require an empty string to be set in the EEPROM)
95 const char* c_description=NULL;
96 const char* c_serial=NULL;
97 if (!description.empty())
98 c_description=description.c_str();
100 c_serial=serial.c_str();
102 int ret = ftdi_usb_open_desc_index(d->ftdi, vendor, product, c_description, c_serial, index);
107 return get_strings_and_reopen();
110 int Context::open(const std::string& description)
112 int ret = ftdi_usb_open_string(d->ftdi, description.c_str());
117 return get_strings_and_reopen();
120 int Context::open(struct libusb_device *dev)
128 return get_strings_and_reopen();
134 return ftdi_usb_close(d->ftdi);
139 return ftdi_usb_reset(d->ftdi);
142 int Context::flush(int mask)
147 ret &= ftdi_usb_purge_rx_buffer(d->ftdi);
149 ret &= ftdi_usb_purge_tx_buffer(d->ftdi);
154 int Context::set_interface(enum ftdi_interface interface)
156 return ftdi_set_interface(d->ftdi, interface);
159 void Context::set_usb_device(struct libusb_device_handle *dev)
161 ftdi_set_usbdev(d->ftdi, dev);
162 d->dev = libusb_get_device(dev);
165 int Context::set_baud_rate(int baudrate)
167 return ftdi_set_baudrate(d->ftdi, baudrate);
170 int Context::set_line_property(enum ftdi_bits_type bits, enum ftdi_stopbits_type sbit, enum ftdi_parity_type parity)
172 return ftdi_set_line_property(d->ftdi, bits, sbit, parity);
175 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)
177 return ftdi_set_line_property2(d->ftdi, bits, sbit, parity, break_type);
180 int Context::read(unsigned char *buf, int size)
182 return ftdi_read_data(d->ftdi, buf, size);
185 int Context::set_read_chunk_size(unsigned int chunksize)
187 return ftdi_read_data_set_chunksize(d->ftdi, chunksize);
190 int Context::read_chunk_size()
193 if (ftdi_read_data_get_chunksize(d->ftdi, &chunk) < 0)
199 int Context::write(unsigned char *buf, int size)
201 return ftdi_write_data(d->ftdi, buf, size);
204 int Context::set_write_chunk_size(unsigned int chunksize)
206 return ftdi_write_data_set_chunksize(d->ftdi, chunksize);
209 int Context::write_chunk_size()
212 if (ftdi_write_data_get_chunksize(d->ftdi, &chunk) < 0)
218 int Context::set_flow_control(int flowctrl)
220 return ftdi_setflowctrl(d->ftdi, flowctrl);
223 int Context::set_modem_control(int mask)
225 int dtr = 0, rts = 0;
232 return ftdi_setdtr_rts(d->ftdi, dtr, rts);
235 int Context::set_dtr(bool state)
237 return ftdi_setdtr(d->ftdi, state);
240 int Context::set_rts(bool state)
242 return ftdi_setrts(d->ftdi, state);
245 int Context::set_latency(unsigned char latency)
247 return ftdi_set_latency_timer(d->ftdi, latency);
250 unsigned Context::latency()
252 unsigned char latency = 0;
253 ftdi_get_latency_timer(d->ftdi, &latency);
257 unsigned short Context::poll_modem_status()
259 unsigned short status = 0;
260 ftdi_poll_modem_status(d->ftdi, &status);
264 int Context::set_event_char(unsigned char eventch, unsigned char enable)
266 return ftdi_set_event_char(d->ftdi, eventch, enable);
269 int Context::set_error_char(unsigned char errorch, unsigned char enable)
271 return ftdi_set_error_char(d->ftdi, errorch, enable);
274 int Context::bitbang_enable(unsigned char bitmask)
276 return ftdi_set_bitmode(d->ftdi, bitmask, BITMODE_BITBANG);
279 int Context::bitbang_disable()
281 return ftdi_disable_bitbang(d->ftdi);
284 int Context::set_bitmode(unsigned char bitmask, unsigned char mode)
286 return set_bitmode(bitmask, mode);
289 int Context::set_bitmode(unsigned char bitmask, enum ftdi_mpsse_mode mode)
291 return ftdi_set_bitmode(d->ftdi, bitmask, mode);
294 int Context::read_pins(unsigned char *pins)
296 return ftdi_read_pins(d->ftdi, pins);
299 char* Context::error_string()
301 return ftdi_get_error_string(d->ftdi);
304 int Context::get_strings()
307 char vendor[512], desc[512], serial[512];
309 int ret = ftdi_usb_get_strings(d->ftdi, d->dev, vendor, 512, desc, 512, serial, 512);
315 d->description = desc;
321 int Context::get_strings_and_reopen()
323 // Get device strings (closes device)
324 int ret=get_strings();
332 ret = ftdi_usb_open_dev(d->ftdi, d->dev);
333 d->open = (ret >= 0);
338 /*! \brief Device strings properties.
340 const std::string& Context::vendor()
345 /*! \brief Device strings properties.
347 const std::string& Context::description()
349 return d->description;
352 /*! \brief Device strings properties.
354 const std::string& Context::serial()
359 void Context::set_context(struct ftdi_context* context)
365 void Context::set_usb_device(struct libusb_device *dev)
370 struct ftdi_context* Context::context()
375 class Eeprom::Private
382 struct ftdi_eeprom eeprom;
383 struct ftdi_context* context;
386 Eeprom::Eeprom(Context* parent)
387 : d ( new Private() )
389 d->context = parent->context();
396 void Eeprom::init_defaults()
398 return ftdi_eeprom_initdefaults(&d->eeprom);
401 void Eeprom::set_size(int size)
403 return ftdi_eeprom_setsize(d->context, &d->eeprom, size);
406 int Eeprom::size(unsigned char *eeprom, int maxsize)
408 return ftdi_read_eeprom_getsize(d->context, eeprom, maxsize);
411 int Eeprom::chip_id(unsigned int *chipid)
413 return ftdi_read_chipid(d->context, chipid);
416 int Eeprom::build(unsigned char *output)
418 return ftdi_eeprom_build(&d->eeprom, output);
421 int Eeprom::read(unsigned char *eeprom)
423 return ftdi_read_eeprom(d->context, eeprom);
426 int Eeprom::write(unsigned char *eeprom)
428 return ftdi_write_eeprom(d->context, eeprom);
431 int Eeprom::read_location(int eeprom_addr, unsigned short *eeprom_val)
433 return ftdi_read_eeprom_location(d->context, eeprom_addr, eeprom_val);
436 int Eeprom::write_location(int eeprom_addr, unsigned short eeprom_val)
438 return ftdi_write_eeprom_location(d->context, eeprom_addr, eeprom_val);
443 return ftdi_erase_eeprom(d->context);
449 Private(struct ftdi_device_list* _devlist)
456 ftdi_list_free(&devlist);
459 std::list<Context> list;
460 struct ftdi_device_list* devlist;
463 List::List(struct ftdi_device_list* devlist)
464 : d( new Private(devlist) )
469 for (; devlist != 0; devlist = devlist->next)
472 c.set_usb_device(devlist->dev);
474 d->list.push_back(c);
484 * Return begin iterator for accessing the contained list elements
487 List::iterator List::begin()
489 return d->list.begin();
493 * Return end iterator for accessing the contained list elements
496 List::iterator List::end()
498 return d->list.end();
502 * Return begin iterator for accessing the contained list elements
503 * @return Const iterator
505 List::const_iterator List::begin() const
507 return d->list.begin();
511 * Return end iterator for accessing the contained list elements
512 * @return Const iterator
514 List::const_iterator List::end() const
516 return d->list.end();
520 * Return begin reverse iterator for accessing the contained list elements
521 * @return Reverse iterator
523 List::reverse_iterator List::rbegin()
525 return d->list.rbegin();
529 * Return end reverse iterator for accessing the contained list elements
530 * @return Reverse iterator
532 List::reverse_iterator List::rend()
534 return d->list.rend();
538 * Return begin reverse iterator for accessing the contained list elements
539 * @return Const reverse iterator
541 List::const_reverse_iterator List::rbegin() const
543 return d->list.rbegin();
547 * Return end reverse iterator for accessing the contained list elements
548 * @return Const reverse iterator
550 List::const_reverse_iterator List::rend() const
552 return d->list.rend();
557 * Get number of elements stored in the list
558 * @return Number of elements
560 List::ListType::size_type List::size() const
562 return d->list.size();
566 * Check if list is empty
567 * @return True if empty, false otherwise
569 bool List::empty() const
571 return d->list.empty();
575 * Removes all elements. Invalidates all iterators.
576 * Do it in a non-throwing way and also make
577 * sure we really free the allocated memory.
581 ListType().swap(d->list);
586 ftdi_list_free(&d->devlist);
592 * Appends a copy of the element as the new last element.
593 * @param element Value to copy and append
595 void List::push_back(const Context& element)
597 d->list.push_back(element);
601 * Adds a copy of the element as the new first element.
602 * @param element Value to copy and add
604 void List::push_front(const Context& element)
606 d->list.push_front(element);
610 * Erase one element pointed by iterator
611 * @param pos Element to erase
612 * @return Position of the following element (or end())
614 List::iterator List::erase(iterator pos)
616 return d->list.erase(pos);
620 * Erase a range of elements
621 * @param beg Begin of range
622 * @param end End of range
623 * @return Position of the element after the erased range (or end())
625 List::iterator List::erase(iterator beg, iterator end)
627 return d->list.erase(beg, end);
630 List* List::find_all(int vendor, int product)
632 struct ftdi_device_list* dlist = 0;
633 struct ftdi_context ftdi;
635 ftdi_usb_find_all(&ftdi, &dlist, vendor, product);
637 return new List(dlist);