Use boost::shared_ptr for reference counted memory handling
[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 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU Lesser General Public License           *
13  *   version 2.1 as published by the Free Software Foundation;             *
14  *                                                                         *
15  ***************************************************************************/
16
17 #include "ftdi.hpp"
18 #include "ftdi.h"
19
20 namespace Ftdi
21 {
22
23 class Context::Private
24 {
25 public:
26     Private()
27         :  ftdi(0), dev(0), open(false)
28     {
29         ftdi = ftdi_new();
30     }
31
32     ~Private()
33     {
34         if(open)
35             ftdi_usb_close(ftdi);
36
37         ftdi_free(ftdi);
38     }
39
40     bool open;
41
42     struct ftdi_context* ftdi;
43     struct usb_device*   dev;
44
45     std::string vendor;
46     std::string description;
47     std::string serial;
48 };
49
50 /*! \brief Constructor.
51  */
52 Context::Context()
53         : d( new Private() )
54 {
55 }
56
57 /*! \brief Destructor.
58  */
59 Context::~Context()
60 {
61 }
62
63 bool Context::is_open()
64 {
65     return d->open;
66 }
67
68 int Context::open(int vendor, int product, const std::string& description, const std::string& serial)
69 {
70     int ret = 0;
71
72     if (description.empty() && serial.empty())
73         ret = ftdi_usb_open(d->ftdi, vendor, product);
74     else
75         ret = ftdi_usb_open_desc(d->ftdi, vendor, product, description.c_str(), serial.c_str());
76
77     d->dev = usb_device(d->ftdi->usb_dev);
78
79     if ((ret = ftdi_usb_open_dev(d->ftdi, d->dev)) >= 0)
80     {
81         d->open = true;
82         get_strings();
83     }
84
85     return ret;
86 }
87
88 int Context::open(struct usb_device *dev)
89 {
90     int ret = 0;
91
92     if (dev != 0)
93         d->dev = dev;
94
95     if (d->dev == 0)
96         return -1;
97
98     if ((ret = ftdi_usb_open_dev(d->ftdi, d->dev)) >= 0)
99     {
100         d->open = true;
101         get_strings();
102     }
103
104     return ret;
105 }
106
107 int Context::close()
108 {
109     d->open = false;
110     return ftdi_usb_close(d->ftdi);
111 }
112
113 int Context::reset()
114 {
115     return ftdi_usb_reset(d->ftdi);
116 }
117
118 int Context::flush(int mask)
119 {
120     int ret = 1;
121
122     if (mask & Input)
123         ret &= ftdi_usb_purge_rx_buffer(d->ftdi);
124     if (mask & Output)
125         ret &= ftdi_usb_purge_tx_buffer(d->ftdi);
126
127     return ret;
128 }
129
130 int Context::set_interface(enum ftdi_interface interface)
131 {
132     return ftdi_set_interface(d->ftdi, interface);
133 }
134
135 void Context::set_usb_device(struct usb_dev_handle *dev)
136 {
137     ftdi_set_usbdev(d->ftdi, dev);
138     d->dev = usb_device(dev);
139 }
140
141 int Context::set_baud_rate(int baudrate)
142 {
143     return ftdi_set_baudrate(d->ftdi, baudrate);
144 }
145
146 int Context::set_line_property(enum ftdi_bits_type bits, enum ftdi_stopbits_type sbit, enum ftdi_parity_type parity)
147 {
148     return ftdi_set_line_property(d->ftdi, bits, sbit, parity);
149 }
150
151 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)
152 {
153     return ftdi_set_line_property2(d->ftdi, bits, sbit, parity, break_type);
154 }
155
156 int Context::read(unsigned char *buf, int size)
157 {
158     return ftdi_read_data(d->ftdi, buf, size);
159 }
160
161 int Context::set_read_chunk_size(unsigned int chunksize)
162 {
163     return ftdi_read_data_set_chunksize(d->ftdi, chunksize);
164 }
165
166 int Context::read_chunk_size()
167 {
168     unsigned chunk = -1;
169     if (ftdi_read_data_get_chunksize(d->ftdi, &chunk) < 0)
170         return -1;
171
172     return chunk;
173 }
174
175 int Context::write(unsigned char *buf, int size)
176 {
177     return ftdi_write_data(d->ftdi, buf, size);
178 }
179
180 int Context::set_write_chunk_size(unsigned int chunksize)
181 {
182     return ftdi_write_data_set_chunksize(d->ftdi, chunksize);
183 }
184
185 int Context::write_chunk_size()
186 {
187     unsigned chunk = -1;
188     if (ftdi_write_data_get_chunksize(d->ftdi, &chunk) < 0)
189         return -1;
190
191     return chunk;
192 }
193
194 int Context::set_flow_control(int flowctrl)
195 {
196     return ftdi_setflowctrl(d->ftdi, flowctrl);
197 }
198
199 int Context::set_modem_control(int mask)
200 {
201     int dtr = 0, rts = 0;
202
203     if (mask & Dtr)
204         dtr = 1;
205     if (mask & Rts)
206         rts = 1;
207
208     return ftdi_setdtr_rts(d->ftdi, dtr, rts);
209 }
210
211 int Context::set_dtr(bool state)
212 {
213     return ftdi_setdtr(d->ftdi, state);
214 }
215
216 int Context::set_rts(bool state)
217 {
218     return ftdi_setrts(d->ftdi, state);
219 }
220
221 int Context::set_latency(unsigned char latency)
222 {
223     return ftdi_set_latency_timer(d->ftdi, latency);
224 }
225
226 unsigned Context::latency()
227 {
228     unsigned char latency = 0;
229     ftdi_get_latency_timer(d->ftdi, &latency);
230     return latency;
231 }
232
233 unsigned short Context::poll_modem_status()
234 {
235     unsigned short status = 0;
236     ftdi_poll_modem_status(d->ftdi, &status);
237     return status;
238 }
239
240 int Context::set_event_char(unsigned char eventch, unsigned char enable)
241 {
242     return ftdi_set_event_char(d->ftdi, eventch, enable);
243 }
244
245 int Context::set_error_char(unsigned char errorch, unsigned char enable)
246 {
247     return ftdi_set_error_char(d->ftdi, errorch, enable);
248 }
249
250 int Context::bitbang_enable(unsigned char bitmask)
251 {
252     return ftdi_enable_bitbang(d->ftdi, bitmask);
253 }
254
255 int Context::bitbang_disable()
256 {
257     return ftdi_disable_bitbang(d->ftdi);
258 }
259
260 int Context::set_bitmode(unsigned char bitmask, unsigned char mode)
261 {
262     return ftdi_set_bitmode(d->ftdi, bitmask, mode);
263 }
264
265 int Context::read_pins(unsigned char *pins)
266 {
267     return ftdi_read_pins(d->ftdi, pins);
268 }
269
270 char* Context::error_string()
271 {
272     return ftdi_get_error_string(d->ftdi);
273 }
274
275 int Context::get_strings()
276 {
277     // Prepare buffers
278     char vendor[512], desc[512], serial[512];
279
280     int ret = ftdi_usb_get_strings(d->ftdi, d->dev, vendor, 512, desc, 512, serial, 512);
281
282     if (ret < 0)
283         return -1;
284
285     d->vendor = vendor;
286     d->description = desc;
287     d->serial = serial;
288
289     return 1;
290 }
291
292 /*! \fn vendor
293  * \fn description
294  * \fn serial
295  * \brief Device strings properties.
296  */
297 const std::string& Context::vendor()
298 {
299     return d->vendor;
300 }
301
302 const std::string& Context::description()
303 {
304     return d->description;
305 }
306
307 const std::string& Context::serial()
308 {
309     return d->serial;
310 }
311
312 void Context::set_context(struct ftdi_context* context)
313 {
314     ftdi_free(d->ftdi);
315     d->ftdi = context;
316 }
317
318 void Context::set_usb_device(struct usb_device *dev)
319 {
320     d->dev = dev;
321 }
322
323 struct ftdi_context* Context::context()
324 {
325     return d->ftdi;
326 }
327
328 class Eeprom::Private
329 {
330 public:
331     Private()
332             : context(0)
333     {}
334
335     struct ftdi_eeprom eeprom;
336     struct ftdi_context* context;
337 };
338
339 Eeprom::Eeprom(Context* parent)
340         : d ( new Private() )
341 {
342     d->context = parent->context();
343 }
344
345 Eeprom::~Eeprom()
346 {
347 }
348
349 void Eeprom::init_defaults()
350 {
351     return ftdi_eeprom_initdefaults(&d->eeprom);
352 }
353
354 void Eeprom::set_size(int size)
355 {
356     return ftdi_eeprom_setsize(d->context, &d->eeprom, size);
357 }
358
359 int Eeprom::size(unsigned char *eeprom, int maxsize)
360 {
361     return ftdi_read_eeprom_getsize(d->context, eeprom, maxsize);
362 }
363
364 int Eeprom::chip_id(unsigned int *chipid)
365 {
366     return ftdi_read_chipid(d->context, chipid);
367 }
368
369 int Eeprom::build(unsigned char *output)
370 {
371     return ftdi_eeprom_build(&d->eeprom, output);
372 }
373
374 int Eeprom::read(unsigned char *eeprom)
375 {
376     return ftdi_read_eeprom(d->context, eeprom);
377 }
378
379 int Eeprom::write(unsigned char *eeprom)
380 {
381     return ftdi_write_eeprom(d->context, eeprom);
382 }
383
384 int Eeprom::erase()
385 {
386     return ftdi_erase_eeprom(d->context);
387 }
388
389 class List::Private
390 {
391 public:
392     Private(struct ftdi_device_list* devlist)
393             : list(devlist)
394     {}
395
396     ~Private()
397     {
398         ftdi_list_free(&list);
399     }
400
401     struct ftdi_device_list* list;
402 };
403
404 List::List(struct ftdi_device_list* devlist)
405         : ListBase(), d( new Private(devlist) )
406 {
407     if (devlist != 0)
408     {
409         // Iterate list
410         for (d->list = devlist; d->list != 0; d->list = d->list->next)
411         {
412             Context c;
413             c.set_usb_device(d->list->dev);
414             c.get_strings();
415             push_back(c);
416         }
417     }
418 }
419
420 List::~List()
421 {
422 }
423
424 List* List::find_all(int vendor, int product)
425 {
426     struct ftdi_device_list* dlist = 0;
427     struct ftdi_context ftdi;
428     ftdi_init(&ftdi);
429     ftdi_usb_find_all(&ftdi, &dlist, vendor, product);
430     ftdi_deinit(&ftdi);
431     return new List(dlist);
432 }
433
434 }