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