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