55 #include "serial/uart_usb_lib.h"
58 #include "sicslow_ethernet.h"
67 #include "dev/watchdog.h"
70 #include "bootloader.h"
72 #include <avr/pgmspace.h>
73 #include <avr/eeprom.h>
75 #include <util/delay.h>
77 #if JACKDAW_CONF_USE_SETTINGS
81 #define BUF ((struct uip_eth_hdr *)&uip_buf[0])
83 #define PRINTF_P printf_P
88 #define bzero(ptr,size) memset(ptr,0,size)
93 #define IAD_TIMEOUT_DETACH 300
94 #define IAD_TIMEOUT_ATTACH 600
102 extern char usb_busy;
112 static uint8_t previous_uart_usb_control_line_state = 0;
115 static uint8_t
timer = 0;
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);
133 PROCESS(cdc_process,
"CDC serial process");
146 static FILE *rs232_stdout,*usb_stdout;
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;
161 if(previous_uart_usb_control_line_state&1) {
162 previous_stdout = stdout;
164 uart_usb_set_stdout();
167 stdout = previous_stdout;
189 if (usbstick_mode.debugOn) {
217 PRINTF_P(PSTR(
"\n\r*********** Jackdaw Menu **********\n\r"));
218 PRINTF_P(PSTR(
" [Built "__DATE__
"] \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"));
228 PRINTF_P(PSTR(
"* d Toggle RS232 output *\n\r"));
230 #if RF230BB && RF230_CONF_SNEEZER
231 PRINTF_P(PSTR(
"* S Enable sneezer mode *\n\r"));
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"));
237 PRINTF_P(PSTR(
"* e Energy Scan *\n\r"));
239 PRINTF_P(PSTR(
"* u Switch to mass-storage*\n\r"));
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"));
251 #if UIP_CONF_IPV6_RPL
258 a = (addr->u8[i] << 8) + addr->u8[i + 1];
259 if(a == 0 && f >= 0) {
260 if(f++ == 0) PRINTF_P(PSTR(
"::"));
267 PRINTF_P(PSTR(
"%x"),a);
279 static enum menustate_enum
284 } menustate = normal;
286 static char channel_string[3];
287 static uint8_t channel_string_i;
291 if (menustate == channel) {
297 if (channel_string_i) {
298 channel_string[channel_string_i] = 0;
299 tempchannel = atoi(channel_string);
302 if ((tempchannel < 11) || (tempchannel > 26)) {
303 PRINTF_P(PSTR(
"\n\rInvalid input\n\r"));
305 rf230_set_channel(tempchannel);
308 PRINTF_P(PSTR(
"\n\rInvalid input\n\r"));
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);
315 PRINTF_P(PSTR(
"\n\rChannel changed to %d, but unable to store in EEPROM!\n\r"),tempchannel);
318 PRINTF_P(PSTR(
"\n\rChannel changed to %d.\n\r"),tempchannel);
322 PRINTF_P(PSTR(
"\n\rChannel unchanged.\n\r"));
330 if (channel_string_i) {
332 PRINTF_P(PSTR(
"\b \b"));
346 if (channel_string_i > 1) {
356 channel_string[channel_string_i] = c;
363 }
else if (menustate == txpower) {
369 if (channel_string_i) {
370 channel_string[channel_string_i] = 0;
371 tempchannel = atoi(channel_string);
373 if ((tempchannel < 0) || (tempchannel > 15)) {
374 PRINTF_P(PSTR(
"\n\rInvalid input\n\r"));
377 rf230_set_txpower(tempchannel);
380 PRINTF_P(PSTR(
"\n\rInvalid input\n\r"));
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);
387 PRINTF_P(PSTR(
"\n\rTransmit power changed to %d, but unable to store in EEPROM!\n\r"),tempchannel);
390 PRINTF_P(PSTR(
"\n\rTransmit power changed to %d.\n\r"),tempchannel);
394 PRINTF_P(PSTR(
"\n\rTransmit power unchanged.\n\r"));
402 if (channel_string_i) {
404 PRINTF_P(PSTR(
"\b \b"));
418 if (channel_string_i > 1) {
428 channel_string[channel_string_i] = c;
442 if (usbstick_mode.sneeze) c=
'S';
454 PRINTF_P(PSTR(
"Bringing interface down\n\r"));
455 usb_eth_set_active(0);
459 PRINTF_P(PSTR(
"Bringing interface up\n\r"));
460 usb_eth_set_active(1);
462 #if JACKDAW_CONF_RANDOM_MAC
466 PRINTF_P(PSTR(
"RNG Output: "));
468 uint8_t value = rng_get_uint8();
473 PRINTF_P(PSTR(
"\n\r"));
480 PRINTF_P(PSTR(
"Jackdaw now in sniffer mode\n\r"));
481 usbstick_mode.sendToRf = 0;
482 usbstick_mode.translate = 0;
484 rf230_listen_channel(rf230_get_channel());
490 #if RF230BB && RF230_CONF_SNEEZER
492 if (usbstick_mode.sneeze) {
494 PRINTF_P(PSTR(
"Jackdaw now behaving itself.\n\r"));
495 usbstick_mode.sneeze = 0;
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"));
502 PRINTF_P(PSTR(
"*********on channel %2d with power "),rf230_get_channel());
504 PRINTF_P(PSTR(
"*********\n\r"));
506 PRINTF_P(PSTR(
"************on channel %2d with power %2d************\n\r"),rf230_get_channel(),rf230_get_txpower());
508 PRINTF_P(PSTR(
"Press any key to stop.\n\r"));
510 usbstick_mode.sneeze = 1;
516 PRINTF_P(PSTR(
"Jackdaw now in network mode\n\r"));
517 usbstick_mode.sendToRf = 1;
518 usbstick_mode.translate = 1;
520 rf230_set_channel(rf230_get_channel());
527 if (usbstick_mode.sicslowpan) {
528 PRINTF_P(PSTR(
"Jackdaw does not perform 6lowpan translation\n\r"));
529 usbstick_mode.sicslowpan = 0;
531 PRINTF_P(PSTR(
"Jackdaw now performs 6lowpan translations\n\r"));
532 usbstick_mode.sicslowpan = 1;
538 if (usbstick_mode.raw) {
539 PRINTF_P(PSTR(
"Jackdaw does not capture raw frames\n\r"));
540 usbstick_mode.raw = 0;
542 PRINTF_P(PSTR(
"Jackdaw now captures raw frames\n\r"));
543 usbstick_mode.raw = 1;
548 if (usbstick_mode.debugOn) {
549 PRINTF_P(PSTR(
"Jackdaw does not output debug strings\n\r"));
550 usbstick_mode.debugOn = 0;
552 PRINTF_P(PSTR(
"Jackdaw now outputs debug strings\n\r"));
553 usbstick_mode.debugOn = 1;
561 PRINTF_P(PSTR(
"\nSelect 802.15.4 Channel in range 11-26 [%d]: "), rf230_get_channel());
566 channel_string_i = 0;
571 PRINTF_P(PSTR(
"\nSelect transmit power (0=+3dBm 15=-17.2dBm) [%d]: "), rf230_get_txpower());
576 channel_string_i = 0;
580 #if UIP_CONF_IPV6_RPL
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"));
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"));
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);
612 PRINTF_P(PSTR(
")\n\r"));
617 if (j) PRINTF_P(PSTR(
" <none>"));
618 PRINTF_P(PSTR(
"\n\r---------\n\r"));
623 PRINTF_P(PSTR(
"Global repair returns %d\n\r"),rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE)));
627 rpl_local_repair(rpl_get_dag(RPL_ANY_INSTANCE));
628 PRINTF_P(PSTR(
"Local repair initiated\n\r"));
633 for (i = 0; i < UIP_DS6_ROUTE_NB; i++) {
634 uip_ds6_routing_table[i].isused=0;
636 PRINTF_P(PSTR(
"Routing table cleared!\n\r"));
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 "));}
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"));
656 PRINTF_P(PSTR(
"Output raw 802.15.4 frames\n\r"));
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]
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]
680 PRINTF_P(PSTR(
" * Operates on channel %d with TX power "),rf230_get_channel());
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());
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;
691 PRINTF_P(PSTR(
" * Current/Last/Smallest RSSI: %d/%d/--dBm\n\r"), -91+(rf230_rssi()-1), -91+(rf230_last_rssi-1));
698 PRINTF_P(PSTR(
" * Current RSSI: "));
701 PRINTF_P(PSTR(
"%ddB\n\r"), -91+3*(rssi-1));
703 PRINTF_P(PSTR(
"Unknown\n\r"));
709 if (usb_eth_is_active == 0) PRINTF_P(PSTR(
"not "));
710 PRINTF_P(PSTR(
"active\n\r"));
712 #if CONFIG_STACK_MONITOR
715 extern uint16_t __bss_end;
716 uint16_t p=(uint16_t)&__bss_end;
718 if (*(uint16_t *)p != 0x4242) {
719 printf_P(PSTR(
" * Never-used stack > %d bytes\n\r"),p-(uint16_t)&__bss_end);
723 }
while (p<RAMEND-100);
730 PRINTF_P(PSTR(
"Energy Scan:\n"));
736 uint8_t previous_channel = rf230_get_channel();
740 int8_t RSSI, maxRSSI[17];
741 uint16_t accRSSI[17];
743 bzero((
void*)accRSSI,
sizeof(accRSSI));
744 bzero((
void*)maxRSSI,
sizeof(maxRSSI));
746 for(j=0;j<(1<<12);j++) {
747 for(i=11;i<=26;i++) {
749 rf230_listen_channel(i);
760 maxRSSI[i-11]=Max(maxRSSI[i-11],RSSI);
765 if(!(j&((1<<7)-1))) {
775 rf230_set_channel(previous_channel);
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]--) {
786 for(;maxRSSI[i-11]>0;maxRSSI[i-11]--) {
789 PRINTF_P(PSTR(
"\n"));
794 PRINTF_P(PSTR(
"Done.\n"));
802 PRINTF_P(PSTR(
"Entering DFU Mode...\n\r"));
805 for(i = 0; i < 10; i++)_delay_ms(100);
807 Jump_To_Bootloader();
812 PRINTF_P(PSTR(
"Resetting...\n\r"));
815 for(i = 0; i < 10; i++)_delay_ms(100);
817 for(i = 0; i < 20; i++)_delay_ms(100);
826 usb_mode = mass_storage;
835 rndis_state = rndis_uninitialized;
842 for(i = 0; i < 50; i++)
854 PRINTF_P(PSTR(
"%c is not a valid option! h for menu\n\r"), c);