Remove duplicated udev rule.
[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
20b1459a
TJ
275int Context::set_bitmode(unsigned char bitmask, unsigned char mode)
276{
c2ed8c4e 277 return ftdi_set_bitmode(d->ftdi, bitmask, mode);
58cce2d4
GE
278}
279
280int Context::set_bitmode(unsigned char bitmask, enum ftdi_mpsse_mode mode)
281{
cdf448f6 282 return ftdi_set_bitmode(d->ftdi, bitmask, mode);
20b1459a
TJ
283}
284
2d790e37
TJ
285int Context::bitbang_disable()
286{
287 return ftdi_disable_bitbang(d->ftdi);
288}
289
20b1459a
TJ
290int Context::read_pins(unsigned char *pins)
291{
cdf448f6 292 return ftdi_read_pins(d->ftdi, pins);
20b1459a
TJ
293}
294
295char* Context::error_string()
296{
cdf448f6 297 return ftdi_get_error_string(d->ftdi);
20b1459a
TJ
298}
299
300int Context::get_strings()
301{
cdf448f6
TJ
302 // Prepare buffers
303 char vendor[512], desc[512], serial[512];
304
305 int ret = ftdi_usb_get_strings(d->ftdi, d->dev, vendor, 512, desc, 512, serial, 512);
306
307 if (ret < 0)
308 return -1;
20b1459a 309
cdf448f6
TJ
310 d->vendor = vendor;
311 d->description = desc;
312 d->serial = serial;
20b1459a 313
cdf448f6 314 return 1;
20b1459a
TJ
315}
316
58cce2d4
GE
317int Context::get_strings_and_reopen()
318{
319 // Get device strings (closes device)
320 int ret=get_strings();
321 if (ret < 0)
322 {
323 d->open = 0;
324 return ret;
325 }
326
327 // Reattach device
328 ret = ftdi_usb_open_dev(d->ftdi, d->dev);
329 d->open = (ret >= 0);
330
331 return ret;
332}
333
1bbaf1ce 334/*! \brief Device strings properties.
20b1459a
TJ
335 */
336const std::string& Context::vendor()
337{
cdf448f6 338 return d->vendor;
20b1459a
TJ
339}
340
1bbaf1ce
JP
341/*! \brief Device strings properties.
342 */
20b1459a
TJ
343const std::string& Context::description()
344{
cdf448f6 345 return d->description;
20b1459a
TJ
346}
347
1bbaf1ce
JP
348/*! \brief Device strings properties.
349 */
20b1459a
TJ
350const std::string& Context::serial()
351{
cdf448f6 352 return d->serial;
20b1459a
TJ
353}
354
355void Context::set_context(struct ftdi_context* context)
356{
cdf448f6
TJ
357 ftdi_free(d->ftdi);
358 d->ftdi = context;
20b1459a
TJ
359}
360
579b006f 361void Context::set_usb_device(struct libusb_device *dev)
20b1459a 362{
cdf448f6 363 d->dev = dev;
20b1459a
TJ
364}
365
366struct ftdi_context* Context::context()
367{
cdf448f6 368 return d->ftdi;
20b1459a
TJ
369}
370
371class Eeprom::Private
372{
cdf448f6
TJ
373public:
374 Private()
375 : context(0)
376 {}
20b1459a 377
cdf448f6
TJ
378 struct ftdi_eeprom eeprom;
379 struct ftdi_context* context;
20b1459a
TJ
380};
381
382Eeprom::Eeprom(Context* parent)
cdf448f6 383 : d ( new Private() )
20b1459a 384{
cdf448f6 385 d->context = parent->context();
20b1459a
TJ
386}
387
388Eeprom::~Eeprom()
389{
20b1459a
TJ
390}
391
f14f84d3 392int Eeprom::init_defaults(char* manufacturer, char *product, char * serial)
20b1459a 393{
74e8e79d 394 return ftdi_eeprom_initdefaults(d->context, manufacturer, product, serial);
20b1459a
TJ
395}
396
20b1459a
TJ
397int Eeprom::chip_id(unsigned int *chipid)
398{
cdf448f6 399 return ftdi_read_chipid(d->context, chipid);
20b1459a
TJ
400}
401
402int Eeprom::build(unsigned char *output)
403{
a35aa9bd 404 return ftdi_eeprom_build(d->context);
20b1459a
TJ
405}
406
407int Eeprom::read(unsigned char *eeprom)
408{
a35aa9bd 409 return ftdi_read_eeprom(d->context);
20b1459a
TJ
410}
411
412int Eeprom::write(unsigned char *eeprom)
413{
a35aa9bd 414 return ftdi_write_eeprom(d->context);
20b1459a
TJ
415}
416
449c87a9
TJ
417int Eeprom::read_location(int eeprom_addr, unsigned short *eeprom_val)
418{
419 return ftdi_read_eeprom_location(d->context, eeprom_addr, eeprom_val);
420}
421
422int Eeprom::write_location(int eeprom_addr, unsigned short eeprom_val)
423{
424 return ftdi_write_eeprom_location(d->context, eeprom_addr, eeprom_val);
425}
426
20b1459a
TJ
427int Eeprom::erase()
428{
cdf448f6 429 return ftdi_erase_eeprom(d->context);
20b1459a
TJ
430}
431
432class List::Private
433{
cdf448f6 434public:
6b22a054
MV
435 Private(struct ftdi_device_list* _devlist)
436 : devlist(_devlist)
cdf448f6 437 {}
20b1459a 438
cfceadbc
MV
439 ~Private()
440 {
6b22a054
MV
441 if(devlist)
442 ftdi_list_free(&devlist);
cfceadbc
MV
443 }
444
6b22a054
MV
445 std::list<Context> list;
446 struct ftdi_device_list* devlist;
20b1459a
TJ
447};
448
449List::List(struct ftdi_device_list* devlist)
6b22a054 450 : d( new Private(devlist) )
20b1459a 451{
cdf448f6
TJ
452 if (devlist != 0)
453 {
454 // Iterate list
6b22a054 455 for (; devlist != 0; devlist = devlist->next)
cdf448f6 456 {
cfceadbc 457 Context c;
6b22a054 458 c.set_usb_device(devlist->dev);
cfceadbc 459 c.get_strings();
6b22a054 460 d->list.push_back(c);
cdf448f6 461 }
cdf448f6 462 }
20b1459a
TJ
463}
464
465List::~List()
466{
20b1459a
TJ
467}
468
a14193ac
TJ
469/**
470* Return begin iterator for accessing the contained list elements
471* @return Iterator
472*/
473List::iterator List::begin()
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 Iterator
481*/
482List::iterator List::end()
483{
484 return d->list.end();
485}
486
487/**
488* Return begin iterator for accessing the contained list elements
489* @return Const iterator
490*/
491List::const_iterator List::begin() const
6b22a054 492{
a14193ac 493 return d->list.begin();
6b22a054
MV
494}
495
a14193ac
TJ
496/**
497* Return end iterator for accessing the contained list elements
498* @return Const iterator
499*/
500List::const_iterator List::end() const
501{
502 return d->list.end();
503}
6b22a054 504
a14193ac
TJ
505/**
506* Return begin reverse iterator for accessing the contained list elements
507* @return Reverse iterator
508*/
509List::reverse_iterator List::rbegin()
6b22a054 510{
a14193ac 511 return d->list.rbegin();
6b22a054
MV
512}
513
a14193ac
TJ
514/**
515* Return end reverse iterator for accessing the contained list elements
516* @return Reverse iterator
517*/
518List::reverse_iterator List::rend()
519{
520 return d->list.rend();
521}
522
523/**
524* Return begin reverse iterator for accessing the contained list elements
525* @return Const reverse iterator
526*/
527List::const_reverse_iterator List::rbegin() const
528{
529 return d->list.rbegin();
530}
531
532/**
533* Return end reverse iterator for accessing the contained list elements
534* @return Const reverse iterator
535*/
536List::const_reverse_iterator List::rend() const
537{
538 return d->list.rend();
539
540}
541
542/**
543* Get number of elements stored in the list
544* @return Number of elements
545*/
546List::ListType::size_type List::size() const
547{
548 return d->list.size();
549}
550
551/**
552* Check if list is empty
553* @return True if empty, false otherwise
554*/
555bool List::empty() const
556{
557 return d->list.empty();
558}
559
560/**
561 * Removes all elements. Invalidates all iterators.
562 * Do it in a non-throwing way and also make
563 * sure we really free the allocated memory.
564 */
6b22a054
MV
565void List::clear()
566{
a14193ac 567 ListType().swap(d->list);
6b22a054
MV
568
569 // Free device list
a14193ac
TJ
570 if (d->devlist)
571 {
572 ftdi_list_free(&d->devlist);
573 d->devlist = 0;
574 }
6b22a054
MV
575}
576
a14193ac
TJ
577/**
578 * Appends a copy of the element as the new last element.
579 * @param element Value to copy and append
580*/
581void List::push_back(const Context& element)
6b22a054 582{
a14193ac 583 d->list.push_back(element);
6b22a054
MV
584}
585
a14193ac
TJ
586/**
587 * Adds a copy of the element as the new first element.
588 * @param element Value to copy and add
589*/
590void List::push_front(const Context& element)
6b22a054 591{
a14193ac 592 d->list.push_front(element);
6b22a054
MV
593}
594
a14193ac
TJ
595/**
596 * Erase one element pointed by iterator
597 * @param pos Element to erase
598 * @return Position of the following element (or end())
599*/
600List::iterator List::erase(iterator pos)
601{
602 return d->list.erase(pos);
603}
604
605/**
606 * Erase a range of elements
607 * @param beg Begin of range
608 * @param end End of range
609 * @return Position of the element after the erased range (or end())
610*/
611List::iterator List::erase(iterator beg, iterator end)
612{
613 return d->list.erase(beg, end);
614}
6b22a054 615
20b1459a
TJ
616List* List::find_all(int vendor, int product)
617{
cdf448f6
TJ
618 struct ftdi_device_list* dlist = 0;
619 struct ftdi_context ftdi;
620 ftdi_init(&ftdi);
621 ftdi_usb_find_all(&ftdi, &dlist, vendor, product);
622 ftdi_deinit(&ftdi);
623 return new List(dlist);
20b1459a
TJ
624}
625
626}