libftdi: Fix doxygen errors
[libftdi] / ftdipp / ftdi.cpp
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 /*
9 Copyright (C) 2008 by Marek Vavruša
10
11 The software in this package is distributed under the GNU General
12 Public License version 2 (with a special exception described below).
13
14 A copy of GNU General Public License (GPL) is included in this distribution,
15 in the file COPYING.GPL.
16
17 As a special exception, if other files instantiate templates or use macros
18 or inline functions from this file, or you compile this file and link it
19 with other works to produce a work based on this file, this file
20 does not by itself cause the resulting work to be covered
21 by the GNU General Public License.
22
23 However the source code for this file must still be made available
24 in accordance with section (3) of the GNU General Public License.
25
26 This exception does not invalidate any other reasons why a work based
27 on this file might be covered by the GNU General Public License.
28 */
29 #include "ftdi.hpp"
30 #include "ftdi.h"
31
32 namespace Ftdi
33 {
34
35 class Context::Private
36 {
37 public:
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 usb_device*   dev;
56
57     std::string vendor;
58     std::string description;
59     std::string serial;
60 };
61
62 /*! \brief Constructor.
63  */
64 Context::Context()
65         : d( new Private() )
66 {
67 }
68
69 /*! \brief Destructor.
70  */
71 Context::~Context()
72 {
73 }
74
75 bool Context::is_open()
76 {
77     return d->open;
78 }
79
80 int Context::open(int vendor, int product, const std::string& description, const std::string& serial)
81 {
82     int ret = 0;
83
84     // Open device
85     if (description.empty() && serial.empty())
86         ret = ftdi_usb_open(d->ftdi, vendor, product);
87     else
88         ret = ftdi_usb_open_desc(d->ftdi, vendor, product, description.c_str(), serial.c_str());
89
90     if (ret < 0)
91        return ret;
92
93     // Get device strings (closes device)
94     get_strings();
95
96     // Reattach device
97     ret = ftdi_usb_open_dev(d->ftdi, d->dev);
98     d->open = (ret >= 0);
99
100     return ret;
101 }
102
103 int Context::open(struct usb_device *dev)
104 {
105     if (dev != 0)
106         d->dev = dev;
107
108     if (d->dev == 0)
109         return -1;
110
111     // Get device strings (closes device)
112     get_strings();
113
114     // Reattach device
115     int ret = ftdi_usb_open_dev(d->ftdi, d->dev);
116     d->open = (ret >= 0);
117
118     return ret;
119 }
120
121 int Context::close()
122 {
123     d->open = false;
124     return ftdi_usb_close(d->ftdi);
125 }
126
127 int Context::reset()
128 {
129     return ftdi_usb_reset(d->ftdi);
130 }
131
132 int Context::flush(int mask)
133 {
134     int ret = 1;
135
136     if (mask & Input)
137         ret &= ftdi_usb_purge_rx_buffer(d->ftdi);
138     if (mask & Output)
139         ret &= ftdi_usb_purge_tx_buffer(d->ftdi);
140
141     return ret;
142 }
143
144 int Context::set_interface(enum ftdi_interface interface)
145 {
146     return ftdi_set_interface(d->ftdi, interface);
147 }
148
149 void Context::set_usb_device(struct usb_dev_handle *dev)
150 {
151     ftdi_set_usbdev(d->ftdi, dev);
152     d->dev = usb_device(dev);
153 }
154
155 int Context::set_baud_rate(int baudrate)
156 {
157     return ftdi_set_baudrate(d->ftdi, baudrate);
158 }
159
160 int Context::set_line_property(enum ftdi_bits_type bits, enum ftdi_stopbits_type sbit, enum ftdi_parity_type parity)
161 {
162     return ftdi_set_line_property(d->ftdi, bits, sbit, parity);
163 }
164
165 int 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)
166 {
167     return ftdi_set_line_property2(d->ftdi, bits, sbit, parity, break_type);
168 }
169
170 int Context::read(unsigned char *buf, int size)
171 {
172     return ftdi_read_data(d->ftdi, buf, size);
173 }
174
175 int Context::set_read_chunk_size(unsigned int chunksize)
176 {
177     return ftdi_read_data_set_chunksize(d->ftdi, chunksize);
178 }
179
180 int Context::read_chunk_size()
181 {
182     unsigned chunk = -1;
183     if (ftdi_read_data_get_chunksize(d->ftdi, &chunk) < 0)
184         return -1;
185
186     return chunk;
187 }
188
189 int Context::write(unsigned char *buf, int size)
190 {
191     return ftdi_write_data(d->ftdi, buf, size);
192 }
193
194 int Context::set_write_chunk_size(unsigned int chunksize)
195 {
196     return ftdi_write_data_set_chunksize(d->ftdi, chunksize);
197 }
198
199 int Context::write_chunk_size()
200 {
201     unsigned chunk = -1;
202     if (ftdi_write_data_get_chunksize(d->ftdi, &chunk) < 0)
203         return -1;
204
205     return chunk;
206 }
207
208 int Context::set_flow_control(int flowctrl)
209 {
210     return ftdi_setflowctrl(d->ftdi, flowctrl);
211 }
212
213 int Context::set_modem_control(int mask)
214 {
215     int dtr = 0, rts = 0;
216
217     if (mask & Dtr)
218         dtr = 1;
219     if (mask & Rts)
220         rts = 1;
221
222     return ftdi_setdtr_rts(d->ftdi, dtr, rts);
223 }
224
225 int Context::set_dtr(bool state)
226 {
227     return ftdi_setdtr(d->ftdi, state);
228 }
229
230 int Context::set_rts(bool state)
231 {
232     return ftdi_setrts(d->ftdi, state);
233 }
234
235 int Context::set_latency(unsigned char latency)
236 {
237     return ftdi_set_latency_timer(d->ftdi, latency);
238 }
239
240 unsigned Context::latency()
241 {
242     unsigned char latency = 0;
243     ftdi_get_latency_timer(d->ftdi, &latency);
244     return latency;
245 }
246
247 unsigned short Context::poll_modem_status()
248 {
249     unsigned short status = 0;
250     ftdi_poll_modem_status(d->ftdi, &status);
251     return status;
252 }
253
254 int Context::set_event_char(unsigned char eventch, unsigned char enable)
255 {
256     return ftdi_set_event_char(d->ftdi, eventch, enable);
257 }
258
259 int Context::set_error_char(unsigned char errorch, unsigned char enable)
260 {
261     return ftdi_set_error_char(d->ftdi, errorch, enable);
262 }
263
264 int Context::bitbang_enable(unsigned char bitmask)
265 {
266     return ftdi_enable_bitbang(d->ftdi, bitmask);
267 }
268
269 int Context::bitbang_disable()
270 {
271     return ftdi_disable_bitbang(d->ftdi);
272 }
273
274 int Context::set_bitmode(unsigned char bitmask, unsigned char mode)
275 {
276     return ftdi_set_bitmode(d->ftdi, bitmask, mode);
277 }
278
279 int Context::read_pins(unsigned char *pins)
280 {
281     return ftdi_read_pins(d->ftdi, pins);
282 }
283
284 char* Context::error_string()
285 {
286     return ftdi_get_error_string(d->ftdi);
287 }
288
289 int Context::get_strings()
290 {
291     // Prepare buffers
292     char vendor[512], desc[512], serial[512];
293
294     int ret = ftdi_usb_get_strings(d->ftdi, d->dev, vendor, 512, desc, 512, serial, 512);
295
296     if (ret < 0)
297         return -1;
298
299     d->vendor = vendor;
300     d->description = desc;
301     d->serial = serial;
302
303     return 1;
304 }
305
306 /*! \brief Device strings properties.
307  */
308 const std::string& Context::vendor()
309 {
310     return d->vendor;
311 }
312
313 /*! \brief Device strings properties.
314  */
315 const std::string& Context::description()
316 {
317     return d->description;
318 }
319
320 /*! \brief Device strings properties.
321  */
322 const std::string& Context::serial()
323 {
324     return d->serial;
325 }
326
327 void Context::set_context(struct ftdi_context* context)
328 {
329     ftdi_free(d->ftdi);
330     d->ftdi = context;
331 }
332
333 void Context::set_usb_device(struct usb_device *dev)
334 {
335     d->dev = dev;
336 }
337
338 struct ftdi_context* Context::context()
339 {
340     return d->ftdi;
341 }
342
343 class Eeprom::Private
344 {
345 public:
346     Private()
347             : context(0)
348     {}
349
350     struct ftdi_eeprom eeprom;
351     struct ftdi_context* context;
352 };
353
354 Eeprom::Eeprom(Context* parent)
355         : d ( new Private() )
356 {
357     d->context = parent->context();
358 }
359
360 Eeprom::~Eeprom()
361 {
362 }
363
364 void Eeprom::init_defaults()
365 {
366     return ftdi_eeprom_initdefaults(&d->eeprom);
367 }
368
369 void Eeprom::set_size(int size)
370 {
371     return ftdi_eeprom_setsize(d->context, &d->eeprom, size);
372 }
373
374 int Eeprom::size(unsigned char *eeprom, int maxsize)
375 {
376     return ftdi_read_eeprom_getsize(d->context, eeprom, maxsize);
377 }
378
379 int Eeprom::chip_id(unsigned int *chipid)
380 {
381     return ftdi_read_chipid(d->context, chipid);
382 }
383
384 int Eeprom::build(unsigned char *output)
385 {
386     return ftdi_eeprom_build(&d->eeprom, output);
387 }
388
389 int Eeprom::read(unsigned char *eeprom)
390 {
391     return ftdi_read_eeprom(d->context, eeprom);
392 }
393
394 int Eeprom::write(unsigned char *eeprom)
395 {
396     return ftdi_write_eeprom(d->context, eeprom);
397 }
398
399 int Eeprom::erase()
400 {
401     return ftdi_erase_eeprom(d->context);
402 }
403
404 class List::Private
405 {
406 public:
407     Private(struct ftdi_device_list* _devlist)
408             : devlist(_devlist)
409     {}
410
411     ~Private()
412     {
413         if(devlist)
414             ftdi_list_free(&devlist);
415     }
416
417     std::list<Context> list;
418     struct ftdi_device_list* devlist;
419 };
420
421 List::List(struct ftdi_device_list* devlist)
422         : d( new Private(devlist) )
423 {
424     if (devlist != 0)
425     {
426         // Iterate list
427         for (; devlist != 0; devlist = devlist->next)
428         {
429             Context c;
430             c.set_usb_device(devlist->dev);
431             c.get_strings();
432             d->list.push_back(c);
433         }
434     }
435 }
436
437 List::~List()
438 {
439 }
440
441 /**
442 * Return begin iterator for accessing the contained list elements
443 * @return Iterator
444 */
445 List::iterator List::begin()
446 {
447     return d->list.begin();
448 }
449
450 /**
451 * Return end iterator for accessing the contained list elements
452 * @return Iterator
453 */
454 List::iterator List::end()
455 {
456     return d->list.end();
457 }
458
459 /**
460 * Return begin iterator for accessing the contained list elements
461 * @return Const iterator
462 */
463 List::const_iterator List::begin() const
464 {
465     return d->list.begin();
466 }
467
468 /**
469 * Return end iterator for accessing the contained list elements
470 * @return Const iterator
471 */
472 List::const_iterator List::end() const
473 {
474     return d->list.end();
475 }
476
477 /**
478 * Return begin reverse iterator for accessing the contained list elements
479 * @return Reverse iterator
480 */
481 List::reverse_iterator List::rbegin()
482 {
483     return d->list.rbegin();
484 }
485
486 /**
487 * Return end reverse iterator for accessing the contained list elements
488 * @return Reverse iterator
489 */
490 List::reverse_iterator List::rend()
491 {
492     return d->list.rend();
493 }
494
495 /**
496 * Return begin reverse iterator for accessing the contained list elements
497 * @return Const reverse iterator
498 */
499 List::const_reverse_iterator List::rbegin() const
500 {
501     return d->list.rbegin();
502 }
503
504 /**
505 * Return end reverse iterator for accessing the contained list elements
506 * @return Const reverse iterator
507 */
508 List::const_reverse_iterator List::rend() const
509 {
510     return d->list.rend();
511
512 }
513
514 /**
515 * Get number of elements stored in the list
516 * @return Number of elements
517 */
518 List::ListType::size_type List::size() const
519 {
520     return d->list.size();
521 }
522
523 /**
524 * Check if list is empty
525 * @return True if empty, false otherwise
526 */
527 bool List::empty() const
528 {
529     return d->list.empty();
530 }
531
532 /**
533  * Removes all elements. Invalidates all iterators.
534  * Do it in a non-throwing way and also make
535  * sure we really free the allocated memory.
536  */
537 void List::clear()
538 {
539     ListType().swap(d->list);
540
541     // Free device list
542     if (d->devlist)
543     {
544         ftdi_list_free(&d->devlist);
545         d->devlist = 0;
546     }
547 }
548
549 /**
550  * Appends a copy of the element as the new last element.
551  * @param element Value to copy and append
552 */
553 void List::push_back(const Context& element)
554 {
555     d->list.push_back(element);
556 }
557
558 /**
559  * Adds a copy of the element as the new first element.
560  * @param element Value to copy and add
561 */
562 void List::push_front(const Context& element)
563 {
564     d->list.push_front(element);
565 }
566
567 /**
568  * Erase one element pointed by iterator
569  * @param pos Element to erase
570  * @return Position of the following element (or end())
571 */
572 List::iterator List::erase(iterator pos)
573 {
574     return d->list.erase(pos);
575 }
576
577 /**
578  * Erase a range of elements
579  * @param beg Begin of range
580  * @param end End of range
581  * @return Position of the element after the erased range (or end())
582 */
583 List::iterator List::erase(iterator beg, iterator end)
584 {
585     return d->list.erase(beg, end);
586 }
587
588 List* List::find_all(int vendor, int product)
589 {
590     struct ftdi_device_list* dlist = 0;
591     struct ftdi_context ftdi;
592     ftdi_init(&ftdi);
593     ftdi_usb_find_all(&ftdi, &dlist, vendor, product);
594     ftdi_deinit(&ftdi);
595     return new List(dlist);
596 }
597
598 }