Don't #include <libusb.h> from ftdi.h
[libftdi] / ftdipp / ftdi.cpp
... / ...
CommitLineData
1/***************************************************************************
2 ftdi.cpp - C++ wraper for libftdi
3 -------------------
4 begin : Mon Oct 13 2008
5 copyright : (C) 2008-2013 by Marek Vavruša / libftdi developers
6 email : opensource@intra2net.com and marek@vavrusa.com
7 ***************************************************************************/
8/*
9Copyright (C) 2008-2013 by Marek Vavruša / libftdi developers
10
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.
25
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*/
29#include <libusb.h>
30#include "ftdi.hpp"
31#include "ftdi_i.h"
32#include "ftdi.h"
33
34namespace Ftdi
35{
36
37class Context::Private
38{
39public:
40 Private()
41 : open(false), ftdi(0), dev(0)
42 {
43 ftdi = ftdi_new();
44 }
45
46 ~Private()
47 {
48 if (open)
49 ftdi_usb_close(ftdi);
50
51 ftdi_free(ftdi);
52 }
53
54 bool open;
55
56 struct ftdi_context* ftdi;
57 struct libusb_device* dev;
58
59 std::string vendor;
60 std::string description;
61 std::string serial;
62};
63
64/*! \brief Constructor.
65 */
66Context::Context()
67 : d( new Private() )
68{
69}
70
71/*! \brief Destructor.
72 */
73Context::~Context()
74{
75}
76
77bool Context::is_open()
78{
79 return d->open;
80}
81
82int Context::open(int vendor, int product)
83{
84 // Open device
85 int ret = ftdi_usb_open(d->ftdi, vendor, product);
86
87 if (ret < 0)
88 return ret;
89
90 return get_strings_and_reopen();
91}
92
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();
103
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();
120}
121
122int Context::open(struct libusb_device *dev)
123{
124 if (dev != 0)
125 d->dev = dev;
126
127 if (d->dev == 0)
128 return -1;
129
130 return get_strings_and_reopen();
131}
132
133int Context::close()
134{
135 d->open = false;
136 d->dev = 0;
137 return ftdi_usb_close(d->ftdi);
138}
139
140int Context::reset()
141{
142 return ftdi_usb_reset(d->ftdi);
143}
144
145int Context::flush(int mask)
146{
147 int ret = 1;
148
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;
155}
156
157int Context::set_interface(enum ftdi_interface interface)
158{
159 return ftdi_set_interface(d->ftdi, interface);
160}
161
162void Context::set_usb_device(struct libusb_device_handle *dev)
163{
164 ftdi_set_usbdev(d->ftdi, dev);
165 d->dev = libusb_get_device(dev);
166}
167
168int Context::set_baud_rate(int baudrate)
169{
170 return ftdi_set_baudrate(d->ftdi, baudrate);
171}
172
173int Context::set_line_property(enum ftdi_bits_type bits, enum ftdi_stopbits_type sbit, enum ftdi_parity_type parity)
174{
175 return ftdi_set_line_property(d->ftdi, bits, sbit, parity);
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{
180 return ftdi_set_line_property2(d->ftdi, bits, sbit, parity, break_type);
181}
182
183int Context::read(unsigned char *buf, int size)
184{
185 return ftdi_read_data(d->ftdi, buf, size);
186}
187
188int Context::set_read_chunk_size(unsigned int chunksize)
189{
190 return ftdi_read_data_set_chunksize(d->ftdi, chunksize);
191}
192
193int Context::read_chunk_size()
194{
195 unsigned chunk = -1;
196 if (ftdi_read_data_get_chunksize(d->ftdi, &chunk) < 0)
197 return -1;
198
199 return chunk;
200}
201
202int Context::write(unsigned char *buf, int size)
203{
204 return ftdi_write_data(d->ftdi, buf, size);
205}
206
207int Context::set_write_chunk_size(unsigned int chunksize)
208{
209 return ftdi_write_data_set_chunksize(d->ftdi, chunksize);
210}
211
212int Context::write_chunk_size()
213{
214 unsigned chunk = -1;
215 if (ftdi_write_data_get_chunksize(d->ftdi, &chunk) < 0)
216 return -1;
217
218 return chunk;
219}
220
221int Context::set_flow_control(int flowctrl)
222{
223 return ftdi_setflowctrl(d->ftdi, flowctrl);
224}
225
226int Context::set_modem_control(int mask)
227{
228 int dtr = 0, rts = 0;
229
230 if (mask & Dtr)
231 dtr = 1;
232 if (mask & Rts)
233 rts = 1;
234
235 return ftdi_setdtr_rts(d->ftdi, dtr, rts);
236}
237
238int Context::set_dtr(bool state)
239{
240 return ftdi_setdtr(d->ftdi, state);
241}
242
243int Context::set_rts(bool state)
244{
245 return ftdi_setrts(d->ftdi, state);
246}
247
248int Context::set_latency(unsigned char latency)
249{
250 return ftdi_set_latency_timer(d->ftdi, latency);
251}
252
253unsigned Context::latency()
254{
255 unsigned char latency = 0;
256 ftdi_get_latency_timer(d->ftdi, &latency);
257 return latency;
258}
259
260unsigned short Context::poll_modem_status()
261{
262 unsigned short status = 0;
263 ftdi_poll_modem_status(d->ftdi, &status);
264 return status;
265}
266
267int Context::set_event_char(unsigned char eventch, unsigned char enable)
268{
269 return ftdi_set_event_char(d->ftdi, eventch, enable);
270}
271
272int Context::set_error_char(unsigned char errorch, unsigned char enable)
273{
274 return ftdi_set_error_char(d->ftdi, errorch, enable);
275}
276
277int Context::set_bitmode(unsigned char bitmask, unsigned char mode)
278{
279 return ftdi_set_bitmode(d->ftdi, bitmask, mode);
280}
281
282int Context::set_bitmode(unsigned char bitmask, enum ftdi_mpsse_mode mode)
283{
284 return ftdi_set_bitmode(d->ftdi, bitmask, mode);
285}
286
287int Context::bitbang_disable()
288{
289 return ftdi_disable_bitbang(d->ftdi);
290}
291
292int Context::read_pins(unsigned char *pins)
293{
294 return ftdi_read_pins(d->ftdi, pins);
295}
296
297char* Context::error_string()
298{
299 return ftdi_get_error_string(d->ftdi);
300}
301
302int Context::get_strings()
303{
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;
311
312 d->vendor = vendor;
313 d->description = desc;
314 d->serial = serial;
315
316 return 1;
317}
318
319int Context::get_strings_and_reopen()
320{
321 if ( d->dev == 0 )
322 {
323 d->dev = libusb_get_device(d->ftdi->usb_dev);
324 }
325
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
341/*! \brief Device strings properties.
342 */
343const std::string& Context::vendor()
344{
345 return d->vendor;
346}
347
348/*! \brief Device strings properties.
349 */
350const std::string& Context::description()
351{
352 return d->description;
353}
354
355/*! \brief Device strings properties.
356 */
357const std::string& Context::serial()
358{
359 return d->serial;
360}
361
362void Context::set_context(struct ftdi_context* context)
363{
364 ftdi_free(d->ftdi);
365 d->ftdi = context;
366}
367
368void Context::set_usb_device(struct libusb_device *dev)
369{
370 d->dev = dev;
371}
372
373struct ftdi_context* Context::context()
374{
375 return d->ftdi;
376}
377
378class Eeprom::Private
379{
380public:
381 Private()
382 : context(0)
383 {}
384
385 struct ftdi_eeprom eeprom;
386 struct ftdi_context* context;
387};
388
389Eeprom::Eeprom(Context* parent)
390 : d ( new Private() )
391{
392 d->context = parent->context();
393}
394
395Eeprom::~Eeprom()
396{
397}
398
399int Eeprom::init_defaults(char* manufacturer, char *product, char * serial)
400{
401 return ftdi_eeprom_initdefaults(d->context, manufacturer, product, serial);
402}
403
404int Eeprom::chip_id(unsigned int *chipid)
405{
406 return ftdi_read_chipid(d->context, chipid);
407}
408
409int Eeprom::build(unsigned char *output)
410{
411 return ftdi_eeprom_build(d->context);
412}
413
414int Eeprom::read(unsigned char *eeprom)
415{
416 return ftdi_read_eeprom(d->context);
417}
418
419int Eeprom::write(unsigned char *eeprom)
420{
421 return ftdi_write_eeprom(d->context);
422}
423
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
434int Eeprom::erase()
435{
436 return ftdi_erase_eeprom(d->context);
437}
438
439class List::Private
440{
441public:
442 Private(struct ftdi_device_list* _devlist)
443 : devlist(_devlist)
444 {}
445
446 ~Private()
447 {
448 if(devlist)
449 ftdi_list_free(&devlist);
450 }
451
452 std::list<Context> list;
453 struct ftdi_device_list* devlist;
454};
455
456List::List(struct ftdi_device_list* devlist)
457 : d( new Private(devlist) )
458{
459 if (devlist != 0)
460 {
461 // Iterate list
462 for (; devlist != 0; devlist = devlist->next)
463 {
464 Context c;
465 c.set_usb_device(devlist->dev);
466 c.get_strings();
467 d->list.push_back(c);
468 }
469 }
470}
471
472List::~List()
473{
474}
475
476/**
477* Return begin iterator for accessing the contained list elements
478* @return Iterator
479*/
480List::iterator List::begin()
481{
482 return d->list.begin();
483}
484
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
499{
500 return d->list.begin();
501}
502
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}
511
512/**
513* Return begin reverse iterator for accessing the contained list elements
514* @return Reverse iterator
515*/
516List::reverse_iterator List::rbegin()
517{
518 return d->list.rbegin();
519}
520
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 */
572void List::clear()
573{
574 ListType().swap(d->list);
575
576 // Free device list
577 if (d->devlist)
578 {
579 ftdi_list_free(&d->devlist);
580 d->devlist = 0;
581 }
582}
583
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)
589{
590 d->list.push_back(element);
591}
592
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)
598{
599 d->list.push_front(element);
600}
601
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}
622
623List* List::find_all(Context &context, int vendor, int product)
624{
625 struct ftdi_device_list* dlist = 0;
626 ftdi_usb_find_all(context.context(), &dlist, vendor, product);
627 return new List(dlist);
628}
629
630}