Contiki 2.6

cdc_task.c

Go to the documentation of this file.
00001 /* This file has been prepared for Doxygen automatic documentation generation.*/
00002 /*! \file cdc_task.c **********************************************************
00003  *
00004  * \brief
00005  *      Manages the CDC-ACM Virtual Serial Port Dataclass for the USB Device
00006  *
00007  * \addtogroup usbstick
00008  *
00009  * \author 
00010  *        Colin O'Flynn <coflynn@newae.com>
00011  *
00012  ******************************************************************************/
00013 /* Copyright (c) 2008  ATMEL Corporation
00014    All rights reserved.
00015 
00016    Redistribution and use in source and binary forms, with or without
00017    modification, are permitted provided that the following conditions are met:
00018 
00019    * Redistributions of source code must retain the above copyright
00020      notice, this list of conditions and the following disclaimer.
00021    * Redistributions in binary form must reproduce the above copyright
00022      notice, this list of conditions and the following disclaimer in
00023      the documentation and/or other materials provided with the
00024      distribution.
00025    * Neither the name of the copyright holders nor the names of
00026      contributors may be used to endorse or promote products derived
00027      from this software without specific prior written permission.
00028 
00029   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00030   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00031   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00032   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00033   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00034   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00035   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00036   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00037   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00038   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00039   POSSIBILITY OF SUCH DAMAGE.
00040 */
00041 /**
00042  \ingroup usbstick
00043  \defgroup cdctask CDC Task
00044  @{
00045  */
00046 
00047 //_____  I N C L U D E S ___________________________________________________
00048 
00049 
00050 #include "contiki.h"
00051 #include "usb_drv.h"
00052 #include "usb_descriptors.h"
00053 #include "usb_specific_request.h"
00054 #include "cdc_task.h"
00055 #include "serial/uart_usb_lib.h"
00056 #include "rndis/rndis_protocol.h"
00057 #include "rndis/rndis_task.h"
00058 #include "sicslow_ethernet.h"
00059 #if RF230BB
00060 #include "rf230bb.h"
00061 #else
00062 #include "radio.h"
00063 #endif
00064 
00065 #include <stdio.h>
00066 #include <stdlib.h>
00067 #include "dev/watchdog.h"
00068 #include "rng.h"
00069 
00070 #include "bootloader.h"
00071 
00072 #include <avr/pgmspace.h>
00073 #include <avr/eeprom.h>
00074 #include <avr/wdt.h>
00075 #include <util/delay.h>
00076 
00077 #if JACKDAW_CONF_USE_SETTINGS
00078 #include "settings.h"
00079 #endif
00080 
00081 #define BUF ((struct uip_eth_hdr *)&uip_buf[0])
00082 #define PRINTF printf
00083 #define PRINTF_P printf_P
00084 
00085 //_____ M A C R O S ________________________________________________________
00086 
00087 
00088 #define bzero(ptr,size) memset(ptr,0,size)
00089 
00090 //_____ D E F I N I T I O N S ______________________________________________
00091 
00092 
00093 #define IAD_TIMEOUT_DETACH 300
00094 #define IAD_TIMEOUT_ATTACH 600
00095 
00096 //_____ D E C L A R A T I O N S ____________________________________________
00097 
00098 
00099 void menu_print(void);
00100 void menu_process(char c);
00101 
00102 extern char usb_busy;
00103 
00104 //! Counter for USB Serial port
00105 extern U8    tx_counter;
00106 
00107 //! Timers for LEDs
00108 uint8_t led3_timer;
00109 
00110 
00111 //! previous configuration
00112 static uint8_t previous_uart_usb_control_line_state = 0;
00113 
00114 
00115 static uint8_t timer = 0;
00116 static struct etimer et;
00117 
00118 #define CONVERTTXPOWER 1
00119 #if CONVERTTXPOWER  //adds ~120 bytes to program flash size
00120 const char txonesdigit[16]   PROGMEM = {'3','2','2','1','1','0','0','1','2','3','4','5','7','9','2','7'};
00121 const char txtenthsdigit[16] PROGMEM = {'0','6','1','6','1','5','2','2','2','2','2','2','2','2','2','2'};
00122 static void printtxpower(void) {
00123     uint8_t power=rf230_get_txpower()&0xf;
00124     char sign=(power<6?'+':'-');
00125     char tens=(power>14?'1':'0');
00126     char ones=pgm_read_byte(&txonesdigit[power]);
00127     char tenths=pgm_read_byte(&txtenthsdigit[power]);
00128     if (tens=='0') {tens=sign;sign=' ';}
00129     PRINTF_P(PSTR("%c%c%c.%cdBm"),sign,tens,ones,tenths);
00130 }
00131 #endif
00132 
00133 PROCESS(cdc_process, "CDC serial process");
00134 
00135 /**
00136  * \brief Communication Data Class (CDC) Process
00137  *
00138  *   This is the link between USB and the "good stuff". In this routine data
00139  *   is received and processed by CDC-ACM Class
00140  */
00141 PROCESS_THREAD(cdc_process, ev, data_proc)
00142 {
00143         PROCESS_BEGIN();
00144 
00145 #if USB_CONF_RS232
00146         static FILE *rs232_stdout,*usb_stdout;
00147         rs232_stdout=stdout;
00148 #endif
00149 
00150         while(1) {
00151             // turn off LED's if necessary
00152                 if (led3_timer) led3_timer--;
00153                 else                    Led3_off();
00154                 
00155                 if(Is_device_enumerated()) {
00156                         // If the configuration is different than the last time we checked...
00157                         if((uart_usb_get_control_line_state()&1)!=previous_uart_usb_control_line_state) {
00158                                 previous_uart_usb_control_line_state = uart_usb_get_control_line_state()&1;
00159                                 static FILE* previous_stdout;
00160                                 
00161                                 if(previous_uart_usb_control_line_state&1) {
00162                                         previous_stdout = stdout;
00163                                         uart_usb_init();
00164                                         uart_usb_set_stdout();
00165                                 //      menu_print(); do this later
00166                                 } else {
00167                                         stdout = previous_stdout;
00168                                 }
00169 #if USB_CONF_RS232
00170                                 usb_stdout=stdout;
00171 #endif
00172                         }
00173 
00174                         //Flush buffer if timeout
00175                 if(timer >= 4 && tx_counter!=0 ){
00176                     timer = 0;
00177                     uart_usb_flush();
00178                 } else {
00179                                 timer++;
00180                         }
00181 
00182 #if USB_CONF_RS232
00183                         stdout=usb_stdout;
00184 #endif
00185                         while (uart_usb_test_hit()){
00186                            menu_process(uart_usb_getchar());   // See what they want
00187             }
00188 #if USB_CONF_RS232
00189             if (usbstick_mode.debugOn) {
00190                           stdout=rs232_stdout;
00191                         } else {
00192                           stdout=NULL;
00193                         }
00194 #endif
00195                 }//if (Is_device_enumerated())
00196 
00197 
00198 
00199                 if (USB_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) {
00200                         etimer_set(&et, CLOCK_SECOND/80);
00201                 } else {
00202                         etimer_set(&et, CLOCK_SECOND);
00203                 }
00204 
00205                 PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));  
00206                 
00207         } // while(1)
00208 
00209         PROCESS_END();
00210 }
00211 
00212 /**
00213  \brief Print debug menu
00214  */
00215 void menu_print(void)
00216 {
00217                 PRINTF_P(PSTR("\n\r*********** Jackdaw Menu **********\n\r"));
00218                 PRINTF_P(PSTR("        [Built "__DATE__"]      \n\r"));
00219 //              PRINTF_P(PSTR("*                                 *\n\r"));
00220                 PRINTF_P(PSTR("*  m        Print current mode    *\n\r"));
00221                 PRINTF_P(PSTR("*  s        Set to sniffer mode   *\n\r"));
00222                 PRINTF_P(PSTR("*  n        Set to network mode   *\n\r"));
00223                 PRINTF_P(PSTR("*  c        Set RF channel        *\n\r"));
00224                 PRINTF_P(PSTR("*  p        Set RF power          *\n\r"));
00225                 PRINTF_P(PSTR("*  6        Toggle 6lowpan        *\n\r"));
00226                 PRINTF_P(PSTR("*  r        Toggle raw mode       *\n\r"));
00227 #if USB_CONF_RS232
00228                 PRINTF_P(PSTR("*  d        Toggle RS232 output   *\n\r"));
00229 #endif
00230 #if RF230BB && RF230_CONF_SNEEZER
00231                 PRINTF_P(PSTR("*  S        Enable sneezer mode   *\n\r"));
00232 #endif
00233 #if UIP_CONF_IPV6_RPL
00234                 PRINTF_P(PSTR("*  N        RPL Neighbors         *\n\r"));
00235                 PRINTF_P(PSTR("*  G        RPL Global Repair     *\n\r"));
00236 #endif
00237                 PRINTF_P(PSTR("*  e        Energy Scan           *\n\r"));
00238 #if USB_CONF_STORAGE
00239                 PRINTF_P(PSTR("*  u        Switch to mass-storage*\n\r"));
00240 #endif
00241                 if(bootloader_is_present())
00242                 PRINTF_P(PSTR("*  D        Switch to DFU mode    *\n\r"));
00243                 PRINTF_P(PSTR("*  R        Reset (via WDT)       *\n\r"));
00244                 PRINTF_P(PSTR("*  h,?      Print this menu       *\n\r"));
00245                 PRINTF_P(PSTR("*                                 *\n\r"));
00246                 PRINTF_P(PSTR("* Make selection at any time by   *\n\r"));
00247                 PRINTF_P(PSTR("* pressing your choice on keyboard*\n\r"));
00248                 PRINTF_P(PSTR("***********************************\n\r"));
00249 }
00250 
00251 #if UIP_CONF_IPV6_RPL
00252 static void
00253 ipaddr_add(const uip_ipaddr_t *addr)
00254 {
00255   uint16_t a;
00256   int8_t i, f;
00257   for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) {
00258     a = (addr->u8[i] << 8) + addr->u8[i + 1];
00259     if(a == 0 && f >= 0) {
00260       if(f++ == 0) PRINTF_P(PSTR("::"));
00261     } else {
00262       if(f > 0) {
00263         f = -1;
00264       } else if(i > 0) {
00265             PRINTF_P(PSTR(":"));
00266       }
00267           PRINTF_P(PSTR("%x"),a);
00268     }
00269   }
00270 }
00271 #endif
00272 
00273 /**
00274  \brief Process incomming char on debug port
00275  */
00276 void menu_process(char c)
00277 {
00278 
00279         static enum menustate_enum            /* Defines an enumeration type    */
00280         {
00281                 normal,
00282                 channel,
00283         txpower
00284         } menustate = normal;
00285         
00286         static char channel_string[3];
00287         static uint8_t channel_string_i;// = 0;
00288         
00289         int tempchannel;
00290 
00291         if (menustate == channel) {
00292 
00293                 switch(c) {
00294                         case '\r':
00295                         case '\n':              
00296                                                                 
00297                                 if (channel_string_i)  {
00298                                         channel_string[channel_string_i] = 0;
00299                                         tempchannel = atoi(channel_string);
00300 
00301 #if RF230BB
00302                                         if ((tempchannel < 11) || (tempchannel > 26))  {
00303                                                 PRINTF_P(PSTR("\n\rInvalid input\n\r"));
00304                                         } else {
00305                                                 rf230_set_channel(tempchannel);
00306 #else
00307                                         if(radio_set_operating_channel(tempchannel)!=RADIO_SUCCESS) {
00308                                                 PRINTF_P(PSTR("\n\rInvalid input\n\r"));
00309                                         } else {
00310 #endif
00311 #if JACKDAW_CONF_USE_SETTINGS
00312                                                 if(settings_set_uint8(SETTINGS_KEY_CHANNEL, tempchannel)==SETTINGS_STATUS_OK) {                       
00313                             PRINTF_P(PSTR("\n\rChannel changed to %d and stored in EEPROM.\n\r"),tempchannel);
00314                                                 } else {
00315                             PRINTF_P(PSTR("\n\rChannel changed to %d, but unable to store in EEPROM!\n\r"),tempchannel);
00316                         }
00317 #else
00318                                                 PRINTF_P(PSTR("\n\rChannel changed to %d.\n\r"),tempchannel);
00319 #endif
00320                                         }
00321                                 } else {
00322                                         PRINTF_P(PSTR("\n\rChannel unchanged.\n\r"));
00323                                 }
00324 
00325                                 menustate = normal;
00326                                 break;
00327                 
00328                         case '\b':
00329                         
00330                                 if (channel_string_i) {
00331                                         channel_string_i--;
00332                                         PRINTF_P(PSTR("\b \b"));
00333                                 }
00334                                 break;
00335                                         
00336                         case '0':
00337                         case '1':
00338                         case '2':
00339                         case '3':
00340                         case '4':
00341                         case '5':
00342                         case '6':
00343                         case '7':
00344                         case '8':
00345                         case '9':
00346                                 if (channel_string_i > 1) {
00347                                         // This time the user has gone too far.
00348                                         // Beep at them.
00349                                         putc('\a', stdout);
00350                                         //uart_usb_putchar('\a');
00351                                         break;
00352                                 }
00353                                 putc(c, stdout);
00354                                 //uart_usb_putchar(c);
00355                                 
00356                                 channel_string[channel_string_i] = c;
00357                                 channel_string_i++;
00358                                 break;
00359 
00360                         default:
00361                                 break;
00362                 }
00363         } else if (menustate == txpower) {
00364 
00365                 switch(c) {
00366                         case '\r':
00367                         case '\n':              
00368                                                                 
00369                                 if (channel_string_i)  {
00370                                         channel_string[channel_string_i] = 0;
00371                                         tempchannel = atoi(channel_string);
00372 #if RF230BB
00373                                         if ((tempchannel < 0) || (tempchannel > 15))  {
00374                                                 PRINTF_P(PSTR("\n\rInvalid input\n\r"));
00375                                         } else {
00376                         PRINTF_P(PSTR(" ")); //for some reason needs a print here to clear the string input...
00377                                                 rf230_set_txpower(tempchannel);
00378 #else
00379                                         if(radio_set_tx_power_level(tempchannel)!=RADIO_SUCCESS) {
00380                                                 PRINTF_P(PSTR("\n\rInvalid input\n\r"));
00381                                         } else {
00382 #endif
00383 #if JACKDAW_CONF_USE_SETTINGS
00384                                                 if(settings_set_uint8(SETTINGS_KEY_TXPOWER, tempchannel)==SETTINGS_STATUS_OK) {
00385                                                         PRINTF_P(PSTR("\n\rTransmit power changed to %d, and stored in EEPROM.\n\r"),tempchannel);
00386                                                 } else {
00387                                                         PRINTF_P(PSTR("\n\rTransmit power changed to %d, but unable to store in EEPROM!\n\r"),tempchannel);
00388                                                 }
00389 #else
00390                                                 PRINTF_P(PSTR("\n\rTransmit power changed to %d.\n\r"),tempchannel);
00391 #endif
00392                                         }
00393                                 } else {
00394                                         PRINTF_P(PSTR("\n\rTransmit power unchanged.\n\r"));
00395                                 }
00396 
00397                                 menustate = normal;
00398                                 break;
00399                 
00400                         case '\b':
00401                         
00402                                 if (channel_string_i) {
00403                                         channel_string_i--;
00404                                         PRINTF_P(PSTR("\b \b"));
00405                                 }
00406                                 break;
00407                                         
00408                         case '0':
00409                         case '1':
00410                         case '2':
00411                         case '3':
00412                         case '4':
00413                         case '5':
00414                         case '6':
00415                         case '7':
00416                         case '8':
00417                         case '9':
00418                                 if (channel_string_i > 1) {
00419                                         // This time the user has gone too far.
00420                                         // Beep at them.
00421                                         putc('\a', stdout);
00422                                         //uart_usb_putchar('\a');
00423                                         break;
00424                                 }
00425                                 putc(c, stdout);
00426                                 //uart_usb_putchar(c);
00427                                 
00428                                 channel_string[channel_string_i] = c;
00429                                 channel_string_i++;
00430                                 break;
00431 
00432                         default:
00433                                 break;
00434                 }
00435  
00436         } else {
00437 
00438                 uint8_t i;
00439 
00440         /* Any attempt to read an RF230 register in sneeze mode (e.g. rssi) will hang the MCU */
00441         /* So convert any command into a sneeze off */
00442         if (usbstick_mode.sneeze) c='S';
00443 
00444                 switch(c) {
00445                         case '\r':
00446                         case '\n':
00447                                 break;
00448 
00449                         case 'h':
00450                         case '?':
00451                                 menu_print();
00452                                 break;
00453                         case '-':
00454                                 PRINTF_P(PSTR("Bringing interface down\n\r"));
00455                                 usb_eth_set_active(0);
00456                                 break;
00457                         case '=':
00458                         case '+':
00459                                 PRINTF_P(PSTR("Bringing interface up\n\r"));
00460                                 usb_eth_set_active(1);
00461                                 break;
00462 #if JACKDAW_CONF_RANDOM_MAC
00463                         case 'T':
00464                                 // Test "strong" random number generator of R Quattlebaum
00465                 // This can potentially reboot the stick!
00466                                 PRINTF_P(PSTR("RNG Output: "));
00467                                 {
00468                                         uint8_t value = rng_get_uint8();
00469                                         uint8_t i;
00470                                         for(i=0;i<8;i++) {
00471                                                 uart_usb_putchar(((value>>(7-i))&1)?'1':'0');
00472                                         }
00473                                         PRINTF_P(PSTR("\n\r"));
00474                                         uart_usb_flush();
00475                                         watchdog_periodic();
00476                                 }
00477                                 break;
00478 #endif
00479                         case 's':
00480                                 PRINTF_P(PSTR("Jackdaw now in sniffer mode\n\r"));
00481                                 usbstick_mode.sendToRf = 0;
00482                                 usbstick_mode.translate = 0;
00483 #if RF230BB
00484                                 rf230_listen_channel(rf230_get_channel());
00485 #else           
00486                                 radio_set_trx_state(RX_ON);
00487 #endif
00488                                 break;
00489 
00490 #if RF230BB && RF230_CONF_SNEEZER
00491                         case 'S':
00492                                 if (usbstick_mode.sneeze) {
00493                                         rf230_warm_reset();
00494                                         PRINTF_P(PSTR("Jackdaw now behaving itself.\n\r"));
00495                                         usbstick_mode.sneeze = 0;
00496                                 } else {
00497                                         if (rf230_get_txpower()<3)
00498                                                 PRINTF_P(PSTR("*****WARNING Radio may overheat in this mode*******\n\r"));
00499                                         rf230_start_sneeze();
00500                                         PRINTF_P(PSTR("********Jackdaw is continuously broadcasting*******\n\r"));
00501 #if CONVERTTXPOWER
00502                                         PRINTF_P(PSTR("*********on channel %2d with power "),rf230_get_channel());
00503                                         printtxpower();
00504                                         PRINTF_P(PSTR("*********\n\r"));
00505 #else
00506                                         PRINTF_P(PSTR("************on channel %2d with power %2d************\n\r"),rf230_get_channel(),rf230_get_txpower());
00507 #endif
00508                                         PRINTF_P(PSTR("Press any key to stop.\n\r"));
00509                                         watchdog_periodic();
00510                                         usbstick_mode.sneeze = 1;
00511                                 }
00512                                 break;
00513 #endif
00514 
00515                         case 'n':
00516                                 PRINTF_P(PSTR("Jackdaw now in network mode\n\r"));
00517                                 usbstick_mode.sendToRf = 1;
00518                                 usbstick_mode.translate = 1;
00519 #if RF230BB
00520                                 rf230_set_channel(rf230_get_channel());
00521 #else           
00522                             radio_set_trx_state(RX_AACK_ON);  //TODO: Use startup state which may be RX_ON
00523 #endif
00524                                 break;
00525 
00526                         case '6':
00527                                 if (usbstick_mode.sicslowpan) {
00528                                         PRINTF_P(PSTR("Jackdaw does not perform 6lowpan translation\n\r"));
00529                                         usbstick_mode.sicslowpan = 0;
00530                                 } else {
00531                                         PRINTF_P(PSTR("Jackdaw now performs 6lowpan translations\n\r"));
00532                                         usbstick_mode.sicslowpan = 1;
00533                                 }       
00534                                 
00535                                 break;
00536 
00537                         case 'r':
00538                                 if (usbstick_mode.raw) {
00539                                         PRINTF_P(PSTR("Jackdaw does not capture raw frames\n\r"));
00540                                         usbstick_mode.raw = 0;
00541                                 } else {
00542                                         PRINTF_P(PSTR("Jackdaw now captures raw frames\n\r"));
00543                                         usbstick_mode.raw = 1;
00544                                 }       
00545                                 break;
00546 #if USB_CONF_RS232
00547                         case 'd':
00548                                 if (usbstick_mode.debugOn) {
00549                                         PRINTF_P(PSTR("Jackdaw does not output debug strings\n\r"));
00550                                         usbstick_mode.debugOn = 0;
00551                                 } else {
00552                                         PRINTF_P(PSTR("Jackdaw now outputs debug strings\n\r"));
00553                                         usbstick_mode.debugOn = 1;
00554                                 }       
00555                                 break;
00556 #endif
00557 
00558 
00559                         case 'c':
00560 #if RF230BB
00561                                 PRINTF_P(PSTR("\nSelect 802.15.4 Channel in range 11-26 [%d]: "), rf230_get_channel());
00562 #else
00563                                 PRINTF_P(PSTR("\nSelect 802.15.4 Channel in range 11-26 [%d]: "), radio_get_operating_channel());
00564 #endif
00565                                 menustate = channel;
00566                                 channel_string_i = 0;
00567                                 break;
00568 
00569                         case 'p':
00570 #if RF230BB
00571                                 PRINTF_P(PSTR("\nSelect transmit power (0=+3dBm 15=-17.2dBm) [%d]: "), rf230_get_txpower());
00572 #else
00573 //                              PRINTF_P(PSTR("\nSelect transmit power (0=+3dBm 15=-17.2dBm) [%d]: "), ?_power());;
00574 #endif
00575                                 menustate = txpower;
00576                                 channel_string_i = 0;
00577                                 break;
00578 
00579 
00580 #if UIP_CONF_IPV6_RPL
00581 #include "rpl.h"
00582 extern uip_ds6_nbr_t uip_ds6_nbr_cache[];
00583 extern uip_ds6_route_t uip_ds6_routing_table[];
00584 extern uip_ds6_netif_t uip_ds6_if;
00585                         case 'N':
00586                         {       uint8_t i,j;
00587                                 PRINTF_P(PSTR("\n\rAddresses [%u max]\n\r"),UIP_DS6_ADDR_NB);
00588                                 for (i=0;i<UIP_DS6_ADDR_NB;i++) {
00589                                         if (uip_ds6_if.addr_list[i].isused) {     
00590                                                 ipaddr_add(&uip_ds6_if.addr_list[i].ipaddr);
00591                                                 PRINTF_P(PSTR("\n\r"));
00592                                         }
00593                                 }
00594                                 PRINTF_P(PSTR("\n\rNeighbors [%u max]\n\r"),UIP_DS6_NBR_NB);
00595                                 for(i = 0,j=1; i < UIP_DS6_NBR_NB; i++) {
00596                                         if(uip_ds6_nbr_cache[i].isused) {
00597                                                 ipaddr_add(&uip_ds6_nbr_cache[i].ipaddr);
00598                                                 PRINTF_P(PSTR("\n\r"));
00599                                                 j=0;
00600                                         }
00601                                 }
00602                                 if (j) PRINTF_P(PSTR("  <none>"));
00603                                 PRINTF_P(PSTR("\n\rRoutes [%u max]\n\r"),UIP_DS6_ROUTE_NB);
00604                                 for(i = 0,j=1; i < UIP_DS6_ROUTE_NB; i++) {
00605                                         if(uip_ds6_routing_table[i].isused) {
00606                                                 ipaddr_add(&uip_ds6_routing_table[i].ipaddr);
00607                                                 PRINTF_P(PSTR("/%u (via "), uip_ds6_routing_table[i].length);
00608                                                 ipaddr_add(&uip_ds6_routing_table[i].nexthop);
00609                                                 if(uip_ds6_routing_table[i].state.lifetime < 600) {
00610                                                         PRINTF_P(PSTR(") %lus\n\r"), uip_ds6_routing_table[i].state.lifetime);
00611                                                 } else {
00612                                                         PRINTF_P(PSTR(")\n\r"));
00613                                                 }
00614                                                 j=0;
00615                                         }
00616                                 }
00617                                 if (j) PRINTF_P(PSTR("  <none>"));
00618                                 PRINTF_P(PSTR("\n\r---------\n\r"));
00619                                 break;
00620                         }
00621                         
00622                         case 'G':
00623                                 PRINTF_P(PSTR("Global repair returns %d\n\r"),rpl_repair_root(RPL_DEFAULT_INSTANCE));
00624                                 break;
00625             
00626             case 'L':
00627                 rpl_local_repair(rpl_get_any_dag());
00628                  PRINTF_P(PSTR("Local repair initiated\n\r")); 
00629                  break;
00630  
00631             case 'Z':     //zap the routing table           
00632             {   uint8_t i; 
00633                                 for (i = 0; i < UIP_DS6_ROUTE_NB; i++) {
00634                                         uip_ds6_routing_table[i].isused=0;
00635                 }
00636                 PRINTF_P(PSTR("Routing table cleared!\n\r")); 
00637                 break;
00638             }
00639 #endif                          
00640                         
00641                         case 'm':
00642                                 PRINTF_P(PSTR("Currently Jackdaw:\n\r  * Will "));
00643                                 if (usbstick_mode.sendToRf == 0) { PRINTF_P(PSTR("not "));}
00644                                 PRINTF_P(PSTR("send data over RF\n\r  * Will "));
00645                                 if (usbstick_mode.translate == 0) { PRINTF_P(PSTR("not "));}
00646                                 PRINTF_P(PSTR("change link-local addresses inside IP messages\n\r  * Will "));
00647                                 if (usbstick_mode.sicslowpan == 0) { PRINTF_P(PSTR("not "));}
00648                                 PRINTF_P(PSTR("decompress 6lowpan headers\n\r  * Will "));
00649                                 if (usbstick_mode.raw == 0) { PRINTF_P(PSTR("not "));}
00650 
00651 #if USB_CONF_RS232
00652                                 PRINTF_P(PSTR("Output raw 802.15.4 frames\n\r  * Will "));
00653                                 if (usbstick_mode.debugOn == 0) { PRINTF_P(PSTR("not "));}
00654                                 PRINTF_P(PSTR("Output RS232 debug strings\n\r"));
00655 #else
00656                                 PRINTF_P(PSTR("Output raw 802.15.4 frames\n\r"));
00657 #endif
00658 
00659                                 PRINTF_P(PSTR("  * USB Ethernet MAC: %02x:%02x:%02x:%02x:%02x:%02x\n"),
00660                                         ((uint8_t *)&usb_ethernet_addr)[0],
00661                                         ((uint8_t *)&usb_ethernet_addr)[1],
00662                                         ((uint8_t *)&usb_ethernet_addr)[2],
00663                                         ((uint8_t *)&usb_ethernet_addr)[3],
00664                                         ((uint8_t *)&usb_ethernet_addr)[4],
00665                                         ((uint8_t *)&usb_ethernet_addr)[5]
00666                                 );
00667                                 extern uint64_t macLongAddr;
00668                                 PRINTF_P(PSTR("  * 802.15.4 EUI-64: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n"),
00669                                         ((uint8_t *)&macLongAddr)[0],
00670                                         ((uint8_t *)&macLongAddr)[1],
00671                                         ((uint8_t *)&macLongAddr)[2],
00672                                         ((uint8_t *)&macLongAddr)[3],
00673                                         ((uint8_t *)&macLongAddr)[4],
00674                                         ((uint8_t *)&macLongAddr)[5],
00675                                         ((uint8_t *)&macLongAddr)[6],
00676                                         ((uint8_t *)&macLongAddr)[7]
00677                                 );
00678 #if RF230BB
00679 #if CONVERTTXPOWER
00680                                 PRINTF_P(PSTR("  * Operates on channel %d with TX power "),rf230_get_channel());
00681                                 printtxpower();
00682                                 PRINTF_P(PSTR("\n\r"));
00683 #else  //just show the raw value          
00684                                 PRINTF_P(PSTR("  * Operates on channel %d\n\r"), rf230_get_channel());
00685                                 PRINTF_P(PSTR("  * TX Power(0=+3dBm, 15=-17.2dBm): %d\n\r"), rf230_get_txpower());
00686 #endif
00687                                 if (rf230_smallest_rssi) {
00688                                         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));
00689                                         rf230_smallest_rssi=0;
00690                                 } else {
00691                                         PRINTF_P(PSTR("  * Current/Last/Smallest RSSI: %d/%d/--dBm\n\r"), -91+(rf230_rssi()-1), -91+(rf230_last_rssi-1));
00692                                 }
00693 
00694 #else /* RF230BB */
00695                                 PRINTF_P(PSTR("  * Operates on channel %d\n\r"), radio_get_operating_channel());
00696                                 PRINTF_P(PSTR("  * TX Power Level: 0x%02X\n\r"), radio_get_tx_power_level());
00697                                 {
00698                                         PRINTF_P(PSTR("  * Current RSSI: "));
00699                                         int8_t rssi = 0;
00700                                         if(radio_get_rssi_value(&rssi)==RADIO_SUCCESS)
00701                                                 PRINTF_P(PSTR("%ddB\n\r"), -91+3*(rssi-1));
00702                                         else
00703                                                 PRINTF_P(PSTR("Unknown\n\r"));
00704                                 }
00705                                 
00706 #endif /* RF230BB */
00707 
00708                                 PRINTF_P(PSTR("  * Configuration: %d, USB<->ETH is "), usb_configuration_nb);
00709                                 if (usb_eth_is_active == 0) PRINTF_P(PSTR("not "));
00710                                 PRINTF_P(PSTR("active\n\r"));
00711 
00712 #if CONFIG_STACK_MONITOR
00713 /* See contiki-raven-main.c for initialization of the magic numbers */
00714 {
00715 extern uint16_t __bss_end;
00716 uint16_t p=(uint16_t)&__bss_end;
00717     do {
00718       if (*(uint16_t *)p != 0x4242) {
00719         printf_P(PSTR("  * Never-used stack > %d bytes\n\r"),p-(uint16_t)&__bss_end);
00720         break;
00721       }
00722       p+=100;
00723     } while (p<RAMEND-100);
00724 }
00725 #endif
00726 
00727                                 break;
00728 
00729                         case 'e':
00730                                 PRINTF_P(PSTR("Energy Scan:\n"));
00731                                 uart_usb_flush();
00732                                 {
00733                                         uint8_t i;
00734                                         uint16_t j;
00735 #if RF230BB
00736                                         uint8_t previous_channel = rf230_get_channel();
00737 #else // RF230BB
00738                                         uint8_t previous_channel = radio_get_operating_channel();
00739 #endif
00740                                         int8_t RSSI, maxRSSI[17];
00741                                         uint16_t accRSSI[17];
00742                                         
00743                                         bzero((void*)accRSSI,sizeof(accRSSI));
00744                                         bzero((void*)maxRSSI,sizeof(maxRSSI));
00745                                         
00746                                         for(j=0;j<(1<<12);j++) {
00747                                                 for(i=11;i<=26;i++) {
00748 #if RF230BB
00749                                                         rf230_listen_channel(i);
00750 #else // RF230BB
00751                                                         radio_set_operating_channel(i);
00752 #endif
00753                                                         _delay_us(3*10);
00754 #if RF230BB
00755                                                         RSSI = rf230_rssi();  //multiplies rssi register by 3 for consistency with energy-detect register
00756 #else // RF230BB
00757                                                         radio_get_rssi_value(&RSSI);
00758                                                         RSSI*=3;
00759 #endif
00760                                                         maxRSSI[i-11]=Max(maxRSSI[i-11],RSSI);
00761                                                         accRSSI[i-11]+=RSSI;
00762                                                 }
00763                                                 if(j&(1<<7)) {
00764                                                         Led3_on();
00765                                                         if(!(j&((1<<7)-1))) {
00766                                                                 PRINTF_P(PSTR("."));
00767                                                                 uart_usb_flush();
00768                                                         }
00769                                                 }
00770                                                 else
00771                                                         Led3_off();
00772                                                 watchdog_periodic();
00773                                         }
00774 #if RF230BB
00775                                         rf230_set_channel(previous_channel);
00776 #else // RF230BB
00777                                         radio_set_operating_channel(previous_channel);
00778 #endif
00779                                         PRINTF_P(PSTR("\n"));
00780                                         for(i=11;i<=26;i++) {
00781                                                 uint8_t activity=Min(maxRSSI[i-11],accRSSI[i-11]/(1<<7));
00782                                                 PRINTF_P(PSTR(" %d: %02ddB "),i, -91+(maxRSSI[i-11]-1));
00783                                                 for(;activity--;maxRSSI[i-11]--) {
00784                                                         PRINTF_P(PSTR("#"));
00785                                                 }
00786                                                 for(;maxRSSI[i-11]>0;maxRSSI[i-11]--) {
00787                                                         PRINTF_P(PSTR(":"));
00788                                                 }
00789                                                 PRINTF_P(PSTR("\n"));
00790                                                 uart_usb_flush();
00791                                         }
00792 
00793                                 }
00794                                 PRINTF_P(PSTR("Done.\n"));
00795                                 uart_usb_flush();
00796                                 
00797                                 break;
00798 
00799 
00800                         case 'D':
00801                                 {
00802                                         PRINTF_P(PSTR("Entering DFU Mode...\n\r"));
00803                                         uart_usb_flush();
00804                                         Leds_on();
00805                                         for(i = 0; i < 10; i++)_delay_ms(100);
00806                                         Leds_off();
00807                                         Jump_To_Bootloader();
00808                                 }
00809                                 break;
00810                         case 'R':
00811                                 {
00812                                         PRINTF_P(PSTR("Resetting...\n\r"));
00813                                         uart_usb_flush();
00814                                         Leds_on();
00815                                         for(i = 0; i < 10; i++)_delay_ms(100);
00816                                         Usb_detach();
00817                                         for(i = 0; i < 20; i++)_delay_ms(100);
00818                                         watchdog_reboot();
00819                                 }
00820                                 break;
00821                                 
00822 #if USB_CONF_STORAGE
00823                         case 'u':
00824 
00825                                 //Mass storage mode
00826                                 usb_mode = mass_storage;
00827 
00828                                 //No more serial port
00829                                 stdout = NULL;
00830 #if USB_CONF_RS232
00831 //                              usb_stdout = NULL;
00832 #endif
00833 
00834                                 //RNDIS is over
00835                                 rndis_state =   rndis_uninitialized;
00836                                 Leds_off();
00837 
00838                                 //Deatch USB
00839                                 Usb_detach();
00840 
00841                                 //Wait a few seconds
00842                                 for(i = 0; i < 50; i++)
00843                     watchdog_periodic();
00844                                         _delay_ms(100);
00845 
00846                                 //Attach USB
00847                                 Usb_attach();
00848 
00849 
00850                                 break;
00851 #endif
00852 
00853                         default:
00854                                 PRINTF_P(PSTR("%c is not a valid option! h for menu\n\r"), c);
00855                                 break;
00856                 }
00857 
00858 
00859         }
00860 
00861         return;
00862 
00863 }
00864 
00865 
00866 /**
00867     @brief This will enable the VCP_TRX_END LED for a period
00868 */
00869 void vcptx_end_led(void)
00870 {
00871     Led3_on();
00872     led3_timer = 5;
00873 }
00874 /** @}  */
00875