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