ftdi_kobuki.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, Yujin Robot.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of Yujin Robot nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
56 /*****************************************************************************
57  ** Includes
58  *****************************************************************************/
59 
60 #include <ftdi.h>
61 #include <cstring>
62 #include <ecl/command_line.hpp>
63 
64 /*****************************************************************************
65  ** Using
66  *****************************************************************************/
67 
68 using ecl::CmdLine;
70 using ecl::ValueArg;
71 using ecl::SwitchArg;
72 using std::string;
73 
74 /*****************************************************************************
75  ** Main
76  *****************************************************************************/
77 
78 int main(int argc, char **argv)
79 {
80  const unsigned short vendor_id = 0x0403;
81  const unsigned short product_id = 0x6001;
82 
83  /*********************
84  ** Parse Command Line
85  **********************/
86  CmdLine cmd_line("This is used to write a new serial id string to the ftdi device.", ' ', "0.1");
87  ValueArg<std::string> old_arg(
88  "o", "old", "Identify the device via the old serial id (if there are multiple attached) ['unspecified'].", false,
89  "unspecified", "string");
90  UnlabeledValueArg<std::string> new_arg("new_id", "New serial id used to identify the device [kobuki].", false,
91  "kobuki", "string");
92  cmd_line.add(old_arg);
93  cmd_line.add(new_arg);
94  cmd_line.parse(argc, argv);
95  bool using_old_id = false;
96  string old_id;
97  if (old_arg.getValue() != "unspecified")
98  {
99  using_old_id = true;
100  old_id = old_arg.getValue();
101  }
102  string new_id = new_arg.getValue();
103  std::string new_manufacturer("Yujin Robot");
104  std::string new_product("iClebo Kobuki");
105 
106  /*********************
107  ** Debug output
108  **********************/
109  std::cout << "Input Information" << std::endl;
110  if (!using_old_id)
111  {
112  std::cout << " Old id: unused (first device found.)" << std::endl;
113  }
114  else
115  {
116  std::cout << " Old id: " << old_id << std::endl;
117  }
118  std::cout << " New id: " << new_id << std::endl;
119 
120  /*********************
121  ** Open a context
122  **********************/
123  struct ftdi_context ftdi;
124  if (ftdi_init(&ftdi) < 0)
125  {
126  std::cerr << "ftdi_init failed" << std::endl;
127  return EXIT_FAILURE;
128  }
129  if (!using_old_id)
130  { // simply open up the first found.
131  if (ftdi_usb_open(&ftdi, vendor_id, product_id) < 0)
132  {
133  std::cerr << "Couldn't find/open an ftdi device." << std::endl;
134  return EXIT_FAILURE;
135  }
136  }
137  else
138  {
139  if (ftdi_usb_open_desc(&ftdi, vendor_id, product_id, NULL, old_id.c_str()) < 0)
140  {
141  std::cerr << "Couldn't open the device with serial id string: " << old_id << std::endl;
142  return EXIT_FAILURE;
143  }
144  }
145  /*********************
146  ** Open an Eeprom
147  **********************/
148  std::cout << "Eeprom Binary" << std::endl;
149  ftdi_eeprom eeprom;
150  unsigned char eeprom_binary[512];
151  int result = ftdi_read_eeprom(&ftdi,eeprom_binary);
152  int size = FTDI_DEFAULT_EEPROM_SIZE;
153  // this never works for me
154 // int size = ftdi_read_eeprom_getsize(&ftdi, eeprom_binary, 512);
155  if (size < 0)
156  {
157  std::cerr << "Error: Could not read the eeprom from the requested device." << std::endl;
158  return EXIT_FAILURE;
159  }
160  std::cout << " Read binary [" << size << " bytes]." << std::endl;
161  std::cout << " Saving binary ['eeprom.backup']" << std::endl;
162  FILE *fp = fopen ("eeprom.backup", "wb");
163  fwrite (&eeprom_binary, 1, size, fp);
164  fclose (fp);
165 
166  std::cout << "Decoding into eeprom structure." << std::endl;
167  // put the binary into an eeprom structure
168  if ( ftdi_eeprom_decode(&eeprom, eeprom_binary, size) != 0 ) {
169  std::cerr << "Error: Could not write raw binary eeprom into the eeprom structure." << std::endl;
170  return EXIT_FAILURE;
171  }
172  std::cout << " Vendor Id : " << eeprom.vendor_id << std::endl;
173  std::cout << " Product Id : " << eeprom.product_id << std::endl;
174  std::cout << " Self Powered: " << eeprom.self_powered << std::endl;
175  std::cout << " Remote Wake : " << eeprom.remote_wakeup << std::endl;
176  std::cout << " In Iso : " << eeprom.in_is_isochronous << std::endl;
177  std::cout << " Out Iso : " << eeprom.out_is_isochronous << std::endl;
178  std::cout << " Suspend : " << eeprom.suspend_pull_downs << std::endl;
179  std::cout << " Use Serial : " << eeprom.use_serial << std::endl;
180  std::cout << " Change Usb : " << eeprom.change_usb_version << std::endl;
181  std::cout << " Usb Version : " << eeprom.usb_version << std::endl;
182  std::cout << " Max Power : " << eeprom.max_power << std::endl;
183  std::cout << " Manufacturer: " << eeprom.manufacturer << std::endl;
184  std::cout << " Product : " << eeprom.product << std::endl;
185  std::cout << " Serial Id : " << eeprom.serial << std::endl;
186  if ( eeprom.chip_type == TYPE_R ) {
187  std::cout << " Chip Type : TYPE_R" << std::endl;
188  } else {
189  std::cout << " Chip Type : " << eeprom.chip_type << std::endl;
190  }
191  // Looks like the eeprom structure gets TYPE_AM (0)...if we reprogram with
192  // that, for some reason the chip fails. Guesses: maybe this variable is
193  // like the size variable (below), it isn't stored in the eeprom and
194  // we have to manually set it before flashing.
195  eeprom.chip_type = TYPE_R;
196 
197 // std::cout << " Invert : " << eeprom.invert << std::endl;
198 
199  new_id = new_id + "_" + std::string(eeprom.serial);
200 
201  // The size is not stored in the eeprom on the chip itself...rather this
202  // variable is used when passing eeprom_binary to the ftdi_eeprom_build command.
203  eeprom.size = size;
204  std::cout << " Size : " << eeprom.size << std::endl;
205  std::cout << " New serial : " << new_id << "." << std::endl;
206  std::cout << " New manufact. : " << new_manufacturer << "." << std::endl;
207  std::cout << " New product : " << new_product << "." << std::endl;
208  std::cout << " New chip type : TYPE_R." << std::endl;
209  free(eeprom.serial);
210  eeprom.serial = (char*)malloc(new_id.size() + 1);
211  std::strcpy(eeprom.serial, new_id.c_str());
212  free(eeprom.manufacturer);
213  eeprom.manufacturer = (char*)malloc(new_manufacturer.size() + 1);
214  std::strcpy(eeprom.manufacturer, new_manufacturer.c_str());
215  free(eeprom.product);
216  eeprom.product = (char*)malloc(new_product.size() + 1);
217  std::strcpy(eeprom.product, new_product.c_str());
218 
219  std::cout << "Building new eeprom binary." << std::endl;
220  int eeprom_binary_length = ftdi_eeprom_build(&eeprom, eeprom_binary);
221  if (eeprom_binary_length == -1)
222  {
223  std::cerr << "Eeprom binary exceeded 128 bytes, reduce the size of your strings." << std::endl;
224  return EXIT_FAILURE;
225  }
226  else if (eeprom_binary_length == -2)
227  {
228  std::cerr << "Eeprom structure not valid." << std::endl;
229  return EXIT_FAILURE;
230  }
231 // std::cout << " Saving binary ['eeprom.req.after']" << std::endl;
232 // fp = fopen ("eeprom.req.after", "wb");
233 // fwrite (&eeprom_binary, 1, size, fp);
234 // fclose (fp);
235 
236  std::cout << " Flashing binary." << std::endl;
237  result = ftdi_write_eeprom(&ftdi, eeprom_binary);
238  if (result < 0)
239  {
240  std::cerr << " Could not rewrite the eeprom." << std::endl;
241  return EXIT_FAILURE;
242  } else {
243  std::cout << " Flashed " << result << " bytes" << std::endl;
244  }
245  std::cout << "Done." << std::endl;
246 
247  return 0;
248 }
249 
command_line.hpp
ecl::CmdLine
ecl::ValueArg::getValue
T & getValue()
ecl::CmdLine::add
void add(Arg &a)
main
int main(int argc, char **argv)
Definition: ftdi_kobuki.cpp:78
ecl::SwitchArg
ecl::ValueArg
ecl::UnlabeledValueArg
ecl::CmdLine::parse
void parse(int argc, char **argv)


kobuki_ftdi
Author(s): Younghun Ju
autogenerated on Wed Mar 2 2022 00:26:19