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  */
00052 /*****************************************************************************
00053  ** Includes
00054  *****************************************************************************/
00055 
00056 #include <ftdi.h>
00057 #include <cstring>
00058 #include <ecl/command_line.hpp>
00059 
00060 /*****************************************************************************
00061  ** Using
00062  *****************************************************************************/
00063 
00064 using ecl::CmdLine;
00065 using ecl::UnlabeledValueArg;
00066 using ecl::ValueArg;
00067 using ecl::SwitchArg;
00068 using std::string;
00069 
00070 /*****************************************************************************
00071  ** Main
00072  *****************************************************************************/
00073 
00074 int main(int argc, char **argv)
00075 {
00076   const unsigned short vendor_id = 0x0403;
00077   const unsigned short product_id = 0x6001;
00078 
00079   /*********************
00080    ** Parse Command Line
00081    **********************/
00082   CmdLine cmd_line("This is used to write a new serial id string to the ftdi device.", ' ', "0.1");
00083   ValueArg<std::string> old_arg(
00084       "o", "old", "Identify the device via the old serial id (if there are multiple attached) ['unspecified'].", false,
00085       "unspecified", "string");
00086   UnlabeledValueArg<std::string> new_arg("new_id", "New serial id used to identify the device [kobuki].", false,
00087                                          "kobuki", "string");
00088   cmd_line.add(old_arg);
00089   cmd_line.add(new_arg);
00090   cmd_line.parse(argc, argv);
00091   bool using_old_id = false;
00092   string old_id;
00093   if (old_arg.getValue() != "unspecified")
00094   {
00095     using_old_id = true;
00096     old_id = old_arg.getValue();
00097   }
00098   string new_id = new_arg.getValue();
00099   std::string new_manufacturer("Yujin Robot");
00100   std::string new_product("iClebo Kobuki");
00101 
00102   /*********************
00103    ** Debug output
00104    **********************/
00105   std::cout << "Input Information" << std::endl;
00106   if (!using_old_id)
00107   {
00108     std::cout << "  Old id: unused (first device found.)" << std::endl;
00109   }
00110   else
00111   {
00112     std::cout << "  Old id: " << old_id << std::endl;
00113   }
00114   std::cout << "  New id: " << new_id << std::endl;
00115 
00116   /*********************
00117    ** Open a context
00118    **********************/
00119   struct ftdi_context ftdi;
00120   if (ftdi_init(&ftdi) < 0)
00121   {
00122     std::cerr << "ftdi_init failed" << std::endl;
00123     return EXIT_FAILURE;
00124   }
00125   if (!using_old_id)
00126   { // simply open up the first found.
00127     if (ftdi_usb_open(&ftdi, vendor_id, product_id) < 0)
00128     {
00129       std::cerr << "Couldn't find/open an ftdi device." << std::endl;
00130       return EXIT_FAILURE;
00131     }
00132   }
00133   else
00134   {
00135     if (ftdi_usb_open_desc(&ftdi, vendor_id, product_id, NULL, old_id.c_str()) < 0)
00136     {
00137       std::cerr << "Couldn't open the device with serial id string: " << old_id << std::endl;
00138       return EXIT_FAILURE;
00139     }
00140   }
00141   /*********************
00142    ** Open an Eeprom
00143    **********************/
00144   std::cout << "Eeprom Binary" << std::endl;
00145   ftdi_eeprom eeprom;
00146   unsigned char eeprom_binary[512];
00147   int result = ftdi_read_eeprom(&ftdi,eeprom_binary);
00148   int size = FTDI_DEFAULT_EEPROM_SIZE;
00149   // this never works for me
00150 //  int size = ftdi_read_eeprom_getsize(&ftdi, eeprom_binary, 512);
00151   if (size < 0)
00152   {
00153     std::cerr << "Error: Could not read the eeprom from the requested device." << std::endl;
00154     return EXIT_FAILURE;
00155   }
00156   std::cout << "  Read binary [" << size << " bytes]." << std::endl;
00157   std::cout << "  Saving binary ['eeprom.backup']" << std::endl;
00158   FILE *fp = fopen ("eeprom.backup", "wb");
00159   fwrite (&eeprom_binary, 1, size, fp);
00160   fclose (fp);
00161 
00162   std::cout << "Decoding into eeprom structure." << std::endl;
00163   // put the binary into an eeprom structure
00164   if ( ftdi_eeprom_decode(&eeprom, eeprom_binary, size) != 0 ) {
00165     std::cerr << "Error: Could not write raw binary eeprom into the eeprom structure." << std::endl;
00166     return EXIT_FAILURE;
00167   }
00168   std::cout << "    Vendor Id   : " << eeprom.vendor_id << std::endl;
00169   std::cout << "    Product Id  : " << eeprom.product_id << std::endl;
00170   std::cout << "    Self Powered: " << eeprom.self_powered << std::endl;
00171   std::cout << "    Remote Wake : " << eeprom.remote_wakeup << std::endl;
00172   std::cout << "    In Iso      : " << eeprom.in_is_isochronous << std::endl;
00173   std::cout << "    Out Iso     : " << eeprom.out_is_isochronous << std::endl;
00174   std::cout << "    Suspend     : " << eeprom.suspend_pull_downs << std::endl;
00175   std::cout << "    Use Serial  : " << eeprom.use_serial << std::endl;
00176   std::cout << "    Change Usb  : " << eeprom.change_usb_version << std::endl;
00177   std::cout << "    Usb Version : " << eeprom.usb_version << std::endl;
00178   std::cout << "    Max Power   : " << eeprom.max_power << std::endl;
00179   std::cout << "    Manufacturer: " << eeprom.manufacturer << std::endl;
00180   std::cout << "    Product     : " << eeprom.product << std::endl;
00181   std::cout << "    Serial Id   : " << eeprom.serial << std::endl;
00182   if ( eeprom.chip_type == TYPE_R ) {
00183     std::cout << "    Chip Type   : TYPE_R" << std::endl;
00184   } else {
00185     std::cout << "    Chip Type   : " << eeprom.chip_type << std::endl;
00186   }
00187   // Looks like the eeprom structure gets TYPE_AM (0)...if we reprogram with
00188   // that, for some reason the chip fails. Guesses: maybe this variable is
00189   // like the size variable (below), it isn't stored in the eeprom and
00190   // we have to manually set it before flashing.
00191   eeprom.chip_type = TYPE_R;
00192 
00193 //  std::cout << "    Invert      : " << eeprom.invert << std::endl;
00194 
00195   new_id = new_id + "_" + std::string(eeprom.serial);
00196 
00197   // The size is not stored in the eeprom on the chip itself...rather this
00198   // variable is used when passing eeprom_binary to the ftdi_eeprom_build command.
00199   eeprom.size = size;
00200   std::cout << "    Size        : " << eeprom.size << std::endl;
00201   std::cout << "  New serial    : " << new_id << "." << std::endl;
00202   std::cout << "  New manufact. : " << new_manufacturer << "." << std::endl;
00203   std::cout << "  New product   : " << new_product << "." << std::endl;
00204   std::cout << "  New chip type : TYPE_R." << std::endl;
00205   free(eeprom.serial);
00206   eeprom.serial = (char*)malloc(new_id.size() + 1);
00207   std::strcpy(eeprom.serial, new_id.c_str());
00208   free(eeprom.manufacturer);
00209   eeprom.manufacturer = (char*)malloc(new_manufacturer.size() + 1);
00210   std::strcpy(eeprom.manufacturer, new_manufacturer.c_str());
00211   free(eeprom.product);
00212   eeprom.product = (char*)malloc(new_product.size() + 1);
00213   std::strcpy(eeprom.product, new_product.c_str());
00214 
00215   std::cout << "Building new eeprom binary." << std::endl;
00216   int eeprom_binary_length = ftdi_eeprom_build(&eeprom, eeprom_binary);
00217   if (eeprom_binary_length == -1)
00218   {
00219     std::cerr << "Eeprom binary exceeded 128 bytes, reduce the size of your strings." << std::endl;
00220     return EXIT_FAILURE;
00221   }
00222   else if (eeprom_binary_length == -2)
00223   {
00224     std::cerr << "Eeprom structure not valid." << std::endl;
00225     return EXIT_FAILURE;
00226   }
00227 //  std::cout << "  Saving binary ['eeprom.req.after']" << std::endl;
00228 //  fp = fopen ("eeprom.req.after", "wb");
00229 //  fwrite (&eeprom_binary, 1, size, fp);
00230 //  fclose (fp);
00231 
00232   std::cout << "  Flashing binary." << std::endl;
00233   result = ftdi_write_eeprom(&ftdi, eeprom_binary);
00234   if (result < 0)
00235   {
00236     std::cerr << "  Could not rewrite the eeprom." << std::endl;
00237     return EXIT_FAILURE;
00238   } else {
00239     std::cout << "  Flashed " << result << " bytes" << std::endl;
00240   }
00241   std::cout << "Done." << std::endl;
00242 
00243   return 0;
00244 }
00245 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Defines


kobuki_udev
Author(s): Daniel Stonier
autogenerated on Thu Nov 22 2012 19:34:17