deprecated bitbang_enable in C++ wrapper too
[libftdi] / ftdipp / ftdi.cpp
CommitLineData
cdf448f6
TJ
1/***************************************************************************
2 ftdi.cpp - C++ wraper for libftdi
3 -------------------
4 begin : Mon Oct 13 2008
5 copyright : (C) 2008 by Marek Vavruša
6 email : opensource@intra2net.com and marek@vavrusa.com
7 ***************************************************************************/
3ab8f642
TJ
8/*
9Copyright (C) 2008 by Marek Vavruša
cdf448f6 10
3ab8f642
TJ
11The software in this package is distributed under the GNU General
12Public License version 2 (with a special exception described below).
13
14A copy of GNU General Public License (GPL) is included in this distribution,
15in the file COPYING.GPL.
16
17As a special exception, if other files instantiate templates or use macros
18or inline functions from this file, or you compile this file and link it
19with other works to produce a work based on this file, this file
20does not by itself cause the resulting work to be covered
21by the GNU General Public License.
22
23However the source code for this file must still be made available
24in accordance with section (3) of the GNU General Public License.
cdf448f6 25
3ab8f642
TJ
26This exception does not invalidate any other reasons why a work based
27on this file might be covered by the GNU General Public License.
28*/
20b1459a
TJ
29#include "ftdi.hpp"
30#include "ftdi.h"
31
32namespace Ftdi
33{
34
35class Context::Private
36{
cdf448f6
TJ
37public:
38 Private()
22d12cda 39 : ftdi(0), dev(0), open(false)
cdf448f6 40 {
cfceadbc
MV
41 ftdi = ftdi_new();
42 }
43
44 ~Private()
45 {
22d12cda 46 if (open)
cfceadbc
MV
47 ftdi_usb_close(ftdi);
48
49 ftdi_free(ftdi);
cdf448f6
TJ
50 }
51
52 bool open;
53
54 struct ftdi_context* ftdi;
55 struct usb_device* dev;
56
57 std::string vendor;
58 std::string description;
59 std::string serial;
20b1459a
TJ
60};
61
62/*! \brief Constructor.
63 */
64Context::Context()
cdf448f6 65 : d( new Private() )
20b1459a 66{
20b1459a
TJ
67}
68
69/*! \brief Destructor.
70 */
71Context::~Context()
72{
20b1459a
TJ
73}
74
75bool Context::is_open()
76{
cdf448f6 77 return d->open;
20b1459a
TJ
78}
79
80int Context::open(int vendor, int product, const std::string& description, const std::string& serial)
81{
cdf448f6
TJ
82 int ret = 0;
83
2f6b4bb6 84 // Open device
cdf448f6
TJ
85 if (description.empty() && serial.empty())
86 ret = ftdi_usb_open(d->ftdi, vendor, product);
87 else
88 ret = ftdi_usb_open_desc(d->ftdi, vendor, product, description.c_str(), serial.c_str());
20b1459a 89
2f6b4bb6
MV
90 if (ret < 0)
91 return ret;
20b1459a 92
2f6b4bb6
MV
93 // Get device strings (closes device)
94 get_strings();
95
96 // Reattach device
97 ret = ftdi_usb_open_dev(d->ftdi, d->dev);
98 d->open = (ret >= 0);
20b1459a 99
cdf448f6 100 return ret;
20b1459a
TJ
101}
102
103int Context::open(struct usb_device *dev)
104{
cdf448f6
TJ
105 if (dev != 0)
106 d->dev = dev;
107
108 if (d->dev == 0)
109 return -1;
20b1459a 110
2f6b4bb6
MV
111 // Get device strings (closes device)
112 get_strings();
113
114 // Reattach device
115 int ret = ftdi_usb_open_dev(d->ftdi, d->dev);
116 d->open = (ret >= 0);
20b1459a 117
cdf448f6 118 return ret;
20b1459a
TJ
119}
120
121int Context::close()
122{
cdf448f6
TJ
123 d->open = false;
124 return ftdi_usb_close(d->ftdi);
20b1459a
TJ
125}
126
127int Context::reset()
128{
cdf448f6 129 return ftdi_usb_reset(d->ftdi);
20b1459a
TJ
130}
131
132int Context::flush(int mask)
133{
cdf448f6 134 int ret = 1;
20b1459a 135
cdf448f6
TJ
136 if (mask & Input)
137 ret &= ftdi_usb_purge_rx_buffer(d->ftdi);
138 if (mask & Output)
139 ret &= ftdi_usb_purge_tx_buffer(d->ftdi);
140
141 return ret;
20b1459a
TJ
142}
143
144int Context::set_interface(enum ftdi_interface interface)
145{
cdf448f6 146 return ftdi_set_interface(d->ftdi, interface);
20b1459a
TJ
147}
148
149void Context::set_usb_device(struct usb_dev_handle *dev)
150{
cdf448f6
TJ
151 ftdi_set_usbdev(d->ftdi, dev);
152 d->dev = usb_device(dev);
20b1459a
TJ
153}
154
155int Context::set_baud_rate(int baudrate)
156{
cdf448f6 157 return ftdi_set_baudrate(d->ftdi, baudrate);
20b1459a
TJ
158}
159
160int Context::set_line_property(enum ftdi_bits_type bits, enum ftdi_stopbits_type sbit, enum ftdi_parity_type parity)
161{
cdf448f6 162 return ftdi_set_line_property(d->ftdi, bits, sbit, parity);
20b1459a
TJ
163}
164
165int 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)
166{
cdf448f6 167 return ftdi_set_line_property2(d->ftdi, bits, sbit, parity, break_type);
20b1459a
TJ
168}
169
170int Context::read(unsigned char *buf, int size)
171{
cdf448f6 172 return ftdi_read_data(d->ftdi, buf, size);
20b1459a
TJ
173}
174
175int Context::set_read_chunk_size(unsigned int chunksize)
176{
cdf448f6 177 return ftdi_read_data_set_chunksize(d->ftdi, chunksize);
20b1459a
TJ
178}
179
180int Context::read_chunk_size()
181{
cdf448f6
TJ
182 unsigned chunk = -1;
183 if (ftdi_read_data_get_chunksize(d->ftdi, &chunk) < 0)
184 return -1;
20b1459a 185
cdf448f6
TJ
186 return chunk;
187}
20b1459a
TJ
188
189int Context::write(unsigned char *buf, int size)
190{
cdf448f6 191 return ftdi_write_data(d->ftdi, buf, size);
20b1459a
TJ
192}
193
194int Context::set_write_chunk_size(unsigned int chunksize)
195{
cdf448f6 196 return ftdi_write_data_set_chunksize(d->ftdi, chunksize);
20b1459a
TJ
197}
198
199int Context::write_chunk_size()
200{
cdf448f6
TJ
201 unsigned chunk = -1;
202 if (ftdi_write_data_get_chunksize(d->ftdi, &chunk) < 0)
203 return -1;
20b1459a 204
cdf448f6 205 return chunk;
20b1459a
TJ
206}
207
208int Context::set_flow_control(int flowctrl)
209{
cdf448f6 210 return ftdi_setflowctrl(d->ftdi, flowctrl);
20b1459a
TJ
211}
212
213int Context::set_modem_control(int mask)
214{
cdf448f6
TJ
215 int dtr = 0, rts = 0;
216
217 if (mask & Dtr)
218 dtr = 1;
219 if (mask & Rts)
220 rts = 1;
20b1459a 221
cdf448f6 222 return ftdi_setdtr_rts(d->ftdi, dtr, rts);
20b1459a
TJ
223}
224
225int Context::set_dtr(bool state)
226{
cdf448f6 227 return ftdi_setdtr(d->ftdi, state);
20b1459a
TJ
228}
229
230int Context::set_rts(bool state)
231{
cdf448f6 232 return ftdi_setrts(d->ftdi, state);
20b1459a
TJ
233}
234
235int Context::set_latency(unsigned char latency)
236{
cdf448f6 237 return ftdi_set_latency_timer(d->ftdi, latency);
20b1459a
TJ
238}
239
240unsigned Context::latency()
241{
cdf448f6
TJ
242 unsigned char latency = 0;
243 ftdi_get_latency_timer(d->ftdi, &latency);
244 return latency;
20b1459a
TJ
245}
246
247unsigned short Context::poll_modem_status()
248{
cdf448f6
TJ
249 unsigned short status = 0;
250 ftdi_poll_modem_status(d->ftdi, &status);
251 return status;
20b1459a
TJ
252}
253
20b1459a
TJ
254int Context::set_event_char(unsigned char eventch, unsigned char enable)
255{
cdf448f6 256 return ftdi_set_event_char(d->ftdi, eventch, enable);
20b1459a
TJ
257}
258
259int Context::set_error_char(unsigned char errorch, unsigned char enable)
260{
cdf448f6 261 return ftdi_set_error_char(d->ftdi, errorch, enable);
20b1459a
TJ
262}
263
264int Context::bitbang_enable(unsigned char bitmask)
265{
cdf448f6 266 return ftdi_enable_bitbang(d->ftdi, bitmask);
20b1459a
TJ
267}
268
269int Context::bitbang_disable()
270{
cdf448f6 271 return ftdi_disable_bitbang(d->ftdi);
20b1459a
TJ
272}
273
274int Context::set_bitmode(unsigned char bitmask, unsigned char mode)
275{
cdf448f6 276 return ftdi_set_bitmode(d->ftdi, bitmask, mode);
20b1459a
TJ
277}
278
279int Context::read_pins(unsigned char *pins)
280{
cdf448f6 281 return ftdi_read_pins(d->ftdi, pins);
20b1459a
TJ
282}
283
284char* Context::error_string()
285{
cdf448f6 286 return ftdi_get_error_string(d->ftdi);
20b1459a
TJ
287}
288
289int Context::get_strings()
290{
cdf448f6
TJ
291 // Prepare buffers
292 char vendor[512], desc[512], serial[512];
293
294 int ret = ftdi_usb_get_strings(d->ftdi, d->dev, vendor, 512, desc, 512, serial, 512);
295
296 if (ret < 0)
297 return -1;
20b1459a 298
cdf448f6
TJ
299 d->vendor = vendor;
300 d->description = desc;
301 d->serial = serial;
20b1459a 302
cdf448f6 303 return 1;
20b1459a
TJ
304}
305
1bbaf1ce 306/*! \brief Device strings properties.
20b1459a
TJ
307 */
308const std::string& Context::vendor()
309{
cdf448f6 310 return d->vendor;
20b1459a
TJ
311}
312
1bbaf1ce
JP
313/*! \brief Device strings properties.
314 */
20b1459a
TJ
315const std::string& Context::description()
316{
cdf448f6 317 return d->description;
20b1459a
TJ
318}
319
1bbaf1ce
JP
320/*! \brief Device strings properties.
321 */
20b1459a
TJ
322const std::string& Context::serial()
323{
cdf448f6 324 return d->serial;
20b1459a
TJ
325}
326
327void Context::set_context(struct ftdi_context* context)
328{
cdf448f6
TJ
329 ftdi_free(d->ftdi);
330 d->ftdi = context;
20b1459a
TJ
331}
332
333void Context::set_usb_device(struct usb_device *dev)
334{
cdf448f6 335 d->dev = dev;
20b1459a
TJ
336}
337
338struct ftdi_context* Context::context()
339{
cdf448f6 340 return d->ftdi;
20b1459a
TJ
341}
342
343class Eeprom::Private
344{
cdf448f6
TJ
345public:
346 Private()
347 : context(0)
348 {}
20b1459a 349
cdf448f6
TJ
350 struct ftdi_eeprom eeprom;
351 struct ftdi_context* context;
20b1459a
TJ
352};
353
354Eeprom::Eeprom(Context* parent)
cdf448f6 355 : d ( new Private() )
20b1459a 356{
cdf448f6 357 d->context = parent->context();
20b1459a
TJ
358}
359
360Eeprom::~Eeprom()
361{
20b1459a
TJ
362}
363
364void Eeprom::init_defaults()
365{
cdf448f6 366 return ftdi_eeprom_initdefaults(&d->eeprom);
20b1459a
TJ
367}
368
369void Eeprom::set_size(int size)
370{
cdf448f6 371 return ftdi_eeprom_setsize(d->context, &d->eeprom, size);
20b1459a
TJ
372}
373
374int Eeprom::size(unsigned char *eeprom, int maxsize)
375{
cdf448f6 376 return ftdi_read_eeprom_getsize(d->context, eeprom, maxsize);
20b1459a
TJ
377}
378
379int Eeprom::chip_id(unsigned int *chipid)
380{
cdf448f6 381 return ftdi_read_chipid(d->context, chipid);
20b1459a
TJ
382}
383
384int Eeprom::build(unsigned char *output)
385{
cdf448f6 386 return ftdi_eeprom_build(&d->eeprom, output);
20b1459a
TJ
387}
388
389int Eeprom::read(unsigned char *eeprom)
390{
cdf448f6 391 return ftdi_read_eeprom(d->context, eeprom);
20b1459a
TJ
392}
393
394int Eeprom::write(unsigned char *eeprom)
395{
cdf448f6 396 return ftdi_write_eeprom(d->context, eeprom);
20b1459a
TJ
397}
398
449c87a9
TJ
399int Eeprom::read_location(int eeprom_addr, unsigned short *eeprom_val)
400{
401 return ftdi_read_eeprom_location(d->context, eeprom_addr, eeprom_val);
402}
403
404int Eeprom::write_location(int eeprom_addr, unsigned short eeprom_val)
405{
406 return ftdi_write_eeprom_location(d->context, eeprom_addr, eeprom_val);
407}
408
20b1459a
TJ
409int Eeprom::erase()
410{
cdf448f6 411 return ftdi_erase_eeprom(d->context);
20b1459a
TJ
412}
413
414class List::Private
415{
cdf448f6 416public:
6b22a054
MV
417 Private(struct ftdi_device_list* _devlist)
418 : devlist(_devlist)
cdf448f6 419 {}
20b1459a 420
cfceadbc
MV
421 ~Private()
422 {
6b22a054
MV
423 if(devlist)
424 ftdi_list_free(&devlist);
cfceadbc
MV
425 }
426
6b22a054
MV
427 std::list<Context> list;
428 struct ftdi_device_list* devlist;
20b1459a
TJ
429};
430
431List::List(struct ftdi_device_list* devlist)
6b22a054 432 : d( new Private(devlist) )
20b1459a 433{
cdf448f6
TJ
434 if (devlist != 0)
435 {
436 // Iterate list
6b22a054 437 for (; devlist != 0; devlist = devlist->next)
cdf448f6 438 {
cfceadbc 439 Context c;
6b22a054 440 c.set_usb_device(devlist->dev);
cfceadbc 441 c.get_strings();
6b22a054 442 d->list.push_back(c);
cdf448f6 443 }
cdf448f6 444 }
20b1459a
TJ
445}
446
447List::~List()
448{
20b1459a
TJ
449}
450
a14193ac
TJ
451/**
452* Return begin iterator for accessing the contained list elements
453* @return Iterator
454*/
455List::iterator List::begin()
6b22a054 456{
a14193ac 457 return d->list.begin();
6b22a054
MV
458}
459
a14193ac
TJ
460/**
461* Return end iterator for accessing the contained list elements
462* @return Iterator
463*/
464List::iterator List::end()
465{
466 return d->list.end();
467}
468
469/**
470* Return begin iterator for accessing the contained list elements
471* @return Const iterator
472*/
473List::const_iterator List::begin() const
6b22a054 474{
a14193ac 475 return d->list.begin();
6b22a054
MV
476}
477
a14193ac
TJ
478/**
479* Return end iterator for accessing the contained list elements
480* @return Const iterator
481*/
482List::const_iterator List::end() const
483{
484 return d->list.end();
485}
6b22a054 486
a14193ac
TJ
487/**
488* Return begin reverse iterator for accessing the contained list elements
489* @return Reverse iterator
490*/
491List::reverse_iterator List::rbegin()
6b22a054 492{
a14193ac 493 return d->list.rbegin();
6b22a054
MV
494}
495
a14193ac
TJ
496/**
497* Return end reverse iterator for accessing the contained list elements
498* @return Reverse iterator
499*/
500List::reverse_iterator List::rend()
501{
502 return d->list.rend();
503}
504
505/**
506* Return begin reverse iterator for accessing the contained list elements
507* @return Const reverse iterator
508*/
509List::const_reverse_iterator List::rbegin() const
510{
511 return d->list.rbegin();
512}
513
514/**
515* Return end reverse iterator for accessing the contained list elements
516* @return Const reverse iterator
517*/
518List::const_reverse_iterator List::rend() const
519{
520 return d->list.rend();
521
522}
523
524/**
525* Get number of elements stored in the list
526* @return Number of elements
527*/
528List::ListType::size_type List::size() const
529{
530 return d->list.size();
531}
532
533/**
534* Check if list is empty
535* @return True if empty, false otherwise
536*/
537bool List::empty() const
538{
539 return d->list.empty();
540}
541
542/**
543 * Removes all elements. Invalidates all iterators.
544 * Do it in a non-throwing way and also make
545 * sure we really free the allocated memory.
546 */
6b22a054
MV
547void List::clear()
548{
a14193ac 549 ListType().swap(d->list);
6b22a054
MV
550
551 // Free device list
a14193ac
TJ
552 if (d->devlist)
553 {
554 ftdi_list_free(&d->devlist);
555 d->devlist = 0;
556 }
6b22a054
MV
557}
558
a14193ac
TJ
559/**
560 * Appends a copy of the element as the new last element.
561 * @param element Value to copy and append
562*/
563void List::push_back(const Context& element)
6b22a054 564{
a14193ac 565 d->list.push_back(element);
6b22a054
MV
566}
567
a14193ac
TJ
568/**
569 * Adds a copy of the element as the new first element.
570 * @param element Value to copy and add
571*/
572void List::push_front(const Context& element)
6b22a054 573{
a14193ac 574 d->list.push_front(element);
6b22a054
MV
575}
576
a14193ac
TJ
577/**
578 * Erase one element pointed by iterator
579 * @param pos Element to erase
580 * @return Position of the following element (or end())
581*/
582List::iterator List::erase(iterator pos)
583{
584 return d->list.erase(pos);
585}
586
587/**
588 * Erase a range of elements
589 * @param beg Begin of range
590 * @param end End of range
591 * @return Position of the element after the erased range (or end())
592*/
593List::iterator List::erase(iterator beg, iterator end)
594{
595 return d->list.erase(beg, end);
596}
6b22a054 597
20b1459a
TJ
598List* List::find_all(int vendor, int product)
599{
cdf448f6
TJ
600 struct ftdi_device_list* dlist = 0;
601 struct ftdi_context ftdi;
602 ftdi_init(&ftdi);
603 ftdi_usb_find_all(&ftdi, &dlist, vendor, product);
604 ftdi_deinit(&ftdi);
605 return new List(dlist);
20b1459a
TJ
606}
607
608}