SWIG wrapper: Mark ftdi_version_info.version_str and .snapshot_str read only
[libftdi] / ftdipp / ftdi.cpp
... / ...
CommitLineData
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 ***************************************************************************/
8/*
9Copyright (C) 2008 by Marek Vavruša
10
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.
25
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*/
29#include "ftdi.hpp"
30#include "ftdi_i.h"
31#include "ftdi.h"
32
33namespace Ftdi
34{
35
36class Context::Private
37{
38public:
39 Private()
40 : open(false), ftdi(0), dev(0)
41 {
42 ftdi = ftdi_new();
43 }
44
45 ~Private()
46 {
47 if (open)
48 ftdi_usb_close(ftdi);
49
50 ftdi_free(ftdi);
51 }
52
53 bool open;
54
55 struct ftdi_context* ftdi;
56 struct libusb_device* dev;
57
58 std::string vendor;
59 std::string description;
60 std::string serial;
61};
62
63/*! \brief Constructor.
64 */
65Context::Context()
66 : d( new Private() )
67{
68}
69
70/*! \brief Destructor.
71 */
72Context::~Context()
73{
74}
75
76bool Context::is_open()
77{
78 return d->open;
79}
80
81int Context::open(int vendor, int product)
82{
83 // Open device
84 int ret = ftdi_usb_open(d->ftdi, vendor, product);
85
86 if (ret < 0)
87 return ret;
88
89 return get_strings_and_reopen();
90}
91
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();
102
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();
119}
120
121int Context::open(struct libusb_device *dev)
122{
123 if (dev != 0)
124 d->dev = dev;
125
126 if (d->dev == 0)
127 return -1;
128
129 return get_strings_and_reopen();
130}
131
132int Context::close()
133{
134 d->open = false;
135 return ftdi_usb_close(d->ftdi);
136}
137
138int Context::reset()
139{
140 return ftdi_usb_reset(d->ftdi);
141}
142
143int Context::flush(int mask)
144{
145 int ret = 1;
146
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;
153}
154
155int Context::set_interface(enum ftdi_interface interface)
156{
157 return ftdi_set_interface(d->ftdi, interface);
158}
159
160void Context::set_usb_device(struct libusb_device_handle *dev)
161{
162 ftdi_set_usbdev(d->ftdi, dev);
163 d->dev = libusb_get_device(dev);
164}
165
166int Context::set_baud_rate(int baudrate)
167{
168 return ftdi_set_baudrate(d->ftdi, baudrate);
169}
170
171int Context::set_line_property(enum ftdi_bits_type bits, enum ftdi_stopbits_type sbit, enum ftdi_parity_type parity)
172{
173 return ftdi_set_line_property(d->ftdi, bits, sbit, parity);
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{
178 return ftdi_set_line_property2(d->ftdi, bits, sbit, parity, break_type);
179}
180
181int Context::read(unsigned char *buf, int size)
182{
183 return ftdi_read_data(d->ftdi, buf, size);
184}
185
186int Context::set_read_chunk_size(unsigned int chunksize)
187{
188 return ftdi_read_data_set_chunksize(d->ftdi, chunksize);
189}
190
191int Context::read_chunk_size()
192{
193 unsigned chunk = -1;
194 if (ftdi_read_data_get_chunksize(d->ftdi, &chunk) < 0)
195 return -1;
196
197 return chunk;
198}
199
200int Context::write(unsigned char *buf, int size)
201{
202 return ftdi_write_data(d->ftdi, buf, size);
203}
204
205int Context::set_write_chunk_size(unsigned int chunksize)
206{
207 return ftdi_write_data_set_chunksize(d->ftdi, chunksize);
208}
209
210int Context::write_chunk_size()
211{
212 unsigned chunk = -1;
213 if (ftdi_write_data_get_chunksize(d->ftdi, &chunk) < 0)
214 return -1;
215
216 return chunk;
217}
218
219int Context::set_flow_control(int flowctrl)
220{
221 return ftdi_setflowctrl(d->ftdi, flowctrl);
222}
223
224int Context::set_modem_control(int mask)
225{
226 int dtr = 0, rts = 0;
227
228 if (mask & Dtr)
229 dtr = 1;
230 if (mask & Rts)
231 rts = 1;
232
233 return ftdi_setdtr_rts(d->ftdi, dtr, rts);
234}
235
236int Context::set_dtr(bool state)
237{
238 return ftdi_setdtr(d->ftdi, state);
239}
240
241int Context::set_rts(bool state)
242{
243 return ftdi_setrts(d->ftdi, state);
244}
245
246int Context::set_latency(unsigned char latency)
247{
248 return ftdi_set_latency_timer(d->ftdi, latency);
249}
250
251unsigned Context::latency()
252{
253 unsigned char latency = 0;
254 ftdi_get_latency_timer(d->ftdi, &latency);
255 return latency;
256}
257
258unsigned short Context::poll_modem_status()
259{
260 unsigned short status = 0;
261 ftdi_poll_modem_status(d->ftdi, &status);
262 return status;
263}
264
265int Context::set_event_char(unsigned char eventch, unsigned char enable)
266{
267 return ftdi_set_event_char(d->ftdi, eventch, enable);
268}
269
270int Context::set_error_char(unsigned char errorch, unsigned char enable)
271{
272 return ftdi_set_error_char(d->ftdi, errorch, enable);
273}
274
275int Context::bitbang_enable(unsigned char bitmask)
276{
277 return ftdi_set_bitmode(d->ftdi, bitmask, BITMODE_BITBANG);
278}
279
280int Context::bitbang_disable()
281{
282 return ftdi_disable_bitbang(d->ftdi);
283}
284
285int Context::set_bitmode(unsigned char bitmask, unsigned char mode)
286{
287 return ftdi_set_bitmode(d->ftdi, bitmask, mode);
288}
289
290int Context::set_bitmode(unsigned char bitmask, enum ftdi_mpsse_mode mode)
291{
292 return ftdi_set_bitmode(d->ftdi, bitmask, mode);
293}
294
295int Context::read_pins(unsigned char *pins)
296{
297 return ftdi_read_pins(d->ftdi, pins);
298}
299
300char* Context::error_string()
301{
302 return ftdi_get_error_string(d->ftdi);
303}
304
305int Context::get_strings()
306{
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;
314
315 d->vendor = vendor;
316 d->description = desc;
317 d->serial = serial;
318
319 return 1;
320}
321
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
339/*! \brief Device strings properties.
340 */
341const std::string& Context::vendor()
342{
343 return d->vendor;
344}
345
346/*! \brief Device strings properties.
347 */
348const std::string& Context::description()
349{
350 return d->description;
351}
352
353/*! \brief Device strings properties.
354 */
355const std::string& Context::serial()
356{
357 return d->serial;
358}
359
360void Context::set_context(struct ftdi_context* context)
361{
362 ftdi_free(d->ftdi);
363 d->ftdi = context;
364}
365
366void Context::set_usb_device(struct libusb_device *dev)
367{
368 d->dev = dev;
369}
370
371struct ftdi_context* Context::context()
372{
373 return d->ftdi;
374}
375
376class Eeprom::Private
377{
378public:
379 Private()
380 : context(0)
381 {}
382
383 struct ftdi_eeprom eeprom;
384 struct ftdi_context* context;
385};
386
387Eeprom::Eeprom(Context* parent)
388 : d ( new Private() )
389{
390 d->context = parent->context();
391}
392
393Eeprom::~Eeprom()
394{
395}
396
397int Eeprom::init_defaults(char* manufacturer, char *product, char * serial)
398{
399 return ftdi_eeprom_initdefaults(d->context, manufacturer, product, serial);
400}
401
402int Eeprom::chip_id(unsigned int *chipid)
403{
404 return ftdi_read_chipid(d->context, chipid);
405}
406
407int Eeprom::build(unsigned char *output)
408{
409 return ftdi_eeprom_build(d->context);
410}
411
412int Eeprom::read(unsigned char *eeprom)
413{
414 return ftdi_read_eeprom(d->context);
415}
416
417int Eeprom::write(unsigned char *eeprom)
418{
419 return ftdi_write_eeprom(d->context);
420}
421
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
432int Eeprom::erase()
433{
434 return ftdi_erase_eeprom(d->context);
435}
436
437class List::Private
438{
439public:
440 Private(struct ftdi_device_list* _devlist)
441 : devlist(_devlist)
442 {}
443
444 ~Private()
445 {
446 if(devlist)
447 ftdi_list_free(&devlist);
448 }
449
450 std::list<Context> list;
451 struct ftdi_device_list* devlist;
452};
453
454List::List(struct ftdi_device_list* devlist)
455 : d( new Private(devlist) )
456{
457 if (devlist != 0)
458 {
459 // Iterate list
460 for (; devlist != 0; devlist = devlist->next)
461 {
462 Context c;
463 c.set_usb_device(devlist->dev);
464 c.get_strings();
465 d->list.push_back(c);
466 }
467 }
468}
469
470List::~List()
471{
472}
473
474/**
475* Return begin iterator for accessing the contained list elements
476* @return Iterator
477*/
478List::iterator List::begin()
479{
480 return d->list.begin();
481}
482
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
497{
498 return d->list.begin();
499}
500
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}
509
510/**
511* Return begin reverse iterator for accessing the contained list elements
512* @return Reverse iterator
513*/
514List::reverse_iterator List::rbegin()
515{
516 return d->list.rbegin();
517}
518
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 */
570void List::clear()
571{
572 ListType().swap(d->list);
573
574 // Free device list
575 if (d->devlist)
576 {
577 ftdi_list_free(&d->devlist);
578 d->devlist = 0;
579 }
580}
581
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)
587{
588 d->list.push_back(element);
589}
590
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)
596{
597 d->list.push_front(element);
598}
599
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}
620
621List* List::find_all(int vendor, int product)
622{
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);
629}
630
631}