ftdi_kobuki.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2012, Yujin Robot.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of Yujin Robot nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00056 /*****************************************************************************
00057  ** Includes
00058  *****************************************************************************/
00059 
00060 #include <ftdi.h>
00061 #include <cstring>
00062 #include <ecl/command_line.hpp>
00063 
00064 /*****************************************************************************
00065  ** Using
00066  *****************************************************************************/
00067 
00068 using ecl::CmdLine;
00069 using ecl::UnlabeledValueArg;
00070 using ecl::ValueArg;
00071 using ecl::SwitchArg;
00072 using std::string;
00073 
00074 /*****************************************************************************
00075  ** Main
00076  *****************************************************************************/
00077 
00078 int main(int argc, char **argv)
00079 {
00080   const unsigned short vendor_id = 0x0403;
00081   const unsigned short product_id = 0x6001;
00082 
00083   /*********************
00084    ** Parse Command Line
00085    **********************/
00086   CmdLine cmd_line("This is used to write a new serial id string to the ftdi device.", ' ', "0.1");
00087   ValueArg<std::string> old_arg(
00088       "o", "old", "Identify the device via the old serial id (if there are multiple attached) ['unspecified'].", false,
00089       "unspecified", "string");
00090   UnlabeledValueArg<std::string> new_arg("new_id", "New serial id used to identify the device [kobuki].", false,
00091                                          "kobuki", "string");
00092   cmd_line.add(old_arg);
00093   cmd_line.add(new_arg);
00094   cmd_line.parse(argc, argv);
00095   bool using_old_id = false;
00096   string old_id;
00097   if (old_arg.getValue() != "unspecified")
00098   {
00099     using_old_id = true;
00100     old_id = old_arg.getValue();
00101   }
00102   string new_id = new_arg.getValue();
00103   std::string new_manufacturer("Yujin Robot");
00104   std::string new_product("iClebo Kobuki");
00105 
00106   /*********************
00107    ** Debug output
00108    **********************/
00109   std::cout << "Input Information" << std::endl;
00110   if (!using_old_id)
00111   {
00112     std::cout << "  Old id: unused (first device found.)" << std::endl;
00113   }
00114   else
00115   {
00116     std::cout << "  Old id: " << old_id << std::endl;
00117   }
00118   std::cout << "  New id: " << new_id << std::endl;
00119 
00120   /*********************
00121    ** Open a context
00122    **********************/
00123   struct ftdi_context ftdi;
00124   if (ftdi_init(&ftdi) < 0)
00125   {
00126     std::cerr << "ftdi_init failed" << std::endl;
00127     return EXIT_FAILURE;
00128   }
00129   if (!using_old_id)
00130   { // simply open up the first found.
00131     if (ftdi_usb_open(&ftdi, vendor_id, product_id) < 0)
00132     {
00133       std::cerr << "Couldn't find/open an ftdi device." << std::endl;
00134       return EXIT_FAILURE;
00135     }
00136   }
00137   else
00138   {
00139     if (ftdi_usb_open_desc(&ftdi, vendor_id, product_id, NULL, old_id.c_str()) < 0)
00140     {
00141       std::cerr << "Couldn't open the device with serial id string: " << old_id << std::endl;
00142       return EXIT_FAILURE;
00143     }
00144   }
00145   /*********************
00146    ** Open an Eeprom
00147    **********************/
00148   std::cout << "Eeprom Binary" << std::endl;
00149   ftdi_eeprom eeprom;
00150   unsigned char eeprom_binary[512];
00151   int result = ftdi_read_eeprom(&ftdi,eeprom_binary);
00152   int size = FTDI_DEFAULT_EEPROM_SIZE;
00153   // this never works for me
00154 //  int size = ftdi_read_eeprom_getsize(&ftdi, eeprom_binary, 512);
00155   if (size < 0)
00156   {
00157     std::cerr << "Error: Could not read the eeprom from the requested device." << std::endl;
00158     return EXIT_FAILURE;
00159   }
00160   std::cout << "  Read binary [" << size << " bytes]." << std::endl;
00161   std::cout << "  Saving binary ['eeprom.backup']" << std::endl;
00162   FILE *fp = fopen ("eeprom.backup", "wb");
00163   fwrite (&eeprom_binary, 1, size, fp);
00164   fclose (fp);
00165 
00166   std::cout << "Decoding into eeprom structure." << std::endl;
00167   // put the binary into an eeprom structure
00168   if ( ftdi_eeprom_decode(&eeprom, eeprom_binary, size) != 0 ) {
00169     std::cerr << "Error: Could not write raw binary eeprom into the eeprom structure." << std::endl;
00170     return EXIT_FAILURE;
00171   }
00172   std::cout << "    Vendor Id   : " << eeprom.vendor_id << std::endl;
00173   std::cout << "    Product Id  : " << eeprom.product_id << std::endl;
00174   std::cout << "    Self Powered: " << eeprom.self_powered << std::endl;
00175   std::cout << "    Remote Wake : " << eeprom.remote_wakeup << std::endl;
00176   std::cout << "    In Iso      : " << eeprom.in_is_isochronous << std::endl;
00177   std::cout << "    Out Iso     : " << eeprom.out_is_isochronous << std::endl;
00178   std::cout << "    Suspend     : " << eeprom.suspend_pull_downs << std::endl;
00179   std::cout << "    Use Serial  : " << eeprom.use_serial << std::endl;
00180   std::cout << "    Change Usb  : " << eeprom.change_usb_version << std::endl;
00181   std::cout << "    Usb Version : " << eeprom.usb_version << std::endl;
00182   std::cout << "    Max Power   : " << eeprom.max_power << std::endl;
00183   std::cout << "    Manufacturer: " << eeprom.manufacturer << std::endl;
00184   std::cout << "    Product     : " << eeprom.product << std::endl;
00185   std::cout << "    Serial Id   : " << eeprom.serial << std::endl;
00186   if ( eeprom.chip_type == TYPE_R ) {
00187     std::cout << "    Chip Type   : TYPE_R" << std::endl;
00188   } else {
00189     std::cout << "    Chip Type   : " << eeprom.chip_type << std::endl;
00190   }
00191   // Looks like the eeprom structure gets TYPE_AM (0)...if we reprogram with
00192   // that, for some reason the chip fails. Guesses: maybe this variable is
00193   // like the size variable (below), it isn't stored in the eeprom and
00194   // we have to manually set it before flashing.
00195   eeprom.chip_type = TYPE_R;
00196 
00197 //  std::cout << "    Invert      : " << eeprom.invert << std::endl;
00198 
00199   new_id = new_id + "_" + std::string(eeprom.serial);
00200 
00201   // The size is not stored in the eeprom on the chip itself...rather this
00202   // variable is used when passing eeprom_binary to the ftdi_eeprom_build command.
00203   eeprom.size = size;
00204   std::cout << "    Size        : " << eeprom.size << std::endl;
00205   std::cout << "  New serial    : " << new_id << "." << std::endl;
00206   std::cout << "  New manufact. : " << new_manufacturer << "." << std::endl;
00207   std::cout << "  New product   : " << new_product << "." << std::endl;
00208   std::cout << "  New chip type : TYPE_R." << std::endl;
00209   free(eeprom.serial);
00210   eeprom.serial = (char*)malloc(new_id.size() + 1);
00211   std::strcpy(eeprom.serial, new_id.c_str());
00212   free(eeprom.manufacturer);
00213   eeprom.manufacturer = (char*)malloc(new_manufacturer.size() + 1);
00214   std::strcpy(eeprom.manufacturer, new_manufacturer.c_str());
00215   free(eeprom.product);
00216   eeprom.product = (char*)malloc(new_product.size() + 1);
00217   std::strcpy(eeprom.product, new_product.c_str());
00218 
00219   std::cout << "Building new eeprom binary." << std::endl;
00220   int eeprom_binary_length = ftdi_eeprom_build(&eeprom, eeprom_binary);
00221   if (eeprom_binary_length == -1)
00222   {
00223     std::cerr << "Eeprom binary exceeded 128 bytes, reduce the size of your strings." << std::endl;
00224     return EXIT_FAILURE;
00225   }
00226   else if (eeprom_binary_length == -2)
00227   {
00228     std::cerr << "Eeprom structure not valid." << std::endl;
00229     return EXIT_FAILURE;
00230   }
00231 //  std::cout << "  Saving binary ['eeprom.req.after']" << std::endl;
00232 //  fp = fopen ("eeprom.req.after", "wb");
00233 //  fwrite (&eeprom_binary, 1, size, fp);
00234 //  fclose (fp);
00235 
00236   std::cout << "  Flashing binary." << std::endl;
00237   result = ftdi_write_eeprom(&ftdi, eeprom_binary);
00238   if (result < 0)
00239   {
00240     std::cerr << "  Could not rewrite the eeprom." << std::endl;
00241     return EXIT_FAILURE;
00242   } else {
00243     std::cout << "  Flashed " << result << " bytes" << std::endl;
00244   }
00245   std::cout << "Done." << std::endl;
00246 
00247   return 0;
00248 }
00249 


kobuki_ftdi
Author(s): Younghun Ju
autogenerated on Thu Jun 6 2019 20:24:42