00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
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
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, },
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, },
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
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
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
00415
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
00434
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
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
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 }