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