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