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