Remove ftdi_eeprom_getsize also from the CPP 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             : open(false), ftdi(0), dev(0)
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  */
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)
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
91 int 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
110 int 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
120 int 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
131 int Context::close()
132 {
133     d->open = false;
134     return ftdi_usb_close(d->ftdi);
135 }
136
137 int Context::reset()
138 {
139     return ftdi_usb_reset(d->ftdi);
140 }
141
142 int 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
154 int Context::set_interface(enum ftdi_interface interface)
155 {
156     return ftdi_set_interface(d->ftdi, interface);
157 }
158
159 void 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
165 int Context::set_baud_rate(int baudrate)
166 {
167     return ftdi_set_baudrate(d->ftdi, baudrate);
168 }
169
170 int 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
175 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)
176 {
177     return ftdi_set_line_property2(d->ftdi, bits, sbit, parity, break_type);
178 }
179
180 int Context::read(unsigned char *buf, int size)
181 {
182     return ftdi_read_data(d->ftdi, buf, size);
183 }
184
185 int Context::set_read_chunk_size(unsigned int chunksize)
186 {
187     return ftdi_read_data_set_chunksize(d->ftdi, chunksize);
188 }
189
190 int 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
199 int Context::write(unsigned char *buf, int size)
200 {
201     return ftdi_write_data(d->ftdi, buf, size);
202 }
203
204 int Context::set_write_chunk_size(unsigned int chunksize)
205 {
206     return ftdi_write_data_set_chunksize(d->ftdi, chunksize);
207 }
208
209 int 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
218 int Context::set_flow_control(int flowctrl)
219 {
220     return ftdi_setflowctrl(d->ftdi, flowctrl);
221 }
222
223 int 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
235 int Context::set_dtr(bool state)
236 {
237     return ftdi_setdtr(d->ftdi, state);
238 }
239
240 int Context::set_rts(bool state)
241 {
242     return ftdi_setrts(d->ftdi, state);
243 }
244
245 int Context::set_latency(unsigned char latency)
246 {
247     return ftdi_set_latency_timer(d->ftdi, latency);
248 }
249
250 unsigned Context::latency()
251 {
252     unsigned char latency = 0;
253     ftdi_get_latency_timer(d->ftdi, &latency);
254     return latency;
255 }
256
257 unsigned short Context::poll_modem_status()
258 {
259     unsigned short status = 0;
260     ftdi_poll_modem_status(d->ftdi, &status);
261     return status;
262 }
263
264 int Context::set_event_char(unsigned char eventch, unsigned char enable)
265 {
266     return ftdi_set_event_char(d->ftdi, eventch, enable);
267 }
268
269 int Context::set_error_char(unsigned char errorch, unsigned char enable)
270 {
271     return ftdi_set_error_char(d->ftdi, errorch, enable);
272 }
273
274 int Context::bitbang_enable(unsigned char bitmask)
275 {
276     return ftdi_set_bitmode(d->ftdi, bitmask, BITMODE_BITBANG);
277 }
278
279 int Context::bitbang_disable()
280 {
281     return ftdi_disable_bitbang(d->ftdi);
282 }
283
284 int Context::set_bitmode(unsigned char bitmask, unsigned char mode)
285 {
286     return ftdi_set_bitmode(d->ftdi, bitmask, mode);
287 }
288
289 int Context::set_bitmode(unsigned char bitmask, enum ftdi_mpsse_mode mode)
290 {
291     return ftdi_set_bitmode(d->ftdi, bitmask, mode);
292 }
293
294 int Context::read_pins(unsigned char *pins)
295 {
296     return ftdi_read_pins(d->ftdi, pins);
297 }
298
299 char* Context::error_string()
300 {
301     return ftdi_get_error_string(d->ftdi);
302 }
303
304 int 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
321 int 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  */
340 const std::string& Context::vendor()
341 {
342     return d->vendor;
343 }
344
345 /*! \brief Device strings properties.
346  */
347 const std::string& Context::description()
348 {
349     return d->description;
350 }
351
352 /*! \brief Device strings properties.
353  */
354 const std::string& Context::serial()
355 {
356     return d->serial;
357 }
358
359 void Context::set_context(struct ftdi_context* context)
360 {
361     ftdi_free(d->ftdi);
362     d->ftdi = context;
363 }
364
365 void Context::set_usb_device(struct libusb_device *dev)
366 {
367     d->dev = dev;
368 }
369
370 struct ftdi_context* Context::context()
371 {
372     return d->ftdi;
373 }
374
375 class Eeprom::Private
376 {
377 public:
378     Private()
379             : context(0)
380     {}
381
382     struct ftdi_eeprom eeprom;
383     struct ftdi_context* context;
384 };
385
386 Eeprom::Eeprom(Context* parent)
387         : d ( new Private() )
388 {
389     d->context = parent->context();
390 }
391
392 Eeprom::~Eeprom()
393 {
394 }
395
396 void Eeprom::init_defaults()
397 {
398     return ftdi_eeprom_initdefaults(d->context);
399 }
400
401 void Eeprom::set_size(int size)
402 {
403     return ftdi_eeprom_setsize(d->context, &d->eeprom, size);
404 }
405
406 int Eeprom::chip_id(unsigned int *chipid)
407 {
408     return ftdi_read_chipid(d->context, chipid);
409 }
410
411 int Eeprom::build(unsigned char *output)
412 {
413     return ftdi_eeprom_build(d->context, output);
414 }
415
416 int Eeprom::read(unsigned char *eeprom)
417 {
418     return ftdi_read_eeprom(d->context, eeprom);
419 }
420
421 int Eeprom::write(unsigned char *eeprom)
422 {
423     return ftdi_write_eeprom(d->context, eeprom);
424 }
425
426 int Eeprom::read_location(int eeprom_addr, unsigned short *eeprom_val)
427 {
428     return ftdi_read_eeprom_location(d->context, eeprom_addr, eeprom_val);
429 }
430
431 int Eeprom::write_location(int eeprom_addr, unsigned short eeprom_val)
432 {
433     return ftdi_write_eeprom_location(d->context, eeprom_addr, eeprom_val);
434 }
435
436 int Eeprom::erase()
437 {
438     return ftdi_erase_eeprom(d->context);
439 }
440
441 class List::Private
442 {
443 public:
444     Private(struct ftdi_device_list* _devlist)
445             : devlist(_devlist)
446     {}
447
448     ~Private()
449     {
450         if(devlist)
451             ftdi_list_free(&devlist);
452     }
453
454     std::list<Context> list;
455     struct ftdi_device_list* devlist;
456 };
457
458 List::List(struct ftdi_device_list* devlist)
459         : d( new Private(devlist) )
460 {
461     if (devlist != 0)
462     {
463         // Iterate list
464         for (; devlist != 0; devlist = devlist->next)
465         {
466             Context c;
467             c.set_usb_device(devlist->dev);
468             c.get_strings();
469             d->list.push_back(c);
470         }
471     }
472 }
473
474 List::~List()
475 {
476 }
477
478 /**
479 * Return begin iterator for accessing the contained list elements
480 * @return Iterator
481 */
482 List::iterator List::begin()
483 {
484     return d->list.begin();
485 }
486
487 /**
488 * Return end iterator for accessing the contained list elements
489 * @return Iterator
490 */
491 List::iterator List::end()
492 {
493     return d->list.end();
494 }
495
496 /**
497 * Return begin iterator for accessing the contained list elements
498 * @return Const iterator
499 */
500 List::const_iterator List::begin() const
501 {
502     return d->list.begin();
503 }
504
505 /**
506 * Return end iterator for accessing the contained list elements
507 * @return Const iterator
508 */
509 List::const_iterator List::end() const
510 {
511     return d->list.end();
512 }
513
514 /**
515 * Return begin reverse iterator for accessing the contained list elements
516 * @return Reverse iterator
517 */
518 List::reverse_iterator List::rbegin()
519 {
520     return d->list.rbegin();
521 }
522
523 /**
524 * Return end reverse iterator for accessing the contained list elements
525 * @return Reverse iterator
526 */
527 List::reverse_iterator List::rend()
528 {
529     return d->list.rend();
530 }
531
532 /**
533 * Return begin reverse iterator for accessing the contained list elements
534 * @return Const reverse iterator
535 */
536 List::const_reverse_iterator List::rbegin() const
537 {
538     return d->list.rbegin();
539 }
540
541 /**
542 * Return end reverse iterator for accessing the contained list elements
543 * @return Const reverse iterator
544 */
545 List::const_reverse_iterator List::rend() const
546 {
547     return d->list.rend();
548
549 }
550
551 /**
552 * Get number of elements stored in the list
553 * @return Number of elements
554 */
555 List::ListType::size_type List::size() const
556 {
557     return d->list.size();
558 }
559
560 /**
561 * Check if list is empty
562 * @return True if empty, false otherwise
563 */
564 bool List::empty() const
565 {
566     return d->list.empty();
567 }
568
569 /**
570  * Removes all elements. Invalidates all iterators.
571  * Do it in a non-throwing way and also make
572  * sure we really free the allocated memory.
573  */
574 void List::clear()
575 {
576     ListType().swap(d->list);
577
578     // Free device list
579     if (d->devlist)
580     {
581         ftdi_list_free(&d->devlist);
582         d->devlist = 0;
583     }
584 }
585
586 /**
587  * Appends a copy of the element as the new last element.
588  * @param element Value to copy and append
589 */
590 void List::push_back(const Context& element)
591 {
592     d->list.push_back(element);
593 }
594
595 /**
596  * Adds a copy of the element as the new first element.
597  * @param element Value to copy and add
598 */
599 void List::push_front(const Context& element)
600 {
601     d->list.push_front(element);
602 }
603
604 /**
605  * Erase one element pointed by iterator
606  * @param pos Element to erase
607  * @return Position of the following element (or end())
608 */
609 List::iterator List::erase(iterator pos)
610 {
611     return d->list.erase(pos);
612 }
613
614 /**
615  * Erase a range of elements
616  * @param beg Begin of range
617  * @param end End of range
618  * @return Position of the element after the erased range (or end())
619 */
620 List::iterator List::erase(iterator beg, iterator end)
621 {
622     return d->list.erase(beg, end);
623 }
624
625 List* List::find_all(int vendor, int product)
626 {
627     struct ftdi_device_list* dlist = 0;
628     struct ftdi_context ftdi;
629     ftdi_init(&ftdi);
630     ftdi_usb_find_all(&ftdi, &dlist, vendor, product);
631     ftdi_deinit(&ftdi);
632     return new List(dlist);
633 }
634
635 }