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