Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2010, Mariano Alvira <mar@devl.org> and other contributors 00003 * to the MC1322x project (http://mc1322x.devl.org) 00004 * All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 1. Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * 2. Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * 3. Neither the name of the Institute nor the names of its contributors 00015 * may be used to endorse or promote products derived from this software 00016 * without specific prior written permission. 00017 * 00018 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00019 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00021 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00022 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00023 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00024 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00025 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00026 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00027 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00028 * SUCH DAMAGE. 00029 * 00030 * This file is part of libmc1322x: see http://mc1322x.devl.org 00031 * for details. 00032 * 00033 * 00034 */ 00035 00036 /* control reset and VREF2 lines */ 00037 00038 #include <stdio.h> 00039 #include <string.h> 00040 #include <stdint.h> 00041 #include <getopt.h> 00042 #include <ftdi.h> 00043 00044 #define DEBUG 0 00045 00046 #define low(x) (1 << x) 00047 #define high(x) (1 << (x + 8)) 00048 00049 #define REDBEE_ECONOTAG_RESET high(2) 00050 #define REDBEE_ECONOTAG_VREF2L high(7) 00051 #define REDBEE_ECONOTAG_VREF2H high(6) 00052 #define REDBEE_ECONOTAG_INTERFACE INTERFACE_A 00053 00054 #define REDBEE_USB_RESET high(2) 00055 #define REDBEE_USB_VREF2L low(5) 00056 #define REDBEE_USB_VREF2H low(6) 00057 #define REDBEE_USB_INTERFACE INTERFACE_B 00058 00059 #define BOARD REDBEE_USB 00060 00061 #define STR(x) #x 00062 #define STR2(x) STR(x) 00063 #define CAT(x,y) x##y 00064 #define CAT2(x, y, z) x##y##z 00065 00066 #define dir(x) ( CAT(x,_RESET) | CAT(x,_VREF2L) | CAT(x,_VREF2H)) 00067 #define interface(x) ( CAT(x,_INTERFACE) ) 00068 #define reset_release(x) ( CAT(x,_RESET) ) 00069 #define reset_set(x) ( 0 ) 00070 #define vref2_normal(x) ( CAT(x,_VREF2H) ) 00071 #define vref2_erase(x) ( CAT(x,_VREF2L) ) 00072 00073 /* fgets input buffer length: for prompts and such */ 00074 #define BUF_LEN 32 00075 00076 struct layout { 00077 char *name; 00078 char *desc; 00079 enum ftdi_interface interface; 00080 uint16_t dir; 00081 uint16_t reset_release; 00082 uint16_t reset_set; 00083 uint16_t vref2_normal; 00084 uint16_t vref2_erase; 00085 }; 00086 00087 int print_and_prompt( struct ftdi_device_list *devlist ); 00088 int bb_mpsee(struct ftdi_context *ftdic, uint16_t dir, uint16_t val); 00089 void reset(struct ftdi_context *ftdic, const struct layout * l); 00090 void erase(struct ftdi_context *ftdic, const struct layout * l); 00091 void usage(void); 00092 00093 #define std_layout(x) \ 00094 .interface = interface(x), \ 00095 .dir = dir(x), \ 00096 .reset_release = reset_release(x), \ 00097 .reset_set = reset_set(x), \ 00098 .vref2_normal = vref2_normal(x), \ 00099 .vref2_erase = vref2_erase(x), 00100 00101 static struct layout layouts[] = 00102 { 00103 { .name = "redbee-econotag", 00104 .desc = "Redbee Econotag", 00105 std_layout(REDBEE_ECONOTAG) 00106 }, 00107 { .name = "redbee-usb", 00108 .desc = "Redbee USB stick", 00109 std_layout(REDBEE_USB) 00110 }, 00111 { .name = NULL, /* end of table */ }, 00112 }; 00113 00114 struct command { 00115 char *name; 00116 char *desc; 00117 void (*cmd)(struct ftdi_context *ftdic, const struct layout * l); 00118 }; 00119 00120 static const struct command commands[] = 00121 { 00122 { 00123 .name = "reset", 00124 .desc = "Toggles reset pin", 00125 .cmd = reset, 00126 }, 00127 { 00128 .name = "erase", 00129 .desc = "Sets VREF2 erase mode; toggles reset; waits 2 sec.; sets normal; toggles reset again", 00130 .cmd = erase, 00131 }, 00132 { .name = NULL, /* end of table */ }, 00133 }; 00134 00135 struct layout * find_layout(char * str) 00136 { 00137 uint32_t i = 0; 00138 00139 while(layouts[i].name != NULL) { 00140 if(strcmp(layouts[i].name, str) == 0) { return &layouts[i]; } 00141 i++; 00142 } 00143 00144 return NULL; 00145 } 00146 00147 static uint32_t vendid = 0x0403; uint32_t prodid = 0x6010; 00148 00149 int main(int argc, char **argv) 00150 { 00151 struct ftdi_context ftdic; 00152 struct ftdi_device_list *devlist; 00153 int dev_index = -1; int num_devs; 00154 char layout_str[BUF_LEN]; 00155 struct layout layout; 00156 struct layout *l = NULL; 00157 int i, ret; 00158 00159 /* overrides for layout parameters */ 00160 int interface = -1; 00161 int dir = -1; 00162 int reset_release = -1; 00163 int reset_set = -1; 00164 int vref2_normal = -1; 00165 int vref2_erase = -1; 00166 00167 layout.name = NULL; 00168 00169 while (1) { 00170 int c; 00171 int option_index = 0; 00172 static struct option long_options[] = { 00173 {"layout", required_argument, 0, 'l'}, 00174 {"index", required_argument, 0, 'i'}, 00175 {"vendor", required_argument, 0, 'v'}, 00176 {"product", required_argument, 0, 'p'}, 00177 {"dir", required_argument, 0, 0 }, 00178 {"reset_release", required_argument, 0, 0 }, 00179 {"reset_set", required_argument, 0, 0 }, 00180 {"vref2_normal", required_argument, 0, 0 }, 00181 {"vref2_erase", required_argument, 0, 0 }, 00182 {"interface", required_argument, 0, 0 }, 00183 {"help", no_argument, 0, '?'}, 00184 {0, 0, 0, 0} 00185 }; 00186 00187 c = getopt_long (argc, argv, "i:l:v:p:", 00188 long_options, &option_index); 00189 if (c == -1) 00190 break; 00191 00192 switch (c) { 00193 /* process long opts */ 00194 case 0: 00195 if(strcmp(long_options[option_index].name, "interface") == 0) { 00196 sscanf(optarg, "%i", &interface); 00197 } 00198 if(strcmp(long_options[option_index].name, "dir") == 0) { 00199 sscanf(optarg, "%i", &dir); 00200 } 00201 if (strcmp(long_options[option_index].name, "reset_release") == 0) { 00202 sscanf(optarg, "%i", &reset_release); 00203 } 00204 if (strcmp(long_options[option_index].name, "reset_set") == 0) { 00205 sscanf(optarg, "%i", &reset_set); 00206 } 00207 if (strcmp(long_options[option_index].name, "vref2_normal") == 0) { 00208 sscanf(optarg, "%i", &vref2_normal); 00209 } 00210 if (strcmp(long_options[option_index].name, "vref2_erase") == 0) { 00211 sscanf(optarg, "%i", &vref2_erase); 00212 } 00213 break; 00214 00215 case 'l': 00216 strncpy(layout_str, optarg, BUF_LEN); 00217 break; 00218 case 'i': 00219 dev_index = atoi(optarg); 00220 break; 00221 case 'v': 00222 sscanf(optarg, "%i", &vendid); 00223 break; 00224 case 'p': 00225 sscanf(optarg, "%i", &prodid); 00226 break; 00227 default: 00228 usage(); 00229 break; 00230 } 00231 } 00232 00233 if( !(l = find_layout(layout_str)) && 00234 !((interface >= 0) && 00235 (dir >= 0) && 00236 (reset_release >= 0) && 00237 (reset_set >= 0) && 00238 (vref2_normal >= 0) && 00239 (vref2_erase >= 0)) 00240 ) { 00241 00242 printf("*** You must specify a layout or a complete set of overrides\n"); 00243 return EXIT_FAILURE; 00244 } 00245 00246 if(l) { 00247 memcpy(&layout, l, sizeof(struct layout)); 00248 } 00249 00250 #define override(x) if(x > 0) { layout.x = x; } 00251 override(interface); 00252 override(dir); 00253 override(reset_release); override(reset_set); 00254 override(vref2_normal); override(vref2_erase); 00255 00256 if ((num_devs = ftdi_usb_find_all(&ftdic, &devlist, vendid, prodid)) < 0) 00257 { 00258 fprintf(stderr, "ftdi_usb_find_all failed: %d (%s)\n", 00259 num_devs, 00260 ftdi_get_error_string(&ftdic)); 00261 return EXIT_FAILURE; 00262 } 00263 00264 if (ftdi_init(&ftdic) < 0) 00265 { 00266 fprintf(stderr, "ftdi_init failed\n"); 00267 return EXIT_FAILURE; 00268 } 00269 00270 if (ftdi_set_interface(&ftdic, layout.interface) < 0) { 00271 fprintf(stderr, "couldn't set interface %d\n", layout.interface); 00272 return EXIT_FAILURE; 00273 } 00274 00275 printf("Found %d devices with vendor id 0x%04x product id 0x%04x\n", 00276 num_devs, vendid, prodid); 00277 00278 if(num_devs == 0) { return EXIT_SUCCESS; } 00279 00280 if(num_devs == 1) { dev_index = 0; } 00281 while( (dev_index < 0) || (dev_index >= num_devs)){ 00282 dev_index = print_and_prompt(devlist); 00283 } 00284 00285 if(layout.name != NULL) { 00286 printf("Opening device %d interface %d using layout %s\n", 00287 dev_index, layout.interface, layout.name); 00288 } else { 00289 printf("Opening device %d interface %d without a layout.\n", 00290 dev_index, layout.interface); 00291 } 00292 00293 if( (ret = ftdi_usb_open_desc_index( 00294 &ftdic, 00295 vendid, 00296 prodid, 00297 NULL, 00298 NULL, 00299 dev_index)) < 0) { 00300 fprintf(stderr, "couldn't open dev_index %d\n", dev_index); 00301 return EXIT_FAILURE; 00302 } 00303 00304 00305 for(i = 0; commands[i].name != NULL; i++) { 00306 if( (argv[optind] != NULL) && 00307 (strcmp(commands[i].name, argv[optind]) == 0)) { break; } 00308 } 00309 if(commands[i].name != NULL) { 00310 commands[i].cmd(&ftdic, &layout); 00311 } else { 00312 printf("invalid command\n"); 00313 00314 ftdi_list_free(&devlist); 00315 ftdi_deinit(&ftdic); 00316 00317 return EXIT_FAILURE; 00318 } 00319 00320 printf("done.\n"); 00321 00322 ftdi_list_free(&devlist); 00323 ftdi_deinit(&ftdic); 00324 00325 return EXIT_SUCCESS; 00326 } 00327 00328 void usage(void) 00329 { 00330 int i; 00331 printf( "Usage: bbmc [options|overrides] -l|--layout layout command \n"); 00332 printf( "Commands:\n"); 00333 for(i = 0; commands[i].name != NULL; i++) { 00334 printf( " %s: %s\n", commands[i].name, commands[i].desc); 00335 } 00336 printf("\n"); 00337 printf( "Required options:\n"); 00338 printf( " -l|--layout\t specifiy which board layout to use\n"); 00339 printf( " \t layout is not necessary with a full\n"); 00340 printf( " \t set of overrides\n"); 00341 printf( "\nLayout overrides:\n"); 00342 printf( " --interface\t\t FTDI interface to use\n"); 00343 printf( " --dir\t\t direction (1 is output)\n"); 00344 printf( " --reset_release\t reset release command\n"); 00345 printf( " --reset_set\t\t reset set command\n"); 00346 printf( " --vref2_normal\t vref2 normal\n"); 00347 printf( " --vref2_erase\t vref2 erase\n"); 00348 printf("\n"); 00349 printf( "Layouts:\n"); 00350 for(i = 0; layouts[i].name != NULL; i++) { 00351 printf( "\t%s: %s\n", layouts[i].name, layouts[i].desc); 00352 printf("\n"); 00353 printf( "\t\tinterface: \t0x%04x\n", layouts[i].interface); 00354 printf( "\t\tdir: \t\t0x%04x\n", layouts[i].dir); 00355 printf( "\t\treset release: \t0x%04x\n", layouts[i].reset_release); 00356 printf( "\t\treset hold: \t0x%04x\n", layouts[i].reset_set); 00357 printf( "\t\tvref2 normal: \t0x%04x\n", layouts[i].vref2_normal); 00358 printf( "\t\tvref2 erase: \t0x%04x\n", layouts[i].vref2_erase); 00359 printf("\n"); 00360 } 00361 printf("\n"); 00362 printf( "Options:\n"); 00363 printf( " -i|--index specifiy which device to use (default 0)\n"); 00364 printf( " -v|--vendor set vendor id (default 0x0403)\n"); 00365 printf( " -p|--product set vendor id (default 0x6010)\n"); 00366 } 00367 00368 int print_and_prompt( struct ftdi_device_list *devlist ) 00369 { 00370 int i, ret; 00371 struct ftdi_context ftdic; 00372 struct ftdi_device_list *curdev; 00373 char manufacturer[128], description[128], serial[128]; 00374 char input[BUF_LEN]; char *s; 00375 int sel = -1; 00376 00377 printf("\n"); 00378 00379 i = 0; 00380 for (curdev = devlist; curdev != NULL; i++) 00381 { 00382 printf(" [%d] ", i); 00383 if (0 > (ret = ftdi_usb_get_strings(&ftdic, 00384 curdev->dev, 00385 manufacturer, 128, 00386 description, 128, 00387 serial, 128))) 00388 { 00389 fprintf(stderr, "ftdi_usb_get_strings failed: %d (%s)\n", 00390 ret, ftdi_get_error_string(&ftdic)); 00391 return EXIT_FAILURE; 00392 } 00393 printf("Manufacturer: %s, Description: %s, Serial %s\n", 00394 manufacturer, description, serial); 00395 curdev = curdev->next; 00396 } 00397 00398 printf("\nUse which device? "); 00399 00400 s = fgets(input, BUF_LEN, stdin); 00401 if (s != NULL) { 00402 size_t last = strlen (input) - 1; 00403 if (input[last] == '\n') input[last] = '\0'; 00404 } 00405 00406 sscanf(s, "%i",&sel); 00407 00408 return sel; 00409 } 00410 00411 void reset(struct ftdi_context *ftdic, const struct layout * l) 00412 { 00413 00414 /* using MPSSE since it give access to high GPIO*/ 00415 /* set as inputs for now */ 00416 ftdi_set_bitmode(ftdic, 0 , BITMODE_MPSSE); 00417 00418 printf("toggle reset\n"); 00419 00420 bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_normal)); 00421 bb_mpsee(ftdic, l->dir, (l->reset_set | l->vref2_normal)); 00422 bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_normal)); 00423 00424 return; 00425 00426 } 00427 00428 00429 void erase(struct ftdi_context *ftdic, const struct layout * l) 00430 { 00431 printf("setting VREF2 erase\n"); 00432 00433 /* using MPSSE since it give access to high GPIO*/ 00434 /* set as inputs for now */ 00435 ftdi_set_bitmode(ftdic, 0 , BITMODE_MPSSE); 00436 00437 bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_normal)); 00438 bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_erase)); 00439 00440 printf("toggle reset\n"); 00441 00442 bb_mpsee(ftdic, l->dir, (l->reset_set | l->vref2_erase)); 00443 bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_erase)); 00444 00445 printf("waiting for erase\n"); 00446 00447 sleep(2); 00448 00449 printf("setting VREF2 normal\n"); 00450 00451 bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_normal)); 00452 00453 reset(ftdic, l); 00454 00455 return; 00456 00457 } 00458 00459 00460 int bb_mpsee(struct ftdi_context *ftdic, uint16_t dir, uint16_t val) 00461 { 00462 uint8_t buf[3]; 00463 int ret; 00464 00465 /* command "set data bits low byte" */ 00466 buf[0] = 0x80; 00467 buf[1] = (val & 0xff); 00468 buf[2] = dir & 0xff; 00469 #if DEBUG 00470 fprintf(stderr,"write %x %x %x\n",buf[0],buf[1],buf[2]); 00471 #endif 00472 00473 if ((ret = (ftdi_write_data(ftdic, buf, 3))) < 0) 00474 { 00475 perror("ft2232_write error"); 00476 fprintf(stderr, "ft2232_write command %x\n", buf[0]); 00477 return EXIT_FAILURE; 00478 } 00479 00480 00481 /* command "set data bits high byte" */ 00482 buf[0] = 0x82; 00483 buf[1] = (val >> 8); 00484 buf[2] = dir >> 8; 00485 #if DEBUG 00486 fprintf(stderr,"write %x %x %x\n",buf[0],buf[1],buf[2]); 00487 #endif 00488 00489 if ((ret = (ftdi_write_data(ftdic, buf, 3))) < 0) 00490 { 00491 perror("ft2232_write error"); 00492 fprintf(stderr, "ft2232_write command %x\n", buf[0]); 00493 return EXIT_FAILURE; 00494 } 00495 00496 return 0; 00497 00498 }