List having non-virtual destructor fixed (thanks to Thomas Jarosch) Proposed subset...
[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;
55 struct usb_device* dev;
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
80int Context::open(int vendor, int product, const std::string& description, const std::string& serial)
81{
cdf448f6
TJ
82 int ret = 0;
83
84 if (description.empty() && serial.empty())
85 ret = ftdi_usb_open(d->ftdi, vendor, product);
86 else
87 ret = ftdi_usb_open_desc(d->ftdi, vendor, product, description.c_str(), serial.c_str());
20b1459a 88
cdf448f6 89 d->dev = usb_device(d->ftdi->usb_dev);
20b1459a 90
cdf448f6
TJ
91 if ((ret = ftdi_usb_open_dev(d->ftdi, d->dev)) >= 0)
92 {
93 d->open = true;
94 get_strings();
95 }
20b1459a 96
cdf448f6 97 return ret;
20b1459a
TJ
98}
99
100int Context::open(struct usb_device *dev)
101{
cdf448f6
TJ
102 int ret = 0;
103
104 if (dev != 0)
105 d->dev = dev;
106
107 if (d->dev == 0)
108 return -1;
20b1459a 109
cdf448f6
TJ
110 if ((ret = ftdi_usb_open_dev(d->ftdi, d->dev)) >= 0)
111 {
112 d->open = true;
113 get_strings();
114 }
20b1459a 115
cdf448f6 116 return ret;
20b1459a
TJ
117}
118
119int Context::close()
120{
cdf448f6
TJ
121 d->open = false;
122 return ftdi_usb_close(d->ftdi);
20b1459a
TJ
123}
124
125int Context::reset()
126{
cdf448f6 127 return ftdi_usb_reset(d->ftdi);
20b1459a
TJ
128}
129
130int Context::flush(int mask)
131{
cdf448f6 132 int ret = 1;
20b1459a 133
cdf448f6
TJ
134 if (mask & Input)
135 ret &= ftdi_usb_purge_rx_buffer(d->ftdi);
136 if (mask & Output)
137 ret &= ftdi_usb_purge_tx_buffer(d->ftdi);
138
139 return ret;
20b1459a
TJ
140}
141
142int Context::set_interface(enum ftdi_interface interface)
143{
cdf448f6 144 return ftdi_set_interface(d->ftdi, interface);
20b1459a
TJ
145}
146
147void Context::set_usb_device(struct usb_dev_handle *dev)
148{
cdf448f6
TJ
149 ftdi_set_usbdev(d->ftdi, dev);
150 d->dev = usb_device(dev);
20b1459a
TJ
151}
152
153int Context::set_baud_rate(int baudrate)
154{
cdf448f6 155 return ftdi_set_baudrate(d->ftdi, baudrate);
20b1459a
TJ
156}
157
158int Context::set_line_property(enum ftdi_bits_type bits, enum ftdi_stopbits_type sbit, enum ftdi_parity_type parity)
159{
cdf448f6 160 return ftdi_set_line_property(d->ftdi, bits, sbit, parity);
20b1459a
TJ
161}
162
163int 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)
164{
cdf448f6 165 return ftdi_set_line_property2(d->ftdi, bits, sbit, parity, break_type);
20b1459a
TJ
166}
167
168int Context::read(unsigned char *buf, int size)
169{
cdf448f6 170 return ftdi_read_data(d->ftdi, buf, size);
20b1459a
TJ
171}
172
173int Context::set_read_chunk_size(unsigned int chunksize)
174{
cdf448f6 175 return ftdi_read_data_set_chunksize(d->ftdi, chunksize);
20b1459a
TJ
176}
177
178int Context::read_chunk_size()
179{
cdf448f6
TJ
180 unsigned chunk = -1;
181 if (ftdi_read_data_get_chunksize(d->ftdi, &chunk) < 0)
182 return -1;
20b1459a 183
cdf448f6
TJ
184 return chunk;
185}
20b1459a
TJ
186
187int Context::write(unsigned char *buf, int size)
188{
cdf448f6 189 return ftdi_write_data(d->ftdi, buf, size);
20b1459a
TJ
190}
191
192int Context::set_write_chunk_size(unsigned int chunksize)
193{
cdf448f6 194 return ftdi_write_data_set_chunksize(d->ftdi, chunksize);
20b1459a
TJ
195}
196
197int Context::write_chunk_size()
198{
cdf448f6
TJ
199 unsigned chunk = -1;
200 if (ftdi_write_data_get_chunksize(d->ftdi, &chunk) < 0)
201 return -1;
20b1459a 202
cdf448f6 203 return chunk;
20b1459a
TJ
204}
205
206int Context::set_flow_control(int flowctrl)
207{
cdf448f6 208 return ftdi_setflowctrl(d->ftdi, flowctrl);
20b1459a
TJ
209}
210
211int Context::set_modem_control(int mask)
212{
cdf448f6
TJ
213 int dtr = 0, rts = 0;
214
215 if (mask & Dtr)
216 dtr = 1;
217 if (mask & Rts)
218 rts = 1;
20b1459a 219
cdf448f6 220 return ftdi_setdtr_rts(d->ftdi, dtr, rts);
20b1459a
TJ
221}
222
223int Context::set_dtr(bool state)
224{
cdf448f6 225 return ftdi_setdtr(d->ftdi, state);
20b1459a
TJ
226}
227
228int Context::set_rts(bool state)
229{
cdf448f6 230 return ftdi_setrts(d->ftdi, state);
20b1459a
TJ
231}
232
233int Context::set_latency(unsigned char latency)
234{
cdf448f6 235 return ftdi_set_latency_timer(d->ftdi, latency);
20b1459a
TJ
236}
237
238unsigned Context::latency()
239{
cdf448f6
TJ
240 unsigned char latency = 0;
241 ftdi_get_latency_timer(d->ftdi, &latency);
242 return latency;
20b1459a
TJ
243}
244
245unsigned short Context::poll_modem_status()
246{
cdf448f6
TJ
247 unsigned short status = 0;
248 ftdi_poll_modem_status(d->ftdi, &status);
249 return status;
20b1459a
TJ
250}
251
20b1459a
TJ
252int Context::set_event_char(unsigned char eventch, unsigned char enable)
253{
cdf448f6 254 return ftdi_set_event_char(d->ftdi, eventch, enable);
20b1459a
TJ
255}
256
257int Context::set_error_char(unsigned char errorch, unsigned char enable)
258{
cdf448f6 259 return ftdi_set_error_char(d->ftdi, errorch, enable);
20b1459a
TJ
260}
261
262int Context::bitbang_enable(unsigned char bitmask)
263{
cdf448f6 264 return ftdi_enable_bitbang(d->ftdi, bitmask);
20b1459a
TJ
265}
266
267int Context::bitbang_disable()
268{
cdf448f6 269 return ftdi_disable_bitbang(d->ftdi);
20b1459a
TJ
270}
271
272int Context::set_bitmode(unsigned char bitmask, unsigned char mode)
273{
cdf448f6 274 return ftdi_set_bitmode(d->ftdi, bitmask, mode);
20b1459a
TJ
275}
276
277int Context::read_pins(unsigned char *pins)
278{
cdf448f6 279 return ftdi_read_pins(d->ftdi, pins);
20b1459a
TJ
280}
281
282char* Context::error_string()
283{
cdf448f6 284 return ftdi_get_error_string(d->ftdi);
20b1459a
TJ
285}
286
287int Context::get_strings()
288{
cdf448f6
TJ
289 // Prepare buffers
290 char vendor[512], desc[512], serial[512];
291
292 int ret = ftdi_usb_get_strings(d->ftdi, d->dev, vendor, 512, desc, 512, serial, 512);
293
294 if (ret < 0)
295 return -1;
20b1459a 296
cdf448f6
TJ
297 d->vendor = vendor;
298 d->description = desc;
299 d->serial = serial;
20b1459a 300
cdf448f6 301 return 1;
20b1459a
TJ
302}
303
304/*! \fn vendor
305 * \fn description
306 * \fn serial
307 * \brief Device strings properties.
308 */
309const std::string& Context::vendor()
310{
cdf448f6 311 return d->vendor;
20b1459a
TJ
312}
313
314const std::string& Context::description()
315{
cdf448f6 316 return d->description;
20b1459a
TJ
317}
318
319const std::string& Context::serial()
320{
cdf448f6 321 return d->serial;
20b1459a
TJ
322}
323
324void Context::set_context(struct ftdi_context* context)
325{
cdf448f6
TJ
326 ftdi_free(d->ftdi);
327 d->ftdi = context;
20b1459a
TJ
328}
329
330void Context::set_usb_device(struct usb_device *dev)
331{
cdf448f6 332 d->dev = dev;
20b1459a
TJ
333}
334
335struct ftdi_context* Context::context()
336{
cdf448f6 337 return d->ftdi;
20b1459a
TJ
338}
339
340class Eeprom::Private
341{
cdf448f6
TJ
342public:
343 Private()
344 : context(0)
345 {}
20b1459a 346
cdf448f6
TJ
347 struct ftdi_eeprom eeprom;
348 struct ftdi_context* context;
20b1459a
TJ
349};
350
351Eeprom::Eeprom(Context* parent)
cdf448f6 352 : d ( new Private() )
20b1459a 353{
cdf448f6 354 d->context = parent->context();
20b1459a
TJ
355}
356
357Eeprom::~Eeprom()
358{
20b1459a
TJ
359}
360
361void Eeprom::init_defaults()
362{
cdf448f6 363 return ftdi_eeprom_initdefaults(&d->eeprom);
20b1459a
TJ
364}
365
366void Eeprom::set_size(int size)
367{
cdf448f6 368 return ftdi_eeprom_setsize(d->context, &d->eeprom, size);
20b1459a
TJ
369}
370
371int Eeprom::size(unsigned char *eeprom, int maxsize)
372{
cdf448f6 373 return ftdi_read_eeprom_getsize(d->context, eeprom, maxsize);
20b1459a
TJ
374}
375
376int Eeprom::chip_id(unsigned int *chipid)
377{
cdf448f6 378 return ftdi_read_chipid(d->context, chipid);
20b1459a
TJ
379}
380
381int Eeprom::build(unsigned char *output)
382{
cdf448f6 383 return ftdi_eeprom_build(&d->eeprom, output);
20b1459a
TJ
384}
385
386int Eeprom::read(unsigned char *eeprom)
387{
cdf448f6 388 return ftdi_read_eeprom(d->context, eeprom);
20b1459a
TJ
389}
390
391int Eeprom::write(unsigned char *eeprom)
392{
cdf448f6 393 return ftdi_write_eeprom(d->context, eeprom);
20b1459a
TJ
394}
395
396int Eeprom::erase()
397{
cdf448f6 398 return ftdi_erase_eeprom(d->context);
20b1459a
TJ
399}
400
401class List::Private
402{
cdf448f6 403public:
6b22a054
MV
404 Private(struct ftdi_device_list* _devlist)
405 : devlist(_devlist)
cdf448f6 406 {}
20b1459a 407
cfceadbc
MV
408 ~Private()
409 {
6b22a054
MV
410 if(devlist)
411 ftdi_list_free(&devlist);
cfceadbc
MV
412 }
413
6b22a054
MV
414 std::list<Context> list;
415 struct ftdi_device_list* devlist;
20b1459a
TJ
416};
417
418List::List(struct ftdi_device_list* devlist)
6b22a054 419 : d( new Private(devlist) )
20b1459a 420{
cdf448f6
TJ
421 if (devlist != 0)
422 {
423 // Iterate list
6b22a054 424 for (; devlist != 0; devlist = devlist->next)
cdf448f6 425 {
cfceadbc 426 Context c;
6b22a054 427 c.set_usb_device(devlist->dev);
cfceadbc 428 c.get_strings();
6b22a054 429 d->list.push_back(c);
cdf448f6 430 }
cdf448f6 431 }
20b1459a
TJ
432}
433
434List::~List()
435{
20b1459a
TJ
436}
437
6b22a054
MV
438int List::size()
439{
440 return d->list.size();
441}
442
443void List::push_front(const Context& element)
444{
445 d->list.push_front(element);
446}
447
448
449void List::push_back(const Context& element)
450{
451 d->list.push_back(element);
452}
453
454void List::clear()
455{
456 d->list.clear();
457
458 // Free device list
459 ftdi_list_free(&d->devlist);
460 d->devlist = 0;
461}
462
463std::list<Context>::iterator List::begin()
464{
465 return d->list.begin();
466}
467
468std::list<Context>::iterator List::end()
469{
470 return d->list.end();
471}
472
473
20b1459a
TJ
474List* List::find_all(int vendor, int product)
475{
cdf448f6
TJ
476 struct ftdi_device_list* dlist = 0;
477 struct ftdi_context ftdi;
478 ftdi_init(&ftdi);
479 ftdi_usb_find_all(&ftdi, &dlist, vendor, product);
480 ftdi_deinit(&ftdi);
481 return new List(dlist);
20b1459a
TJ
482}
483
484}