libftdi1  1.0
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-2013 by Marek Vavruša / libftdi developers
00006     email                : opensource@intra2net.com and marek@vavrusa.com
00007  ***************************************************************************/
00008 /*
00009 Copyright (C) 2008-2013 by Marek Vavruša / libftdi developers
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 <libusb.h>
00030 #include "ftdi.hpp"
00031 #include "ftdi_i.h"
00032 #include "ftdi.h"
00033 
00034 namespace Ftdi
00035 {
00036 
00037 class Context::Private
00038 {
00039 public:
00040     Private()
00041             : open(false), ftdi(0), dev(0)
00042     {
00043         ftdi = ftdi_new();
00044     }
00045 
00046     ~Private()
00047     {
00048         if (open)
00049             ftdi_usb_close(ftdi);
00050 
00051         ftdi_free(ftdi);
00052     }
00053 
00054     bool open;
00055 
00056     struct ftdi_context* ftdi;
00057     struct libusb_device* dev;
00058 
00059     std::string vendor;
00060     std::string description;
00061     std::string serial;
00062 };
00063 
00066 Context::Context()
00067         : d( new Private() )
00068 {
00069 }
00070 
00073 Context::~Context()
00074 {
00075 }
00076 
00077 bool Context::is_open()
00078 {
00079     return d->open;
00080 }
00081 
00082 int Context::open(int vendor, int product)
00083 {
00084     // Open device
00085     int ret = ftdi_usb_open(d->ftdi, vendor, product);
00086 
00087     if (ret < 0)
00088        return ret;
00089 
00090     return get_strings_and_reopen();
00091 }
00092 
00093 int Context::open(int vendor, int product, const std::string& description, const std::string& serial, unsigned int index)
00094 {
00095     // translate empty strings to NULL
00096     // -> do not use them to find the device (vs. require an empty string to be set in the EEPROM)
00097     const char* c_description=NULL;
00098     const char* c_serial=NULL;
00099     if (!description.empty())
00100         c_description=description.c_str();
00101     if (!serial.empty())
00102         c_serial=serial.c_str();
00103 
00104     int ret = ftdi_usb_open_desc_index(d->ftdi, vendor, product, c_description, c_serial, index);
00105 
00106     if (ret < 0)
00107        return ret;
00108 
00109     return get_strings_and_reopen();
00110 }
00111 
00112 int Context::open(const std::string& description)
00113 {
00114     int ret = ftdi_usb_open_string(d->ftdi, description.c_str());
00115 
00116     if (ret < 0)
00117        return ret;
00118 
00119     return get_strings_and_reopen();
00120 }
00121 
00122 int Context::open(struct libusb_device *dev)
00123 {
00124     if (dev != 0)
00125         d->dev = dev;
00126 
00127     if (d->dev == 0)
00128         return -1;
00129 
00130     return get_strings_and_reopen();
00131 }
00132 
00133 int Context::close()
00134 {
00135     d->open = false;
00136     d->dev = 0;
00137     return ftdi_usb_close(d->ftdi);
00138 }
00139 
00140 int Context::reset()
00141 {
00142     return ftdi_usb_reset(d->ftdi);
00143 }
00144 
00145 int Context::flush(int mask)
00146 {
00147     int ret = 1;
00148 
00149     if (mask & Input)
00150         ret &= ftdi_usb_purge_rx_buffer(d->ftdi);
00151     if (mask & Output)
00152         ret &= ftdi_usb_purge_tx_buffer(d->ftdi);
00153 
00154     return ret;
00155 }
00156 
00157 int Context::set_interface(enum ftdi_interface interface)
00158 {
00159     return ftdi_set_interface(d->ftdi, interface);
00160 }
00161 
00162 void Context::set_usb_device(struct libusb_device_handle *dev)
00163 {
00164     ftdi_set_usbdev(d->ftdi, dev);
00165     d->dev = libusb_get_device(dev);
00166 }
00167 
00168 int Context::set_baud_rate(int baudrate)
00169 {
00170     return ftdi_set_baudrate(d->ftdi, baudrate);
00171 }
00172 
00173 int Context::set_line_property(enum ftdi_bits_type bits, enum ftdi_stopbits_type sbit, enum ftdi_parity_type parity)
00174 {
00175     return ftdi_set_line_property(d->ftdi, bits, sbit, parity);
00176 }
00177 
00178 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)
00179 {
00180     return ftdi_set_line_property2(d->ftdi, bits, sbit, parity, break_type);
00181 }
00182 
00183 int Context::read(unsigned char *buf, int size)
00184 {
00185     return ftdi_read_data(d->ftdi, buf, size);
00186 }
00187 
00188 int Context::set_read_chunk_size(unsigned int chunksize)
00189 {
00190     return ftdi_read_data_set_chunksize(d->ftdi, chunksize);
00191 }
00192 
00193 int Context::read_chunk_size()
00194 {
00195     unsigned chunk = -1;
00196     if (ftdi_read_data_get_chunksize(d->ftdi, &chunk) < 0)
00197         return -1;
00198 
00199     return chunk;
00200 }
00201 
00202 int Context::write(unsigned char *buf, int size)
00203 {
00204     return ftdi_write_data(d->ftdi, buf, size);
00205 }
00206 
00207 int Context::set_write_chunk_size(unsigned int chunksize)
00208 {
00209     return ftdi_write_data_set_chunksize(d->ftdi, chunksize);
00210 }
00211 
00212 int Context::write_chunk_size()
00213 {
00214     unsigned chunk = -1;
00215     if (ftdi_write_data_get_chunksize(d->ftdi, &chunk) < 0)
00216         return -1;
00217 
00218     return chunk;
00219 }
00220 
00221 int Context::set_flow_control(int flowctrl)
00222 {
00223     return ftdi_setflowctrl(d->ftdi, flowctrl);
00224 }
00225 
00226 int Context::set_modem_control(int mask)
00227 {
00228     int dtr = 0, rts = 0;
00229 
00230     if (mask & Dtr)
00231         dtr = 1;
00232     if (mask & Rts)
00233         rts = 1;
00234 
00235     return ftdi_setdtr_rts(d->ftdi, dtr, rts);
00236 }
00237 
00238 int Context::set_dtr(bool state)
00239 {
00240     return ftdi_setdtr(d->ftdi, state);
00241 }
00242 
00243 int Context::set_rts(bool state)
00244 {
00245     return ftdi_setrts(d->ftdi, state);
00246 }
00247 
00248 int Context::set_latency(unsigned char latency)
00249 {
00250     return ftdi_set_latency_timer(d->ftdi, latency);
00251 }
00252 
00253 unsigned Context::latency()
00254 {
00255     unsigned char latency = 0;
00256     ftdi_get_latency_timer(d->ftdi, &latency);
00257     return latency;
00258 }
00259 
00260 unsigned short Context::poll_modem_status()
00261 {
00262     unsigned short status = 0;
00263     ftdi_poll_modem_status(d->ftdi, &status);
00264     return status;
00265 }
00266 
00267 int Context::set_event_char(unsigned char eventch, unsigned char enable)
00268 {
00269     return ftdi_set_event_char(d->ftdi, eventch, enable);
00270 }
00271 
00272 int Context::set_error_char(unsigned char errorch, unsigned char enable)
00273 {
00274     return ftdi_set_error_char(d->ftdi, errorch, enable);
00275 }
00276 
00277 int Context::set_bitmode(unsigned char bitmask, unsigned char mode)
00278 {
00279     return ftdi_set_bitmode(d->ftdi, bitmask, mode);
00280 }
00281 
00282 int Context::set_bitmode(unsigned char bitmask, enum ftdi_mpsse_mode mode)
00283 {
00284     return ftdi_set_bitmode(d->ftdi, bitmask, mode);
00285 }
00286 
00287 int Context::bitbang_disable()
00288 {
00289     return ftdi_disable_bitbang(d->ftdi);
00290 }
00291 
00292 int Context::read_pins(unsigned char *pins)
00293 {
00294     return ftdi_read_pins(d->ftdi, pins);
00295 }
00296 
00297 char* Context::error_string()
00298 {
00299     return ftdi_get_error_string(d->ftdi);
00300 }
00301 
00302 int Context::get_strings()
00303 {
00304     // Prepare buffers
00305     char vendor[512], desc[512], serial[512];
00306 
00307     int ret = ftdi_usb_get_strings(d->ftdi, d->dev, vendor, 512, desc, 512, serial, 512);
00308 
00309     if (ret < 0)
00310         return -1;
00311 
00312     d->vendor = vendor;
00313     d->description = desc;
00314     d->serial = serial;
00315 
00316     return 1;
00317 }
00318 
00319 int Context::get_strings_and_reopen()
00320 {
00321     if ( d->dev == 0 )
00322     {
00323         d->dev = libusb_get_device(d->ftdi->usb_dev);
00324     }
00325 
00326     // Get device strings (closes device)
00327     int ret=get_strings();
00328     if (ret < 0)
00329     {
00330         d->open = 0;
00331         return ret;
00332     }
00333 
00334     // Reattach device
00335     ret = ftdi_usb_open_dev(d->ftdi, d->dev);
00336     d->open = (ret >= 0);
00337 
00338     return ret;
00339 }
00340 
00343 const std::string& Context::vendor()
00344 {
00345     return d->vendor;
00346 }
00347 
00350 const std::string& Context::description()
00351 {
00352     return d->description;
00353 }
00354 
00357 const std::string& Context::serial()
00358 {
00359     return d->serial;
00360 }
00361 
00362 void Context::set_context(struct ftdi_context* context)
00363 {
00364     ftdi_free(d->ftdi);
00365     d->ftdi = context;
00366 }
00367 
00368 void Context::set_usb_device(struct libusb_device *dev)
00369 {
00370     d->dev = dev;
00371 }
00372 
00373 struct ftdi_context* Context::context()
00374 {
00375     return d->ftdi;
00376 }
00377 
00378 class Eeprom::Private
00379 {
00380 public:
00381     Private()
00382             : context(0)
00383     {}
00384 
00385     struct ftdi_eeprom eeprom;
00386     struct ftdi_context* context;
00387 };
00388 
00389 Eeprom::Eeprom(Context* parent)
00390         : d ( new Private() )
00391 {
00392     d->context = parent->context();
00393 }
00394 
00395 Eeprom::~Eeprom()
00396 {
00397 }
00398 
00399 int Eeprom::init_defaults(char* manufacturer, char *product, char * serial)
00400 {
00401     return ftdi_eeprom_initdefaults(d->context, manufacturer, product, serial);
00402 }
00403 
00404 int Eeprom::chip_id(unsigned int *chipid)
00405 {
00406     return ftdi_read_chipid(d->context, chipid);
00407 }
00408 
00409 int Eeprom::build(unsigned char *output)
00410 {
00411     return ftdi_eeprom_build(d->context);
00412 }
00413 
00414 int Eeprom::read(unsigned char *eeprom)
00415 {
00416     return ftdi_read_eeprom(d->context);
00417 }
00418 
00419 int Eeprom::write(unsigned char *eeprom)
00420 {
00421     return ftdi_write_eeprom(d->context);
00422 }
00423 
00424 int Eeprom::read_location(int eeprom_addr, unsigned short *eeprom_val)
00425 {
00426     return ftdi_read_eeprom_location(d->context, eeprom_addr, eeprom_val);
00427 }
00428 
00429 int Eeprom::write_location(int eeprom_addr, unsigned short eeprom_val)
00430 {
00431     return ftdi_write_eeprom_location(d->context, eeprom_addr, eeprom_val);
00432 }
00433 
00434 int Eeprom::erase()
00435 {
00436     return ftdi_erase_eeprom(d->context);
00437 }
00438 
00439 class List::Private
00440 {
00441 public:
00442     Private(struct ftdi_device_list* _devlist)
00443             : devlist(_devlist)
00444     {}
00445 
00446     ~Private()
00447     {
00448         if(devlist)
00449             ftdi_list_free(&devlist);
00450     }
00451 
00452     std::list<Context> list;
00453     struct ftdi_device_list* devlist;
00454 };
00455 
00456 List::List(struct ftdi_device_list* devlist)
00457         : d( new Private(devlist) )
00458 {
00459     if (devlist != 0)
00460     {
00461         // Iterate list
00462         for (; devlist != 0; devlist = devlist->next)
00463         {
00464             Context c;
00465             c.set_usb_device(devlist->dev);
00466             c.get_strings();
00467             d->list.push_back(c);
00468         }
00469     }
00470 }
00471 
00472 List::~List()
00473 {
00474 }
00475 
00480 List::iterator List::begin()
00481 {
00482     return d->list.begin();
00483 }
00484 
00489 List::iterator List::end()
00490 {
00491     return d->list.end();
00492 }
00493 
00498 List::const_iterator List::begin() const
00499 {
00500     return d->list.begin();
00501 }
00502 
00507 List::const_iterator List::end() const
00508 {
00509     return d->list.end();
00510 }
00511 
00516 List::reverse_iterator List::rbegin()
00517 {
00518     return d->list.rbegin();
00519 }
00520 
00525 List::reverse_iterator List::rend()
00526 {
00527     return d->list.rend();
00528 }
00529 
00534 List::const_reverse_iterator List::rbegin() const
00535 {
00536     return d->list.rbegin();
00537 }
00538 
00543 List::const_reverse_iterator List::rend() const
00544 {
00545     return d->list.rend();
00546 
00547 }
00548 
00553 List::ListType::size_type List::size() const
00554 {
00555     return d->list.size();
00556 }
00557 
00562 bool List::empty() const
00563 {
00564     return d->list.empty();
00565 }
00566 
00572 void List::clear()
00573 {
00574     ListType().swap(d->list);
00575 
00576     // Free device list
00577     if (d->devlist)
00578     {
00579         ftdi_list_free(&d->devlist);
00580         d->devlist = 0;
00581     }
00582 }
00583 
00588 void List::push_back(const Context& element)
00589 {
00590     d->list.push_back(element);
00591 }
00592 
00597 void List::push_front(const Context& element)
00598 {
00599     d->list.push_front(element);
00600 }
00601 
00607 List::iterator List::erase(iterator pos)
00608 {
00609     return d->list.erase(pos);
00610 }
00611 
00618 List::iterator List::erase(iterator beg, iterator end)
00619 {
00620     return d->list.erase(beg, end);
00621 }
00622 
00623 List* List::find_all(Context &context, int vendor, int product)
00624 {
00625     struct ftdi_device_list* dlist = 0;
00626     ftdi_usb_find_all(context.context(), &dlist, vendor, product);
00627     return new List(dlist);
00628 }
00629 
00630 }