libftdi  0.19
ftdi.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                           ftdi.cpp  -  C++ wraper for libftdi
00003                              -------------------
00004     begin                : Mon Oct 13 2008
00005     copyright            : (C) 2008 by Marek Vavruša
00006     email                : opensource@intra2net.com and marek@vavrusa.com
00007  ***************************************************************************/
00008 /*
00009 Copyright (C) 2008 by Marek Vavruša
00010 
00011 The software in this package is distributed under the GNU General
00012 Public License version 2 (with a special exception described below).
00013 
00014 A copy of GNU General Public License (GPL) is included in this distribution,
00015 in the file COPYING.GPL.
00016 
00017 As a special exception, if other files instantiate templates or use macros
00018 or inline functions from this file, or you compile this file and link it
00019 with other works to produce a work based on this file, this file
00020 does not by itself cause the resulting work to be covered
00021 by the GNU General Public License.
00022 
00023 However the source code for this file must still be made available
00024 in accordance with section (3) of the GNU General Public License.
00025 
00026 This exception does not invalidate any other reasons why a work based
00027 on this file might be covered by the GNU General Public License.
00028 */
00029 #include "ftdi.hpp"
00030 #include "ftdi.h"
00031 
00032 namespace Ftdi
00033 {
00034 
00035 class Context::Private
00036 {
00037 public:
00038     Private()
00039             :  ftdi(0), dev(0), open(false)
00040     {
00041         ftdi = ftdi_new();
00042     }
00043 
00044     ~Private()
00045     {
00046         if (open)
00047             ftdi_usb_close(ftdi);
00048 
00049         ftdi_free(ftdi);
00050     }
00051 
00052     bool open;
00053 
00054     struct ftdi_context* ftdi;
00055     struct usb_device*   dev;
00056 
00057     std::string vendor;
00058     std::string description;
00059     std::string serial;
00060 };
00061 
00064 Context::Context()
00065         : d( new Private() )
00066 {
00067 }
00068 
00071 Context::~Context()
00072 {
00073 }
00074 
00075 bool Context::is_open()
00076 {
00077     return d->open;
00078 }
00079 
00080 int Context::open(int vendor, int product)
00081 {
00082     // Open device
00083     int ret = ftdi_usb_open(d->ftdi, vendor, product);
00084 
00085     if (ret < 0)
00086        return ret;
00087 
00088     return get_strings_and_reopen();
00089 }
00090 
00091 int Context::open(int vendor, int product, const std::string& description, const std::string& serial, unsigned int index)
00092 {
00093     // translate empty strings to NULL
00094     // -> do not use them to find the device (vs. require an empty string to be set in the EEPROM)
00095     const char* c_description=NULL;
00096     const char* c_serial=NULL;
00097     if (!description.empty())
00098         c_description=description.c_str();
00099     if (!serial.empty())
00100         c_serial=serial.c_str();
00101 
00102     int ret = ftdi_usb_open_desc_index(d->ftdi, vendor, product, c_description, c_serial, index);
00103 
00104     if (ret < 0)
00105        return ret;
00106 
00107     return get_strings_and_reopen();
00108 }
00109 
00110 int Context::open(const std::string& description)
00111 {
00112     int ret = ftdi_usb_open_string(d->ftdi, description.c_str());
00113 
00114     if (ret < 0)
00115        return ret;
00116 
00117     return get_strings_and_reopen();
00118 }
00119 
00120 int Context::open(struct usb_device *dev)
00121 {
00122     if (dev != 0)
00123         d->dev = dev;
00124 
00125     if (d->dev == 0)
00126         return -1;
00127 
00128     return get_strings_and_reopen();
00129 }
00130 
00131 int Context::close()
00132 {
00133     d->open = false;
00134     return ftdi_usb_close(d->ftdi);
00135 }
00136 
00137 int Context::reset()
00138 {
00139     return ftdi_usb_reset(d->ftdi);
00140 }
00141 
00142 int Context::flush(int mask)
00143 {
00144     int ret = 1;
00145 
00146     if (mask & Input)
00147         ret &= ftdi_usb_purge_rx_buffer(d->ftdi);
00148     if (mask & Output)
00149         ret &= ftdi_usb_purge_tx_buffer(d->ftdi);
00150 
00151     return ret;
00152 }
00153 
00154 int Context::set_interface(enum ftdi_interface interface)
00155 {
00156     return ftdi_set_interface(d->ftdi, interface);
00157 }
00158 
00159 void Context::set_usb_device(struct usb_dev_handle *dev)
00160 {
00161     ftdi_set_usbdev(d->ftdi, dev);
00162     d->dev = usb_device(dev);
00163 }
00164 
00165 int Context::set_baud_rate(int baudrate)
00166 {
00167     return ftdi_set_baudrate(d->ftdi, baudrate);
00168 }
00169 
00170 int Context::set_line_property(enum ftdi_bits_type bits, enum ftdi_stopbits_type sbit, enum ftdi_parity_type parity)
00171 {
00172     return ftdi_set_line_property(d->ftdi, bits, sbit, parity);
00173 }
00174 
00175 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)
00176 {
00177     return ftdi_set_line_property2(d->ftdi, bits, sbit, parity, break_type);
00178 }
00179 
00180 int Context::read(unsigned char *buf, int size)
00181 {
00182     return ftdi_read_data(d->ftdi, buf, size);
00183 }
00184 
00185 int Context::set_read_chunk_size(unsigned int chunksize)
00186 {
00187     return ftdi_read_data_set_chunksize(d->ftdi, chunksize);
00188 }
00189 
00190 int Context::read_chunk_size()
00191 {
00192     unsigned chunk = -1;
00193     if (ftdi_read_data_get_chunksize(d->ftdi, &chunk) < 0)
00194         return -1;
00195 
00196     return chunk;
00197 }
00198 
00199 int Context::write(unsigned char *buf, int size)
00200 {
00201     return ftdi_write_data(d->ftdi, buf, size);
00202 }
00203 
00204 int Context::set_write_chunk_size(unsigned int chunksize)
00205 {
00206     return ftdi_write_data_set_chunksize(d->ftdi, chunksize);
00207 }
00208 
00209 int Context::write_chunk_size()
00210 {
00211     unsigned chunk = -1;
00212     if (ftdi_write_data_get_chunksize(d->ftdi, &chunk) < 0)
00213         return -1;
00214 
00215     return chunk;
00216 }
00217 
00218 int Context::set_flow_control(int flowctrl)
00219 {
00220     return ftdi_setflowctrl(d->ftdi, flowctrl);
00221 }
00222 
00223 int Context::set_modem_control(int mask)
00224 {
00225     int dtr = 0, rts = 0;
00226 
00227     if (mask & Dtr)
00228         dtr = 1;
00229     if (mask & Rts)
00230         rts = 1;
00231 
00232     return ftdi_setdtr_rts(d->ftdi, dtr, rts);
00233 }
00234 
00235 int Context::set_dtr(bool state)
00236 {
00237     return ftdi_setdtr(d->ftdi, state);
00238 }
00239 
00240 int Context::set_rts(bool state)
00241 {
00242     return ftdi_setrts(d->ftdi, state);
00243 }
00244 
00245 int Context::set_latency(unsigned char latency)
00246 {
00247     return ftdi_set_latency_timer(d->ftdi, latency);
00248 }
00249 
00250 unsigned Context::latency()
00251 {
00252     unsigned char latency = 0;
00253     ftdi_get_latency_timer(d->ftdi, &latency);
00254     return latency;
00255 }
00256 
00257 unsigned short Context::poll_modem_status()
00258 {
00259     unsigned short status = 0;
00260     ftdi_poll_modem_status(d->ftdi, &status);
00261     return status;
00262 }
00263 
00264 int Context::set_event_char(unsigned char eventch, unsigned char enable)
00265 {
00266     return ftdi_set_event_char(d->ftdi, eventch, enable);
00267 }
00268 
00269 int Context::set_error_char(unsigned char errorch, unsigned char enable)
00270 {
00271     return ftdi_set_error_char(d->ftdi, errorch, enable);
00272 }
00273 
00274 int Context::bitbang_enable(unsigned char bitmask)
00275 {
00276     return ftdi_set_bitmode(d->ftdi, bitmask, BITMODE_BITBANG);
00277 }
00278 
00279 int Context::bitbang_disable()
00280 {
00281     return ftdi_disable_bitbang(d->ftdi);
00282 }
00283 
00284 int Context::set_bitmode(unsigned char bitmask, unsigned char mode)
00285 {
00286     return ftdi_set_bitmode(d->ftdi, bitmask, mode);
00287 }
00288 
00289 int Context::set_bitmode(unsigned char bitmask, enum ftdi_mpsse_mode mode)
00290 {
00291     return ftdi_set_bitmode(d->ftdi, bitmask, mode);
00292 }
00293 
00294 int Context::read_pins(unsigned char *pins)
00295 {
00296     return ftdi_read_pins(d->ftdi, pins);
00297 }
00298 
00299 char* Context::error_string()
00300 {
00301     return ftdi_get_error_string(d->ftdi);
00302 }
00303 
00304 int Context::get_strings()
00305 {
00306     // Prepare buffers
00307     char vendor[512], desc[512], serial[512];
00308 
00309     int ret = ftdi_usb_get_strings(d->ftdi, d->dev, vendor, 512, desc, 512, serial, 512);
00310 
00311     if (ret < 0)
00312         return -1;
00313 
00314     d->vendor = vendor;
00315     d->description = desc;
00316     d->serial = serial;
00317 
00318     return 1;
00319 }
00320 
00321 int Context::get_strings_and_reopen()
00322 {
00323     // Get device strings (closes device)
00324     int ret=get_strings();
00325     if (ret < 0)
00326     {
00327         d->open = 0;
00328         return ret;
00329     }
00330 
00331     // Reattach device
00332     ret = ftdi_usb_open_dev(d->ftdi, d->dev);
00333     d->open = (ret >= 0);
00334 
00335     return ret;
00336 }
00337 
00340 const std::string& Context::vendor()
00341 {
00342     return d->vendor;
00343 }
00344 
00347 const std::string& Context::description()
00348 {
00349     return d->description;
00350 }
00351 
00354 const std::string& Context::serial()
00355 {
00356     return d->serial;
00357 }
00358 
00359 void Context::set_context(struct ftdi_context* context)
00360 {
00361     ftdi_free(d->ftdi);
00362     d->ftdi = context;
00363 }
00364 
00365 void Context::set_usb_device(struct usb_device *dev)
00366 {
00367     d->dev = dev;
00368 }
00369 
00370 struct ftdi_context* Context::context()
00371 {
00372     return d->ftdi;
00373 }
00374 
00375 class Eeprom::Private
00376 {
00377 public:
00378     Private()
00379             : context(0)
00380     {}
00381 
00382     struct ftdi_eeprom eeprom;
00383     struct ftdi_context* context;
00384 };
00385 
00386 Eeprom::Eeprom(Context* parent)
00387         : d ( new Private() )
00388 {
00389     d->context = parent->context();
00390 }
00391 
00392 Eeprom::~Eeprom()
00393 {
00394 }
00395 
00396 void Eeprom::init_defaults()
00397 {
00398     return ftdi_eeprom_initdefaults(&d->eeprom);
00399 }
00400 
00401 void Eeprom::set_size(int size)
00402 {
00403     return ftdi_eeprom_setsize(d->context, &d->eeprom, size);
00404 }
00405 
00406 int Eeprom::size(unsigned char *eeprom, int maxsize)
00407 {
00408     return ftdi_read_eeprom_getsize(d->context, eeprom, maxsize);
00409 }
00410 
00411 int Eeprom::chip_id(unsigned int *chipid)
00412 {
00413     return ftdi_read_chipid(d->context, chipid);
00414 }
00415 
00416 int Eeprom::build(unsigned char *output)
00417 {
00418     return ftdi_eeprom_build(&d->eeprom, output);
00419 }
00420 
00421 int Eeprom::read(unsigned char *eeprom)
00422 {
00423     return ftdi_read_eeprom(d->context, eeprom);
00424 }
00425 
00426 int Eeprom::write(unsigned char *eeprom)
00427 {
00428     return ftdi_write_eeprom(d->context, eeprom);
00429 }
00430 
00431 int Eeprom::read_location(int eeprom_addr, unsigned short *eeprom_val)
00432 {
00433     return ftdi_read_eeprom_location(d->context, eeprom_addr, eeprom_val);
00434 }
00435 
00436 int Eeprom::write_location(int eeprom_addr, unsigned short eeprom_val)
00437 {
00438     return ftdi_write_eeprom_location(d->context, eeprom_addr, eeprom_val);
00439 }
00440 
00441 int Eeprom::erase()
00442 {
00443     return ftdi_erase_eeprom(d->context);
00444 }
00445 
00446 class List::Private
00447 {
00448 public:
00449     Private(struct ftdi_device_list* _devlist)
00450             : devlist(_devlist)
00451     {}
00452 
00453     ~Private()
00454     {
00455         if(devlist)
00456             ftdi_list_free(&devlist);
00457     }
00458 
00459     std::list<Context> list;
00460     struct ftdi_device_list* devlist;
00461 };
00462 
00463 List::List(struct ftdi_device_list* devlist)
00464         : d( new Private(devlist) )
00465 {
00466     if (devlist != 0)
00467     {
00468         // Iterate list
00469         for (; devlist != 0; devlist = devlist->next)
00470         {
00471             Context c;
00472             c.set_usb_device(devlist->dev);
00473             c.get_strings();
00474             d->list.push_back(c);
00475         }
00476     }
00477 }
00478 
00479 List::~List()
00480 {
00481 }
00482 
00487 List::iterator List::begin()
00488 {
00489     return d->list.begin();
00490 }
00491 
00496 List::iterator List::end()
00497 {
00498     return d->list.end();
00499 }
00500 
00505 List::const_iterator List::begin() const
00506 {
00507     return d->list.begin();
00508 }
00509 
00514 List::const_iterator List::end() const
00515 {
00516     return d->list.end();
00517 }
00518 
00523 List::reverse_iterator List::rbegin()
00524 {
00525     return d->list.rbegin();
00526 }
00527 
00532 List::reverse_iterator List::rend()
00533 {
00534     return d->list.rend();
00535 }
00536 
00541 List::const_reverse_iterator List::rbegin() const
00542 {
00543     return d->list.rbegin();
00544 }
00545 
00550 List::const_reverse_iterator List::rend() const
00551 {
00552     return d->list.rend();
00553 
00554 }
00555 
00560 List::ListType::size_type List::size() const
00561 {
00562     return d->list.size();
00563 }
00564 
00569 bool List::empty() const
00570 {
00571     return d->list.empty();
00572 }
00573 
00579 void List::clear()
00580 {
00581     ListType().swap(d->list);
00582 
00583     // Free device list
00584     if (d->devlist)
00585     {
00586         ftdi_list_free(&d->devlist);
00587         d->devlist = 0;
00588     }
00589 }
00590 
00595 void List::push_back(const Context& element)
00596 {
00597     d->list.push_back(element);
00598 }
00599 
00604 void List::push_front(const Context& element)
00605 {
00606     d->list.push_front(element);
00607 }
00608 
00614 List::iterator List::erase(iterator pos)
00615 {
00616     return d->list.erase(pos);
00617 }
00618 
00625 List::iterator List::erase(iterator beg, iterator end)
00626 {
00627     return d->list.erase(beg, end);
00628 }
00629 
00630 List* List::find_all(int vendor, int product)
00631 {
00632     struct ftdi_device_list* dlist = 0;
00633     struct ftdi_context ftdi;
00634     ftdi_init(&ftdi);
00635     ftdi_usb_find_all(&ftdi, &dlist, vendor, product);
00636     ftdi_deinit(&ftdi);
00637     return new List(dlist);
00638 }
00639 
00640 }