Initial import of using libusb-1.0.
[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;
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{
58cce2d4
GE
286 return set_bitmode(bitmask, mode);
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{
cdf448f6 398 return ftdi_eeprom_initdefaults(&d->eeprom);
20b1459a
TJ
399}
400
401void Eeprom::set_size(int size)
402{
cdf448f6 403 return ftdi_eeprom_setsize(d->context, &d->eeprom, size);
20b1459a
TJ
404}
405
406int Eeprom::size(unsigned char *eeprom, int maxsize)
407{
cdf448f6 408 return ftdi_read_eeprom_getsize(d->context, eeprom, maxsize);
20b1459a
TJ
409}
410
411int Eeprom::chip_id(unsigned int *chipid)
412{
cdf448f6 413 return ftdi_read_chipid(d->context, chipid);
20b1459a
TJ
414}
415
416int Eeprom::build(unsigned char *output)
417{
cdf448f6 418 return ftdi_eeprom_build(&d->eeprom, output);
20b1459a
TJ
419}
420
421int Eeprom::read(unsigned char *eeprom)
422{
cdf448f6 423 return ftdi_read_eeprom(d->context, eeprom);
20b1459a
TJ
424}
425
426int Eeprom::write(unsigned char *eeprom)
427{
cdf448f6 428 return ftdi_write_eeprom(d->context, eeprom);
20b1459a
TJ
429}
430
449c87a9
TJ
431int Eeprom::read_location(int eeprom_addr, unsigned short *eeprom_val)
432{
433 return ftdi_read_eeprom_location(d->context, eeprom_addr, eeprom_val);
434}
435
436int Eeprom::write_location(int eeprom_addr, unsigned short eeprom_val)
437{
438 return ftdi_write_eeprom_location(d->context, eeprom_addr, eeprom_val);
439}
440
20b1459a
TJ
441int Eeprom::erase()
442{
cdf448f6 443 return ftdi_erase_eeprom(d->context);
20b1459a
TJ
444}
445
446class List::Private
447{
cdf448f6 448public:
6b22a054
MV
449 Private(struct ftdi_device_list* _devlist)
450 : devlist(_devlist)
cdf448f6 451 {}
20b1459a 452
cfceadbc
MV
453 ~Private()
454 {
6b22a054
MV
455 if(devlist)
456 ftdi_list_free(&devlist);
cfceadbc
MV
457 }
458
6b22a054
MV
459 std::list<Context> list;
460 struct ftdi_device_list* devlist;
20b1459a
TJ
461};
462
463List::List(struct ftdi_device_list* devlist)
6b22a054 464 : d( new Private(devlist) )
20b1459a 465{
cdf448f6
TJ
466 if (devlist != 0)
467 {
468 // Iterate list
6b22a054 469 for (; devlist != 0; devlist = devlist->next)
cdf448f6 470 {
cfceadbc 471 Context c;
6b22a054 472 c.set_usb_device(devlist->dev);
cfceadbc 473 c.get_strings();
6b22a054 474 d->list.push_back(c);
cdf448f6 475 }
cdf448f6 476 }
20b1459a
TJ
477}
478
479List::~List()
480{
20b1459a
TJ
481}
482
a14193ac
TJ
483/**
484* Return begin iterator for accessing the contained list elements
485* @return Iterator
486*/
487List::iterator List::begin()
6b22a054 488{
a14193ac 489 return d->list.begin();
6b22a054
MV
490}
491
a14193ac
TJ
492/**
493* Return end iterator for accessing the contained list elements
494* @return Iterator
495*/
496List::iterator List::end()
497{
498 return d->list.end();
499}
500
501/**
502* Return begin iterator for accessing the contained list elements
503* @return Const iterator
504*/
505List::const_iterator List::begin() const
6b22a054 506{
a14193ac 507 return d->list.begin();
6b22a054
MV
508}
509
a14193ac
TJ
510/**
511* Return end iterator for accessing the contained list elements
512* @return Const iterator
513*/
514List::const_iterator List::end() const
515{
516 return d->list.end();
517}
6b22a054 518
a14193ac
TJ
519/**
520* Return begin reverse iterator for accessing the contained list elements
521* @return Reverse iterator
522*/
523List::reverse_iterator List::rbegin()
6b22a054 524{
a14193ac 525 return d->list.rbegin();
6b22a054
MV
526}
527
a14193ac
TJ
528/**
529* Return end reverse iterator for accessing the contained list elements
530* @return Reverse iterator
531*/
532List::reverse_iterator List::rend()
533{
534 return d->list.rend();
535}
536
537/**
538* Return begin reverse iterator for accessing the contained list elements
539* @return Const reverse iterator
540*/
541List::const_reverse_iterator List::rbegin() const
542{
543 return d->list.rbegin();
544}
545
546/**
547* Return end reverse iterator for accessing the contained list elements
548* @return Const reverse iterator
549*/
550List::const_reverse_iterator List::rend() const
551{
552 return d->list.rend();
553
554}
555
556/**
557* Get number of elements stored in the list
558* @return Number of elements
559*/
560List::ListType::size_type List::size() const
561{
562 return d->list.size();
563}
564
565/**
566* Check if list is empty
567* @return True if empty, false otherwise
568*/
569bool List::empty() const
570{
571 return d->list.empty();
572}
573
574/**
575 * Removes all elements. Invalidates all iterators.
576 * Do it in a non-throwing way and also make
577 * sure we really free the allocated memory.
578 */
6b22a054
MV
579void List::clear()
580{
a14193ac 581 ListType().swap(d->list);
6b22a054
MV
582
583 // Free device list
a14193ac
TJ
584 if (d->devlist)
585 {
586 ftdi_list_free(&d->devlist);
587 d->devlist = 0;
588 }
6b22a054
MV
589}
590
a14193ac
TJ
591/**
592 * Appends a copy of the element as the new last element.
593 * @param element Value to copy and append
594*/
595void List::push_back(const Context& element)
6b22a054 596{
a14193ac 597 d->list.push_back(element);
6b22a054
MV
598}
599
a14193ac
TJ
600/**
601 * Adds a copy of the element as the new first element.
602 * @param element Value to copy and add
603*/
604void List::push_front(const Context& element)
6b22a054 605{
a14193ac 606 d->list.push_front(element);
6b22a054
MV
607}
608
a14193ac
TJ
609/**
610 * Erase one element pointed by iterator
611 * @param pos Element to erase
612 * @return Position of the following element (or end())
613*/
614List::iterator List::erase(iterator pos)
615{
616 return d->list.erase(pos);
617}
618
619/**
620 * Erase a range of elements
621 * @param beg Begin of range
622 * @param end End of range
623 * @return Position of the element after the erased range (or end())
624*/
625List::iterator List::erase(iterator beg, iterator end)
626{
627 return d->list.erase(beg, end);
628}
6b22a054 629
20b1459a
TJ
630List* List::find_all(int vendor, int product)
631{
cdf448f6
TJ
632 struct ftdi_device_list* dlist = 0;
633 struct ftdi_context ftdi;
634 ftdi_init(&ftdi);
635 ftdi_usb_find_all(&ftdi, &dlist, vendor, product);
636 ftdi_deinit(&ftdi);
637 return new List(dlist);
20b1459a
TJ
638}
639
640}