Remove duplicated udev rule.
[libftdi] / ftdipp / ftdi.cpp
... / ...
CommitLineData
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/*
9Copyright (C) 2008 by Marek Vavruša
10
11The software in this package is distributed under the GNU General
12Public License version 2 (with a special exception described below).
13
14A copy of GNU General Public License (GPL) is included in this distribution,
15in the file COPYING.GPL.
16
17As a special exception, if other files instantiate templates or use macros
18or inline functions from this file, or you compile this file and link it
19with other works to produce a work based on this file, this file
20does not by itself cause the resulting work to be covered
21by the GNU General Public License.
22
23However the source code for this file must still be made available
24in accordance with section (3) of the GNU General Public License.
25
26This exception does not invalidate any other reasons why a work based
27on 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
33namespace Ftdi
34{
35
36class Context::Private
37{
38public:
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 */
65Context::Context()
66 : d( new Private() )
67{
68}
69
70/*! \brief Destructor.
71 */
72Context::~Context()
73{
74}
75
76bool Context::is_open()
77{
78 return d->open;
79}
80
81int 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
92int 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
111int 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
121int 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
132int Context::close()
133{
134 d->open = false;
135 return ftdi_usb_close(d->ftdi);
136}
137
138int Context::reset()
139{
140 return ftdi_usb_reset(d->ftdi);
141}
142
143int 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
155int Context::set_interface(enum ftdi_interface interface)
156{
157 return ftdi_set_interface(d->ftdi, interface);
158}
159
160void 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
166int Context::set_baud_rate(int baudrate)
167{
168 return ftdi_set_baudrate(d->ftdi, baudrate);
169}
170
171int 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
176int 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
181int Context::read(unsigned char *buf, int size)
182{
183 return ftdi_read_data(d->ftdi, buf, size);
184}
185
186int Context::set_read_chunk_size(unsigned int chunksize)
187{
188 return ftdi_read_data_set_chunksize(d->ftdi, chunksize);
189}
190
191int 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
200int Context::write(unsigned char *buf, int size)
201{
202 return ftdi_write_data(d->ftdi, buf, size);
203}
204
205int Context::set_write_chunk_size(unsigned int chunksize)
206{
207 return ftdi_write_data_set_chunksize(d->ftdi, chunksize);
208}
209
210int 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
219int Context::set_flow_control(int flowctrl)
220{
221 return ftdi_setflowctrl(d->ftdi, flowctrl);
222}
223
224int 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
236int Context::set_dtr(bool state)
237{
238 return ftdi_setdtr(d->ftdi, state);
239}
240
241int Context::set_rts(bool state)
242{
243 return ftdi_setrts(d->ftdi, state);
244}
245
246int Context::set_latency(unsigned char latency)
247{
248 return ftdi_set_latency_timer(d->ftdi, latency);
249}
250
251unsigned Context::latency()
252{
253 unsigned char latency = 0;
254 ftdi_get_latency_timer(d->ftdi, &latency);
255 return latency;
256}
257
258unsigned short Context::poll_modem_status()
259{
260 unsigned short status = 0;
261 ftdi_poll_modem_status(d->ftdi, &status);
262 return status;
263}
264
265int Context::set_event_char(unsigned char eventch, unsigned char enable)
266{
267 return ftdi_set_event_char(d->ftdi, eventch, enable);
268}
269
270int Context::set_error_char(unsigned char errorch, unsigned char enable)
271{
272 return ftdi_set_error_char(d->ftdi, errorch, enable);
273}
274
275int Context::set_bitmode(unsigned char bitmask, unsigned char mode)
276{
277 return ftdi_set_bitmode(d->ftdi, bitmask, mode);
278}
279
280int Context::set_bitmode(unsigned char bitmask, enum ftdi_mpsse_mode mode)
281{
282 return ftdi_set_bitmode(d->ftdi, bitmask, mode);
283}
284
285int Context::bitbang_disable()
286{
287 return ftdi_disable_bitbang(d->ftdi);
288}
289
290int Context::read_pins(unsigned char *pins)
291{
292 return ftdi_read_pins(d->ftdi, pins);
293}
294
295char* Context::error_string()
296{
297 return ftdi_get_error_string(d->ftdi);
298}
299
300int 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
317int 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 */
336const std::string& Context::vendor()
337{
338 return d->vendor;
339}
340
341/*! \brief Device strings properties.
342 */
343const std::string& Context::description()
344{
345 return d->description;
346}
347
348/*! \brief Device strings properties.
349 */
350const std::string& Context::serial()
351{
352 return d->serial;
353}
354
355void Context::set_context(struct ftdi_context* context)
356{
357 ftdi_free(d->ftdi);
358 d->ftdi = context;
359}
360
361void Context::set_usb_device(struct libusb_device *dev)
362{
363 d->dev = dev;
364}
365
366struct ftdi_context* Context::context()
367{
368 return d->ftdi;
369}
370
371class Eeprom::Private
372{
373public:
374 Private()
375 : context(0)
376 {}
377
378 struct ftdi_eeprom eeprom;
379 struct ftdi_context* context;
380};
381
382Eeprom::Eeprom(Context* parent)
383 : d ( new Private() )
384{
385 d->context = parent->context();
386}
387
388Eeprom::~Eeprom()
389{
390}
391
392int Eeprom::init_defaults(char* manufacturer, char *product, char * serial)
393{
394 return ftdi_eeprom_initdefaults(d->context, manufacturer, product, serial);
395}
396
397int Eeprom::chip_id(unsigned int *chipid)
398{
399 return ftdi_read_chipid(d->context, chipid);
400}
401
402int Eeprom::build(unsigned char *output)
403{
404 return ftdi_eeprom_build(d->context);
405}
406
407int Eeprom::read(unsigned char *eeprom)
408{
409 return ftdi_read_eeprom(d->context);
410}
411
412int Eeprom::write(unsigned char *eeprom)
413{
414 return ftdi_write_eeprom(d->context);
415}
416
417int 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
422int 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
427int Eeprom::erase()
428{
429 return ftdi_erase_eeprom(d->context);
430}
431
432class List::Private
433{
434public:
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
449List::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
465List::~List()
466{
467}
468
469/**
470* Return begin iterator for accessing the contained list elements
471* @return Iterator
472*/
473List::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*/
482List::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*/
491List::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*/
500List::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*/
509List::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*/
518List::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*/
527List::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*/
536List::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*/
546List::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*/
555bool 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 */
565void 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*/
581void 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*/
590void 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*/
600List::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*/
611List::iterator List::erase(iterator beg, iterator end)
612{
613 return d->list.erase(beg, end);
614}
615
616List* 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}