Contiki 3.x
bbmc.c
1 /*
2  * Copyright (c) 2010, Mariano Alvira <mar@devl.org> and other contributors
3  * to the MC1322x project (http://mc1322x.devl.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the Institute nor the names of its contributors
15  * may be used to endorse or promote products derived from this software
16  * without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * This file is part of libmc1322x: see http://mc1322x.devl.org
31  * for details.
32  *
33  *
34  */
35 
36 /* control reset and VREF2 lines */
37 
38 #include <stdio.h>
39 #include <string.h>
40 #include <stdint.h>
41 #include <getopt.h>
42 #include <ftdi.h>
43 
44 #define DEBUG 0
45 
46 #define low(x) (1 << x)
47 #define high(x) (1 << (x + 8))
48 
49 #define REDBEE_ECONOTAG_RESET high(2)
50 #define REDBEE_ECONOTAG_VREF2L high(7)
51 #define REDBEE_ECONOTAG_VREF2H high(6)
52 #define REDBEE_ECONOTAG_INTERFACE INTERFACE_A
53 
54 #define REDBEE_USB_RESET high(2)
55 #define REDBEE_USB_VREF2L low(5)
56 #define REDBEE_USB_VREF2H low(6)
57 #define REDBEE_USB_INTERFACE INTERFACE_B
58 
59 #define FLEXIBITY_USB_RESET high(2)
60 #define FLEXIBITY_USB_VREF2L high(7)
61 #define FLEXIBITY_USB_VREF2H high(6)
62 #define FLEXIBITY_USB_INTERFACE INTERFACE_A
63 
64 #define BOARD REDBEE_USB
65 
66 #define STR(x) #x
67 #define STR2(x) STR(x)
68 #define CAT(x,y) x##y
69 #define CAT2(x, y, z) x##y##z
70 
71 #define dir(x) ( CAT(x,_RESET) | CAT(x,_VREF2L) | CAT(x,_VREF2H))
72 #define interface(x) ( CAT(x,_INTERFACE) )
73 #define reset_release(x) ( CAT(x,_RESET) )
74 #define reset_set(x) ( 0 )
75 #define vref2_normal(x) ( CAT(x,_VREF2H) )
76 #define vref2_erase(x) ( CAT(x,_VREF2L) )
77 
78 /* fgets input buffer length: for prompts and such */
79 #define BUF_LEN 32
80 
81 struct layout {
82  char *name;
83  char *desc;
84  enum ftdi_interface interface;
85  uint16_t dir;
86  uint16_t reset_release;
87  uint16_t reset_set;
88  uint16_t vref2_normal;
89  uint16_t vref2_erase;
90 };
91 
92 int print_and_prompt( struct ftdi_device_list *devlist );
93 int bb_mpsee(struct ftdi_context *ftdic, uint16_t dir, uint16_t val);
94 void reset(struct ftdi_context *ftdic, const struct layout * l);
95 void erase(struct ftdi_context *ftdic, const struct layout * l);
96 void usage(void);
97 
98 #define std_layout(x) \
99  .interface = interface(x), \
100  .dir = dir(x), \
101  .reset_release = reset_release(x), \
102  .reset_set = reset_set(x), \
103  .vref2_normal = vref2_normal(x), \
104  .vref2_erase = vref2_erase(x),
105 
106 static struct layout layouts[] =
107 {
108  { .name = "redbee-econotag",
109  .desc = "Redbee Econotag",
110  std_layout(REDBEE_ECONOTAG)
111  },
112  { .name = "redbee-usb",
113  .desc = "Redbee USB stick",
114  std_layout(REDBEE_USB)
115  },
116  { .name = "flexibity",
117  .desc = "Flexibity USB Interface",
118  std_layout(FLEXIBITY_USB)
119  },
120  { .name = NULL, /* end of table */ },
121 };
122 
123 struct command {
124  char *name;
125  char *desc;
126  void (*cmd)(struct ftdi_context *ftdic, const struct layout * l);
127 };
128 
129 static const struct command commands[] =
130 {
131  {
132  .name = "reset",
133  .desc = "Toggles reset pin",
134  .cmd = reset,
135  },
136  {
137  .name = "erase",
138  .desc = "Sets VREF2 erase mode; toggles reset; waits 2 sec.; sets normal; toggles reset again",
139  .cmd = erase,
140  },
141  { .name = NULL, /* end of table */ },
142 };
143 
144 struct layout * find_layout(char * str)
145 {
146  uint32_t i = 0;
147 
148  while(layouts[i].name != NULL) {
149  if(strcmp(layouts[i].name, str) == 0) { return &layouts[i]; }
150  i++;
151  }
152 
153  return NULL;
154 }
155 
156 static uint32_t vendid = 0x0403; uint32_t prodid = 0x6010;
157 
158 int main(int argc, char **argv)
159 {
160  struct ftdi_context ftdic;
161  struct ftdi_device_list *devlist;
162  int dev_index = -1; int num_devs;
163  char layout_str[BUF_LEN];
164  struct layout layout;
165  struct layout *l = NULL;
166  int i, ret;
167 
168  /* overrides for layout parameters */
169  int interface = -1;
170  int dir = -1;
171  int reset_release = -1;
172  int reset_set = -1;
173  int vref2_normal = -1;
174  int vref2_erase = -1;
175 
176  layout.name = NULL;
177 
178  while (1) {
179  int c;
180  int option_index = 0;
181  static struct option long_options[] = {
182  {"layout", required_argument, 0, 'l'},
183  {"index", required_argument, 0, 'i'},
184  {"vendor", required_argument, 0, 'v'},
185  {"product", required_argument, 0, 'p'},
186  {"dir", required_argument, 0, 0 },
187  {"reset_release", required_argument, 0, 0 },
188  {"reset_set", required_argument, 0, 0 },
189  {"vref2_normal", required_argument, 0, 0 },
190  {"vref2_erase", required_argument, 0, 0 },
191  {"interface", required_argument, 0, 0 },
192  {"help", no_argument, 0, '?'},
193  {0, 0, 0, 0}
194  };
195 
196  c = getopt_long (argc, argv, "i:l:v:p:",
197  long_options, &option_index);
198  if (c == -1)
199  break;
200 
201  switch (c) {
202  /* process long opts */
203  case 0:
204  if(strcmp(long_options[option_index].name, "interface") == 0) {
205  sscanf(optarg, "%i", &interface);
206  }
207  if(strcmp(long_options[option_index].name, "dir") == 0) {
208  sscanf(optarg, "%i", &dir);
209  }
210  if (strcmp(long_options[option_index].name, "reset_release") == 0) {
211  sscanf(optarg, "%i", &reset_release);
212  }
213  if (strcmp(long_options[option_index].name, "reset_set") == 0) {
214  sscanf(optarg, "%i", &reset_set);
215  }
216  if (strcmp(long_options[option_index].name, "vref2_normal") == 0) {
217  sscanf(optarg, "%i", &vref2_normal);
218  }
219  if (strcmp(long_options[option_index].name, "vref2_erase") == 0) {
220  sscanf(optarg, "%i", &vref2_erase);
221  }
222  break;
223 
224  case 'l':
225  strncpy(layout_str, optarg, BUF_LEN);
226  break;
227  case 'i':
228  dev_index = atoi(optarg);
229  break;
230  case 'v':
231  sscanf(optarg, "%i", &vendid);
232  break;
233  case 'p':
234  sscanf(optarg, "%i", &prodid);
235  break;
236  default:
237  usage();
238  break;
239  }
240  }
241 
242  if( !(l = find_layout(layout_str)) &&
243  !((interface >= 0) &&
244  (dir >= 0) &&
245  (reset_release >= 0) &&
246  (reset_set >= 0) &&
247  (vref2_normal >= 0) &&
248  (vref2_erase >= 0))
249  ) {
250 
251  printf("*** You must specify a layout or a complete set of overrides\n");
252  return EXIT_FAILURE;
253  }
254 
255  if(l) {
256  memcpy(&layout, l, sizeof(struct layout));
257  }
258 
259 #define override(x) if(x > 0) { layout.x = x; }
260  override(interface);
261  override(dir);
262  override(reset_release); override(reset_set);
263  override(vref2_normal); override(vref2_erase);
264 
265  if ((num_devs = ftdi_usb_find_all(&ftdic, &devlist, vendid, prodid)) < 0)
266  {
267  fprintf(stderr, "ftdi_usb_find_all failed: %d (%s)\n",
268  num_devs,
269  ftdi_get_error_string(&ftdic));
270  return EXIT_FAILURE;
271  }
272 
273  if (ftdi_init(&ftdic) < 0)
274  {
275  fprintf(stderr, "ftdi_init failed\n");
276  return EXIT_FAILURE;
277  }
278 
279  if (ftdi_set_interface(&ftdic, layout.interface) < 0) {
280  fprintf(stderr, "couldn't set interface %d\n", layout.interface);
281  return EXIT_FAILURE;
282  }
283 
284  printf("Found %d devices with vendor id 0x%04x product id 0x%04x\n",
285  num_devs, vendid, prodid);
286 
287  if(num_devs == 0) { return EXIT_SUCCESS; }
288 
289  if(num_devs == 1) { dev_index = 0; }
290  while( (dev_index < 0) || (dev_index >= num_devs)){
291  dev_index = print_and_prompt(devlist);
292  }
293 
294  if(layout.name != NULL) {
295  printf("Opening device %d interface %d using layout %s\n",
296  dev_index, layout.interface, layout.name);
297  } else {
298  printf("Opening device %d interface %d without a layout.\n",
299  dev_index, layout.interface);
300  }
301 
302  if( (ret = ftdi_usb_open_desc_index(
303  &ftdic,
304  vendid,
305  prodid,
306  NULL,
307  NULL,
308  dev_index)) < 0) {
309  fprintf(stderr, "couldn't open dev_index %d\n", dev_index);
310  return EXIT_FAILURE;
311  }
312 
313 
314  for(i = 0; commands[i].name != NULL; i++) {
315  if( (argv[optind] != NULL) &&
316  (strcmp(commands[i].name, argv[optind]) == 0)) { break; }
317  }
318  if(commands[i].name != NULL) {
319  commands[i].cmd(&ftdic, &layout);
320  } else {
321  printf("invalid command\n");
322 
323  ftdi_list_free(&devlist);
324  ftdi_deinit(&ftdic);
325 
326  return EXIT_FAILURE;
327  }
328 
329  printf("done.\n");
330 
331  ftdi_list_free(&devlist);
332  ftdi_deinit(&ftdic);
333 
334  return EXIT_SUCCESS;
335 }
336 
337 void usage(void)
338 {
339  int i;
340  printf( "Usage: bbmc [options|overrides] -l|--layout layout command \n");
341  printf( "Commands:\n");
342  for(i = 0; commands[i].name != NULL; i++) {
343  printf( " %s: %s\n", commands[i].name, commands[i].desc);
344  }
345  printf("\n");
346  printf( "Required options:\n");
347  printf( " -l|--layout\t specifiy which board layout to use\n");
348  printf( " \t layout is not necessary with a full\n");
349  printf( " \t set of overrides\n");
350  printf( "\nLayout overrides:\n");
351  printf( " --interface\t\t FTDI interface to use\n");
352  printf( " --dir\t\t direction (1 is output)\n");
353  printf( " --reset_release\t reset release command\n");
354  printf( " --reset_set\t\t reset set command\n");
355  printf( " --vref2_normal\t vref2 normal\n");
356  printf( " --vref2_erase\t vref2 erase\n");
357  printf("\n");
358  printf( "Layouts:\n");
359  for(i = 0; layouts[i].name != NULL; i++) {
360  printf( "\t%s: %s\n", layouts[i].name, layouts[i].desc);
361  printf("\n");
362  printf( "\t\tinterface: \t0x%04x\n", layouts[i].interface);
363  printf( "\t\tdir: \t\t0x%04x\n", layouts[i].dir);
364  printf( "\t\treset release: \t0x%04x\n", layouts[i].reset_release);
365  printf( "\t\treset hold: \t0x%04x\n", layouts[i].reset_set);
366  printf( "\t\tvref2 normal: \t0x%04x\n", layouts[i].vref2_normal);
367  printf( "\t\tvref2 erase: \t0x%04x\n", layouts[i].vref2_erase);
368  printf("\n");
369  }
370  printf("\n");
371  printf( "Options:\n");
372  printf( " -i|--index specifiy which device to use (default 0)\n");
373  printf( " -v|--vendor set vendor id (default 0x0403)\n");
374  printf( " -p|--product set vendor id (default 0x6010)\n");
375 }
376 
377 int print_and_prompt( struct ftdi_device_list *devlist )
378 {
379  int i, ret;
380  struct ftdi_context ftdic;
381  struct ftdi_device_list *curdev;
382  char manufacturer[128], description[128], serial[128];
383  char input[BUF_LEN]; char *s;
384  int sel = -1;
385 
386  printf("\n");
387 
388  i = 0;
389  for (curdev = devlist; curdev != NULL; i++)
390  {
391  printf(" [%d] ", i);
392  if (0 > (ret = ftdi_usb_get_strings(&ftdic,
393  curdev->dev,
394  manufacturer, 128,
395  description, 128,
396  serial, 128)))
397  {
398  fprintf(stderr, "ftdi_usb_get_strings failed: %d (%s)\n",
399  ret, ftdi_get_error_string(&ftdic));
400  return EXIT_FAILURE;
401  }
402  printf("Manufacturer: %s, Description: %s, Serial %s\n",
403  manufacturer, description, serial);
404  curdev = curdev->next;
405  }
406 
407  printf("\nUse which device? ");
408 
409  s = fgets(input, BUF_LEN, stdin);
410  if (s != NULL) {
411  size_t last = strlen (input) - 1;
412  if (input[last] == '\n') input[last] = '\0';
413  }
414 
415  sscanf(s, "%i",&sel);
416 
417  return sel;
418 }
419 
420 void reset(struct ftdi_context *ftdic, const struct layout * l)
421 {
422 
423  /* using MPSSE since it give access to high GPIO*/
424  /* set as inputs for now */
425  ftdi_set_bitmode(ftdic, 0 , BITMODE_MPSSE);
426 
427  printf("toggle reset\n");
428 
429  bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_normal));
430  bb_mpsee(ftdic, l->dir, (l->reset_set | l->vref2_normal));
431  bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_normal));
432 
433  return;
434 
435 }
436 
437 
438 void erase(struct ftdi_context *ftdic, const struct layout * l)
439 {
440  printf("setting VREF2 erase\n");
441 
442  /* using MPSSE since it give access to high GPIO*/
443  /* set as inputs for now */
444  ftdi_set_bitmode(ftdic, 0 , BITMODE_MPSSE);
445 
446  bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_normal));
447  bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_erase));
448 
449  printf("toggle reset\n");
450 
451  bb_mpsee(ftdic, l->dir, (l->reset_set | l->vref2_erase));
452  bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_erase));
453 
454  printf("waiting for erase\n");
455 
456  sleep(2);
457 
458  printf("setting VREF2 normal\n");
459 
460  bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_normal));
461 
462  reset(ftdic, l);
463 
464  return;
465 
466 }
467 
468 
469 int bb_mpsee(struct ftdi_context *ftdic, uint16_t dir, uint16_t val)
470 {
471  uint8_t buf[3];
472  int ret;
473 
474  /* command "set data bits low byte" */
475  buf[0] = 0x80;
476  buf[1] = (val & 0xff);
477  buf[2] = dir & 0xff;
478 #if DEBUG
479  fprintf(stderr,"write %x %x %x\n",buf[0],buf[1],buf[2]);
480 #endif
481 
482  if ((ret = (ftdi_write_data(ftdic, buf, 3))) < 0)
483  {
484  perror("ft2232_write error");
485  fprintf(stderr, "ft2232_write command %x\n", buf[0]);
486  return EXIT_FAILURE;
487  }
488 
489 
490  /* command "set data bits high byte" */
491  buf[0] = 0x82;
492  buf[1] = (val >> 8);
493  buf[2] = dir >> 8;
494 #if DEBUG
495  fprintf(stderr,"write %x %x %x\n",buf[0],buf[1],buf[2]);
496 #endif
497 
498  if ((ret = (ftdi_write_data(ftdic, buf, 3))) < 0)
499  {
500  perror("ft2232_write error");
501  fprintf(stderr, "ft2232_write command %x\n", buf[0]);
502  return EXIT_FAILURE;
503  }
504 
505  return 0;
506 
507 }
#define NULL
The null pointer.
int main(void)
This is main...
Definition: ethconfig.c:49