Contiki 2.5
cdc_task.c
Go to the documentation of this file.
1 /* This file has been prepared for Doxygen automatic documentation generation.*/
2 /*! \file cdc_task.c **********************************************************
3  *
4  * \brief
5  * Manages the CDC-ACM Virtual Serial Port Dataclass for the USB Device
6  *
7  * \addtogroup usbstick
8  *
9  * \author
10  * Colin O'Flynn <coflynn@newae.com>
11  *
12  ******************************************************************************/
13 /* Copyright (c) 2008 ATMEL Corporation
14  All rights reserved.
15 
16  Redistribution and use in source and binary forms, with or without
17  modification, are permitted provided that the following conditions are met:
18 
19  * Redistributions of source code must retain the above copyright
20  notice, this list of conditions and the following disclaimer.
21  * Redistributions in binary form must reproduce the above copyright
22  notice, this list of conditions and the following disclaimer in
23  the documentation and/or other materials provided with the
24  distribution.
25  * Neither the name of the copyright holders nor the names of
26  contributors may be used to endorse or promote products derived
27  from this software without specific prior written permission.
28 
29  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
30  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
33  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39  POSSIBILITY OF SUCH DAMAGE.
40 */
41 /**
42  \ingroup usbstick
43  \defgroup cdctask CDC Task
44  @{
45  */
46 
47 //_____ I N C L U D E S ___________________________________________________
48 
49 
50 #include "contiki.h"
51 #include "usb_drv.h"
52 #include "usb_descriptors.h"
53 #include "usb_specific_request.h"
54 #include "cdc_task.h"
55 #include "serial/uart_usb_lib.h"
56 #include "rndis/rndis_protocol.h"
57 #include "rndis/rndis_task.h"
58 #include "sicslow_ethernet.h"
59 #if RF230BB
60 #include "rf230bb.h"
61 #else
62 #include "radio.h"
63 #endif
64 
65 #include <stdio.h>
66 #include <stdlib.h>
67 #include "dev/watchdog.h"
68 #include "rng.h"
69 
70 #include "bootloader.h"
71 
72 #include <avr/pgmspace.h>
73 #include <avr/eeprom.h>
74 #include <avr/wdt.h>
75 #include <util/delay.h>
76 
77 #if JACKDAW_CONF_USE_SETTINGS
78 #include "settings.h"
79 #endif
80 
81 #define BUF ((struct uip_eth_hdr *)&uip_buf[0])
82 #define PRINTF printf
83 #define PRINTF_P printf_P
84 
85 //_____ M A C R O S ________________________________________________________
86 
87 
88 #define bzero(ptr,size) memset(ptr,0,size)
89 
90 //_____ D E F I N I T I O N S ______________________________________________
91 
92 
93 #define IAD_TIMEOUT_DETACH 300
94 #define IAD_TIMEOUT_ATTACH 600
95 
96 //_____ D E C L A R A T I O N S ____________________________________________
97 
98 
99 void menu_print(void);
100 void menu_process(char c);
101 
102 extern char usb_busy;
103 
104 //! Counter for USB Serial port
105 extern U8 tx_counter;
106 
107 //! Timers for LEDs
108 uint8_t led3_timer;
109 
110 
111 //! previous configuration
112 static uint8_t previous_uart_usb_control_line_state = 0;
113 
114 
115 static uint8_t timer = 0;
116 static struct etimer et;
117 
118 #define CONVERTTXPOWER 1
119 #if CONVERTTXPOWER //adds ~120 bytes to program flash size
120 const char txonesdigit[16] PROGMEM = {'3','2','2','1','1','0','0','1','2','3','4','5','7','9','2','7'};
121 const char txtenthsdigit[16] PROGMEM = {'0','6','1','6','1','5','2','2','2','2','2','2','2','2','2','2'};
122 static void printtxpower(void) {
123  uint8_t power=rf230_get_txpower()&0xf;
124  char sign=(power<6?'+':'-');
125  char tens=(power>14?'1':'0');
126  char ones=pgm_read_byte(&txonesdigit[power]);
127  char tenths=pgm_read_byte(&txtenthsdigit[power]);
128  if (tens=='0') {tens=sign;sign=' ';}
129  PRINTF_P(PSTR("%c%c%c.%cdBm"),sign,tens,ones,tenths);
130 }
131 #endif
132 
133 PROCESS(cdc_process, "CDC serial process");
134 
135 /**
136  * \brief Communication Data Class (CDC) Process
137  *
138  * This is the link between USB and the "good stuff". In this routine data
139  * is received and processed by CDC-ACM Class
140  */
141 PROCESS_THREAD(cdc_process, ev, data_proc)
142 {
143  PROCESS_BEGIN();
144 
145 #if USB_CONF_RS232
146  static FILE *rs232_stdout,*usb_stdout;
147  rs232_stdout=stdout;
148 #endif
149 
150  while(1) {
151  // turn off LED's if necessary
152  if (led3_timer) led3_timer--;
153  else Led3_off();
154 
155  if(Is_device_enumerated()) {
156  // If the configuration is different than the last time we checked...
157  if((uart_usb_get_control_line_state()&1)!=previous_uart_usb_control_line_state) {
158  previous_uart_usb_control_line_state = uart_usb_get_control_line_state()&1;
159  static FILE* previous_stdout;
160 
161  if(previous_uart_usb_control_line_state&1) {
162  previous_stdout = stdout;
163  uart_usb_init();
164  uart_usb_set_stdout();
165  // menu_print(); do this later
166  } else {
167  stdout = previous_stdout;
168  }
169 #if USB_CONF_RS232
170  usb_stdout=stdout;
171 #endif
172  }
173 
174  //Flush buffer if timeout
175  if(timer >= 4 && tx_counter!=0 ){
176  timer = 0;
177  uart_usb_flush();
178  } else {
179  timer++;
180  }
181 
182 #if USB_CONF_RS232
183  stdout=usb_stdout;
184 #endif
185  while (uart_usb_test_hit()){
186  menu_process(uart_usb_getchar()); // See what they want
187  }
188 #if USB_CONF_RS232
189  if (usbstick_mode.debugOn) {
190  stdout=rs232_stdout;
191  } else {
192  stdout=NULL;
193  }
194 #endif
195  }//if (Is_device_enumerated())
196 
197 
198 
199  if (USB_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) {
200  etimer_set(&et, CLOCK_SECOND/80);
201  } else {
202  etimer_set(&et, CLOCK_SECOND);
203  }
204 
206 
207  } // while(1)
208 
209  PROCESS_END();
210 }
211 
212 /**
213  \brief Print debug menu
214  */
215 void menu_print(void)
216 {
217  PRINTF_P(PSTR("\n\r*********** Jackdaw Menu **********\n\r"));
218  PRINTF_P(PSTR(" [Built "__DATE__"] \n\r"));
219 // PRINTF_P(PSTR("* *\n\r"));
220  PRINTF_P(PSTR("* m Print current mode *\n\r"));
221  PRINTF_P(PSTR("* s Set to sniffer mode *\n\r"));
222  PRINTF_P(PSTR("* n Set to network mode *\n\r"));
223  PRINTF_P(PSTR("* c Set RF channel *\n\r"));
224  PRINTF_P(PSTR("* p Set RF power *\n\r"));
225  PRINTF_P(PSTR("* 6 Toggle 6lowpan *\n\r"));
226  PRINTF_P(PSTR("* r Toggle raw mode *\n\r"));
227 #if USB_CONF_RS232
228  PRINTF_P(PSTR("* d Toggle RS232 output *\n\r"));
229 #endif
230 #if RF230BB && RF230_CONF_SNEEZER
231  PRINTF_P(PSTR("* S Enable sneezer mode *\n\r"));
232 #endif
233 #if UIP_CONF_IPV6_RPL
234  PRINTF_P(PSTR("* N RPL Neighbors *\n\r"));
235  PRINTF_P(PSTR("* G RPL Global Repair *\n\r"));
236 #endif
237  PRINTF_P(PSTR("* e Energy Scan *\n\r"));
238 #if USB_CONF_STORAGE
239  PRINTF_P(PSTR("* u Switch to mass-storage*\n\r"));
240 #endif
241  if(bootloader_is_present())
242  PRINTF_P(PSTR("* D Switch to DFU mode *\n\r"));
243  PRINTF_P(PSTR("* R Reset (via WDT) *\n\r"));
244  PRINTF_P(PSTR("* h,? Print this menu *\n\r"));
245  PRINTF_P(PSTR("* *\n\r"));
246  PRINTF_P(PSTR("* Make selection at any time by *\n\r"));
247  PRINTF_P(PSTR("* pressing your choice on keyboard*\n\r"));
248  PRINTF_P(PSTR("***********************************\n\r"));
249 }
250 
251 #if UIP_CONF_IPV6_RPL
252 static void
253 ipaddr_add(const uip_ipaddr_t *addr)
254 {
255  uint16_t a;
256  int8_t i, f;
257  for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) {
258  a = (addr->u8[i] << 8) + addr->u8[i + 1];
259  if(a == 0 && f >= 0) {
260  if(f++ == 0) PRINTF_P(PSTR("::"));
261  } else {
262  if(f > 0) {
263  f = -1;
264  } else if(i > 0) {
265  PRINTF_P(PSTR(":"));
266  }
267  PRINTF_P(PSTR("%x"),a);
268  }
269  }
270 }
271 #endif
272 
273 /**
274  \brief Process incomming char on debug port
275  */
276 void menu_process(char c)
277 {
278 
279  static enum menustate_enum /* Defines an enumeration type */
280  {
281  normal,
282  channel,
283  txpower
284  } menustate = normal;
285 
286  static char channel_string[3];
287  static uint8_t channel_string_i;// = 0;
288 
289  int tempchannel;
290 
291  if (menustate == channel) {
292 
293  switch(c) {
294  case '\r':
295  case '\n':
296 
297  if (channel_string_i) {
298  channel_string[channel_string_i] = 0;
299  tempchannel = atoi(channel_string);
300 
301 #if RF230BB
302  if ((tempchannel < 11) || (tempchannel > 26)) {
303  PRINTF_P(PSTR("\n\rInvalid input\n\r"));
304  } else {
305  rf230_set_channel(tempchannel);
306 #else
307  if(radio_set_operating_channel(tempchannel)!=RADIO_SUCCESS) {
308  PRINTF_P(PSTR("\n\rInvalid input\n\r"));
309  } else {
310 #endif
311 #if JACKDAW_CONF_USE_SETTINGS
312  if(settings_set_uint8(SETTINGS_KEY_CHANNEL, tempchannel)==SETTINGS_STATUS_OK) {
313  PRINTF_P(PSTR("\n\rChannel changed to %d and stored in EEPROM.\n\r"),tempchannel);
314  } else {
315  PRINTF_P(PSTR("\n\rChannel changed to %d, but unable to store in EEPROM!\n\r"),tempchannel);
316  }
317 #else
318  PRINTF_P(PSTR("\n\rChannel changed to %d.\n\r"),tempchannel);
319 #endif
320  }
321  } else {
322  PRINTF_P(PSTR("\n\rChannel unchanged.\n\r"));
323  }
324 
325  menustate = normal;
326  break;
327 
328  case '\b':
329 
330  if (channel_string_i) {
331  channel_string_i--;
332  PRINTF_P(PSTR("\b \b"));
333  }
334  break;
335 
336  case '0':
337  case '1':
338  case '2':
339  case '3':
340  case '4':
341  case '5':
342  case '6':
343  case '7':
344  case '8':
345  case '9':
346  if (channel_string_i > 1) {
347  // This time the user has gone too far.
348  // Beep at them.
349  putc('\a', stdout);
350  //uart_usb_putchar('\a');
351  break;
352  }
353  putc(c, stdout);
354  //uart_usb_putchar(c);
355 
356  channel_string[channel_string_i] = c;
357  channel_string_i++;
358  break;
359 
360  default:
361  break;
362  }
363  } else if (menustate == txpower) {
364 
365  switch(c) {
366  case '\r':
367  case '\n':
368 
369  if (channel_string_i) {
370  channel_string[channel_string_i] = 0;
371  tempchannel = atoi(channel_string);
372 #if RF230BB
373  if ((tempchannel < 0) || (tempchannel > 15)) {
374  PRINTF_P(PSTR("\n\rInvalid input\n\r"));
375  } else {
376  PRINTF_P(PSTR(" ")); //for some reason needs a print here to clear the string input...
377  rf230_set_txpower(tempchannel);
378 #else
379  if(radio_set_tx_power_level(tempchannel)!=RADIO_SUCCESS) {
380  PRINTF_P(PSTR("\n\rInvalid input\n\r"));
381  } else {
382 #endif
383 #if JACKDAW_CONF_USE_SETTINGS
384  if(settings_set_uint8(SETTINGS_KEY_TXPOWER, tempchannel)==SETTINGS_STATUS_OK) {
385  PRINTF_P(PSTR("\n\rTransmit power changed to %d, and stored in EEPROM.\n\r"),tempchannel);
386  } else {
387  PRINTF_P(PSTR("\n\rTransmit power changed to %d, but unable to store in EEPROM!\n\r"),tempchannel);
388  }
389 #else
390  PRINTF_P(PSTR("\n\rTransmit power changed to %d.\n\r"),tempchannel);
391 #endif
392  }
393  } else {
394  PRINTF_P(PSTR("\n\rTransmit power unchanged.\n\r"));
395  }
396 
397  menustate = normal;
398  break;
399 
400  case '\b':
401 
402  if (channel_string_i) {
403  channel_string_i--;
404  PRINTF_P(PSTR("\b \b"));
405  }
406  break;
407 
408  case '0':
409  case '1':
410  case '2':
411  case '3':
412  case '4':
413  case '5':
414  case '6':
415  case '7':
416  case '8':
417  case '9':
418  if (channel_string_i > 1) {
419  // This time the user has gone too far.
420  // Beep at them.
421  putc('\a', stdout);
422  //uart_usb_putchar('\a');
423  break;
424  }
425  putc(c, stdout);
426  //uart_usb_putchar(c);
427 
428  channel_string[channel_string_i] = c;
429  channel_string_i++;
430  break;
431 
432  default:
433  break;
434  }
435 
436  } else {
437 
438  uint8_t i;
439 
440  /* Any attempt to read an RF230 register in sneeze mode (e.g. rssi) will hang the MCU */
441  /* So convert any command into a sneeze off */
442  if (usbstick_mode.sneeze) c='S';
443 
444  switch(c) {
445  case '\r':
446  case '\n':
447  break;
448 
449  case 'h':
450  case '?':
451  menu_print();
452  break;
453  case '-':
454  PRINTF_P(PSTR("Bringing interface down\n\r"));
455  usb_eth_set_active(0);
456  break;
457  case '=':
458  case '+':
459  PRINTF_P(PSTR("Bringing interface up\n\r"));
460  usb_eth_set_active(1);
461  break;
462 #if JACKDAW_CONF_RANDOM_MAC
463  case 'T':
464  // Test "strong" random number generator of R Quattlebaum
465  // This can potentially reboot the stick!
466  PRINTF_P(PSTR("RNG Output: "));
467  {
468  uint8_t value = rng_get_uint8();
469  uint8_t i;
470  for(i=0;i<8;i++) {
471  uart_usb_putchar(((value>>(7-i))&1)?'1':'0');
472  }
473  PRINTF_P(PSTR("\n\r"));
474  uart_usb_flush();
475  watchdog_periodic();
476  }
477  break;
478 #endif
479  case 's':
480  PRINTF_P(PSTR("Jackdaw now in sniffer mode\n\r"));
481  usbstick_mode.sendToRf = 0;
482  usbstick_mode.translate = 0;
483 #if RF230BB
484  rf230_listen_channel(rf230_get_channel());
485 #else
487 #endif
488  break;
489 
490 #if RF230BB && RF230_CONF_SNEEZER
491  case 'S':
492  if (usbstick_mode.sneeze) {
493  rf230_warm_reset();
494  PRINTF_P(PSTR("Jackdaw now behaving itself.\n\r"));
495  usbstick_mode.sneeze = 0;
496  } else {
497  if (rf230_get_txpower()<3)
498  PRINTF_P(PSTR("*****WARNING Radio may overheat in this mode*******\n\r"));
499  rf230_start_sneeze();
500  PRINTF_P(PSTR("********Jackdaw is continuously broadcasting*******\n\r"));
501 #if CONVERTTXPOWER
502  PRINTF_P(PSTR("*********on channel %2d with power "),rf230_get_channel());
503  printtxpower();
504  PRINTF_P(PSTR("*********\n\r"));
505 #else
506  PRINTF_P(PSTR("************on channel %2d with power %2d************\n\r"),rf230_get_channel(),rf230_get_txpower());
507 #endif
508  PRINTF_P(PSTR("Press any key to stop.\n\r"));
509  watchdog_periodic();
510  usbstick_mode.sneeze = 1;
511  }
512  break;
513 #endif
514 
515  case 'n':
516  PRINTF_P(PSTR("Jackdaw now in network mode\n\r"));
517  usbstick_mode.sendToRf = 1;
518  usbstick_mode.translate = 1;
519 #if RF230BB
520  rf230_set_channel(rf230_get_channel());
521 #else
522  radio_set_trx_state(RX_AACK_ON); //TODO: Use startup state which may be RX_ON
523 #endif
524  break;
525 
526  case '6':
527  if (usbstick_mode.sicslowpan) {
528  PRINTF_P(PSTR("Jackdaw does not perform 6lowpan translation\n\r"));
529  usbstick_mode.sicslowpan = 0;
530  } else {
531  PRINTF_P(PSTR("Jackdaw now performs 6lowpan translations\n\r"));
532  usbstick_mode.sicslowpan = 1;
533  }
534 
535  break;
536 
537  case 'r':
538  if (usbstick_mode.raw) {
539  PRINTF_P(PSTR("Jackdaw does not capture raw frames\n\r"));
540  usbstick_mode.raw = 0;
541  } else {
542  PRINTF_P(PSTR("Jackdaw now captures raw frames\n\r"));
543  usbstick_mode.raw = 1;
544  }
545  break;
546 #if USB_CONF_RS232
547  case 'd':
548  if (usbstick_mode.debugOn) {
549  PRINTF_P(PSTR("Jackdaw does not output debug strings\n\r"));
550  usbstick_mode.debugOn = 0;
551  } else {
552  PRINTF_P(PSTR("Jackdaw now outputs debug strings\n\r"));
553  usbstick_mode.debugOn = 1;
554  }
555  break;
556 #endif
557 
558 
559  case 'c':
560 #if RF230BB
561  PRINTF_P(PSTR("\nSelect 802.15.4 Channel in range 11-26 [%d]: "), rf230_get_channel());
562 #else
563  PRINTF_P(PSTR("\nSelect 802.15.4 Channel in range 11-26 [%d]: "), radio_get_operating_channel());
564 #endif
565  menustate = channel;
566  channel_string_i = 0;
567  break;
568 
569  case 'p':
570 #if RF230BB
571  PRINTF_P(PSTR("\nSelect transmit power (0=+3dBm 15=-17.2dBm) [%d]: "), rf230_get_txpower());
572 #else
573 // PRINTF_P(PSTR("\nSelect transmit power (0=+3dBm 15=-17.2dBm) [%d]: "), ?_power());;
574 #endif
575  menustate = txpower;
576  channel_string_i = 0;
577  break;
578 
579 
580 #if UIP_CONF_IPV6_RPL
581 #include "rpl.h"
584 extern uip_ds6_netif_t uip_ds6_if;
585  case 'N':
586  { uint8_t i,j;
587  PRINTF_P(PSTR("\n\rAddresses [%u max]\n\r"),UIP_DS6_ADDR_NB);
588  for (i=0;i<UIP_DS6_ADDR_NB;i++) {
589  if (uip_ds6_if.addr_list[i].isused) {
590  ipaddr_add(&uip_ds6_if.addr_list[i].ipaddr);
591  PRINTF_P(PSTR("\n\r"));
592  }
593  }
594  PRINTF_P(PSTR("\n\rNeighbors [%u max]\n\r"),UIP_DS6_NBR_NB);
595  for(i = 0,j=1; i < UIP_DS6_NBR_NB; i++) {
596  if(uip_ds6_nbr_cache[i].isused) {
597  ipaddr_add(&uip_ds6_nbr_cache[i].ipaddr);
598  PRINTF_P(PSTR("\n\r"));
599  j=0;
600  }
601  }
602  if (j) PRINTF_P(PSTR(" <none>"));
603  PRINTF_P(PSTR("\n\rRoutes [%u max]\n\r"),UIP_DS6_ROUTE_NB);
604  for(i = 0,j=1; i < UIP_DS6_ROUTE_NB; i++) {
605  if(uip_ds6_routing_table[i].isused) {
606  ipaddr_add(&uip_ds6_routing_table[i].ipaddr);
607  PRINTF_P(PSTR("/%u (via "), uip_ds6_routing_table[i].length);
608  ipaddr_add(&uip_ds6_routing_table[i].nexthop);
609  if(uip_ds6_routing_table[i].state.lifetime < 600) {
610  PRINTF_P(PSTR(") %lus\n\r"), uip_ds6_routing_table[i].state.lifetime);
611  } else {
612  PRINTF_P(PSTR(")\n\r"));
613  }
614  j=0;
615  }
616  }
617  if (j) PRINTF_P(PSTR(" <none>"));
618  PRINTF_P(PSTR("\n\r---------\n\r"));
619  break;
620  }
621 
622  case 'G':
623  PRINTF_P(PSTR("Global repair returns %d\n\r"),rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE)));
624  break;
625 
626  case 'L':
627  rpl_local_repair(rpl_get_dag(RPL_ANY_INSTANCE));
628  PRINTF_P(PSTR("Local repair initiated\n\r"));
629  break;
630 
631  case 'Z': //zap the routing table
632  { uint8_t i;
633  for (i = 0; i < UIP_DS6_ROUTE_NB; i++) {
634  uip_ds6_routing_table[i].isused=0;
635  }
636  PRINTF_P(PSTR("Routing table cleared!\n\r"));
637  break;
638  }
639 #endif
640 
641  case 'm':
642  PRINTF_P(PSTR("Currently Jackdaw:\n\r * Will "));
643  if (usbstick_mode.sendToRf == 0) { PRINTF_P(PSTR("not "));}
644  PRINTF_P(PSTR("send data over RF\n\r * Will "));
645  if (usbstick_mode.translate == 0) { PRINTF_P(PSTR("not "));}
646  PRINTF_P(PSTR("change link-local addresses inside IP messages\n\r * Will "));
647  if (usbstick_mode.sicslowpan == 0) { PRINTF_P(PSTR("not "));}
648  PRINTF_P(PSTR("decompress 6lowpan headers\n\r * Will "));
649  if (usbstick_mode.raw == 0) { PRINTF_P(PSTR("not "));}
650 
651 #if USB_CONF_RS232
652  PRINTF_P(PSTR("Output raw 802.15.4 frames\n\r * Will "));
653  if (usbstick_mode.debugOn == 0) { PRINTF_P(PSTR("not "));}
654  PRINTF_P(PSTR("Output RS232 debug strings\n\r"));
655 #else
656  PRINTF_P(PSTR("Output raw 802.15.4 frames\n\r"));
657 #endif
658 
659  PRINTF_P(PSTR(" * USB Ethernet MAC: %02x:%02x:%02x:%02x:%02x:%02x\n"),
660  ((uint8_t *)&usb_ethernet_addr)[0],
661  ((uint8_t *)&usb_ethernet_addr)[1],
662  ((uint8_t *)&usb_ethernet_addr)[2],
663  ((uint8_t *)&usb_ethernet_addr)[3],
664  ((uint8_t *)&usb_ethernet_addr)[4],
665  ((uint8_t *)&usb_ethernet_addr)[5]
666  );
667  extern uint64_t macLongAddr;
668  PRINTF_P(PSTR(" * 802.15.4 EUI-64: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n"),
669  ((uint8_t *)&macLongAddr)[0],
670  ((uint8_t *)&macLongAddr)[1],
671  ((uint8_t *)&macLongAddr)[2],
672  ((uint8_t *)&macLongAddr)[3],
673  ((uint8_t *)&macLongAddr)[4],
674  ((uint8_t *)&macLongAddr)[5],
675  ((uint8_t *)&macLongAddr)[6],
676  ((uint8_t *)&macLongAddr)[7]
677  );
678 #if RF230BB
679 #if CONVERTTXPOWER
680  PRINTF_P(PSTR(" * Operates on channel %d with TX power "),rf230_get_channel());
681  printtxpower();
682  PRINTF_P(PSTR("\n\r"));
683 #else //just show the raw value
684  PRINTF_P(PSTR(" * Operates on channel %d\n\r"), rf230_get_channel());
685  PRINTF_P(PSTR(" * TX Power(0=+3dBm, 15=-17.2dBm): %d\n\r"), rf230_get_txpower());
686 #endif
687  if (rf230_smallest_rssi) {
688  PRINTF_P(PSTR(" * Current/Last/Smallest RSSI: %d/%d/%ddBm\n\r"), -91+(rf230_rssi()-1), -91+(rf230_last_rssi-1),-91+(rf230_smallest_rssi-1));
689  rf230_smallest_rssi=0;
690  } else {
691  PRINTF_P(PSTR(" * Current/Last/Smallest RSSI: %d/%d/--dBm\n\r"), -91+(rf230_rssi()-1), -91+(rf230_last_rssi-1));
692  }
693 
694 #else /* RF230BB */
695  PRINTF_P(PSTR(" * Operates on channel %d\n\r"), radio_get_operating_channel());
696  PRINTF_P(PSTR(" * TX Power Level: 0x%02X\n\r"), radio_get_tx_power_level());
697  {
698  PRINTF_P(PSTR(" * Current RSSI: "));
699  int8_t rssi = 0;
701  PRINTF_P(PSTR("%ddB\n\r"), -91+3*(rssi-1));
702  else
703  PRINTF_P(PSTR("Unknown\n\r"));
704  }
705 
706 #endif /* RF230BB */
707 
708  PRINTF_P(PSTR(" * Configuration: %d, USB<->ETH is "), usb_configuration_nb);
709  if (usb_eth_is_active == 0) PRINTF_P(PSTR("not "));
710  PRINTF_P(PSTR("active\n\r"));
711 
712 #if CONFIG_STACK_MONITOR
713 /* See contiki-raven-main.c for initialization of the magic numbers */
714 {
715 extern uint16_t __bss_end;
716 uint16_t p=(uint16_t)&__bss_end;
717  do {
718  if (*(uint16_t *)p != 0x4242) {
719  printf_P(PSTR(" * Never-used stack > %d bytes\n\r"),p-(uint16_t)&__bss_end);
720  break;
721  }
722  p+=100;
723  } while (p<RAMEND-100);
724 }
725 #endif
726 
727  break;
728 
729  case 'e':
730  PRINTF_P(PSTR("Energy Scan:\n"));
731  uart_usb_flush();
732  {
733  uint8_t i;
734  uint16_t j;
735 #if RF230BB
736  uint8_t previous_channel = rf230_get_channel();
737 #else // RF230BB
738  uint8_t previous_channel = radio_get_operating_channel();
739 #endif
740  int8_t RSSI, maxRSSI[17];
741  uint16_t accRSSI[17];
742 
743  bzero((void*)accRSSI,sizeof(accRSSI));
744  bzero((void*)maxRSSI,sizeof(maxRSSI));
745 
746  for(j=0;j<(1<<12);j++) {
747  for(i=11;i<=26;i++) {
748 #if RF230BB
749  rf230_listen_channel(i);
750 #else // RF230BB
752 #endif
753  _delay_us(3*10);
754 #if RF230BB
755  RSSI = rf230_rssi(); //multiplies rssi register by 3 for consistency with energy-detect register
756 #else // RF230BB
757  radio_get_rssi_value(&RSSI);
758  RSSI*=3;
759 #endif
760  maxRSSI[i-11]=Max(maxRSSI[i-11],RSSI);
761  accRSSI[i-11]+=RSSI;
762  }
763  if(j&(1<<7)) {
764  Led3_on();
765  if(!(j&((1<<7)-1))) {
766  PRINTF_P(PSTR("."));
767  uart_usb_flush();
768  }
769  }
770  else
771  Led3_off();
772  watchdog_periodic();
773  }
774 #if RF230BB
775  rf230_set_channel(previous_channel);
776 #else // RF230BB
777  radio_set_operating_channel(previous_channel);
778 #endif
779  PRINTF_P(PSTR("\n"));
780  for(i=11;i<=26;i++) {
781  uint8_t activity=Min(maxRSSI[i-11],accRSSI[i-11]/(1<<7));
782  PRINTF_P(PSTR(" %d: %02ddB "),i, -91+(maxRSSI[i-11]-1));
783  for(;activity--;maxRSSI[i-11]--) {
784  PRINTF_P(PSTR("#"));
785  }
786  for(;maxRSSI[i-11]>0;maxRSSI[i-11]--) {
787  PRINTF_P(PSTR(":"));
788  }
789  PRINTF_P(PSTR("\n"));
790  uart_usb_flush();
791  }
792 
793  }
794  PRINTF_P(PSTR("Done.\n"));
795  uart_usb_flush();
796 
797  break;
798 
799 
800  case 'D':
801  {
802  PRINTF_P(PSTR("Entering DFU Mode...\n\r"));
803  uart_usb_flush();
804  Leds_on();
805  for(i = 0; i < 10; i++)_delay_ms(100);
806  Leds_off();
807  Jump_To_Bootloader();
808  }
809  break;
810  case 'R':
811  {
812  PRINTF_P(PSTR("Resetting...\n\r"));
813  uart_usb_flush();
814  Leds_on();
815  for(i = 0; i < 10; i++)_delay_ms(100);
816  Usb_detach();
817  for(i = 0; i < 20; i++)_delay_ms(100);
818  watchdog_reboot();
819  }
820  break;
821 
822 #if USB_CONF_STORAGE
823  case 'u':
824 
825  //Mass storage mode
826  usb_mode = mass_storage;
827 
828  //No more serial port
829  stdout = NULL;
830 #if USB_CONF_RS232
831 // usb_stdout = NULL;
832 #endif
833 
834  //RNDIS is over
835  rndis_state = rndis_uninitialized;
836  Leds_off();
837 
838  //Deatch USB
839  Usb_detach();
840 
841  //Wait a few seconds
842  for(i = 0; i < 50; i++)
843  watchdog_periodic();
844  _delay_ms(100);
845 
846  //Attach USB
847  Usb_attach();
848 
849 
850  break;
851 #endif
852 
853  default:
854  PRINTF_P(PSTR("%c is not a valid option! h for menu\n\r"), c);
855  break;
856  }
857 
858 
859  }
860 
861  return;
862 
863 }
864 
865 
866 /**
867  @brief This will enable the VCP_TRX_END LED for a period
868 */
869 void vcptx_end_led(void)
870 {
871  Led3_on();
872  led3_timer = 5;
873 }
874 /** @} */
875