bbmc.c

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 }

Generated on Mon Apr 11 14:23:39 2011 for Contiki 2.5 by  doxygen 1.6.1