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