diff --git a/firmware/BRIDGE-PROTOCOL b/firmware/BRIDGE-PROTOCOL index e812eae..4e8a6c6 100644 --- a/firmware/BRIDGE-PROTOCOL +++ b/firmware/BRIDGE-PROTOCOL @@ -14,5 +14,6 @@ h->r:\5\0 r->h: \2\0 h->r:\6\0 r->h: \2\0 - +h->r:\7\0 +r->h: \7\0 diff --git a/firmware/applications/bridge.c b/firmware/applications/bridge.c index 6c5cb9b..c3b1b98 100644 --- a/firmware/applications/bridge.c +++ b/firmware/applications/bridge.c @@ -99,6 +99,14 @@ void main_bridge(void) config.maclen[0]=serialmsg_message[0]; nrf_config_set(&config); break; + case '7': + puts("\\7"); + char s[sizeof(uint32_t)+1]; + *((uint32_t*)s) =GetUUID32(); + s[sizeof(uint32_t)]=0; + puts(s); + puts("\\0"); + break; }; puts("\\2\\0"); } diff --git a/firmware/basic/uuid.c b/firmware/basic/uuid.c index 12cdf72..69c1430 100644 --- a/firmware/basic/uuid.c +++ b/firmware/basic/uuid.c @@ -8,7 +8,7 @@ uint32_t uuid32=0; uint16_t uuid16=0; -uint32_t __GetUUID32(void){ +static uint32_t __GetUUID32(void){ IAP_return_t iap_return; iap_return = iapReadSerialNumber(); if (iap_return.ReturnCode == 0){ @@ -24,28 +24,22 @@ uint32_t __GetUUID32(void){ }; // What OpenBeacon used. Do we want this? -uint16_t __GetUUID16(void){ +static uint16_t __GetUUID16(void){ IAP_return_t iap_return; iap_return = iapReadSerialNumber(); return crc16 ((uint8_t *) iap_return.Result, sizeof (iap_return.Result)); }; -uint32_t initUUID(void){ +void initUUID(void){ uuid32=__GetUUID32(); uuid16=__GetUUID16(); }; uint32_t GetUUID32(void){ - if(uuid32==0){ - initUUID(); - }; return uuid32; }; uint16_t GetUUID16(void){ - if(uuid32==0){ - initUUID(); - }; return uuid16; }; diff --git a/firmware/basic/uuid.h b/firmware/basic/uuid.h index d64d92b..75f6087 100644 --- a/firmware/basic/uuid.h +++ b/firmware/basic/uuid.h @@ -3,6 +3,7 @@ #include uint32_t GetUUID32(void); +void initUUID(void); #endif diff --git a/firmware/filesystem/util.c b/firmware/filesystem/util.c index f4ace01..a5c01b5 100644 --- a/firmware/filesystem/util.c +++ b/firmware/filesystem/util.c @@ -103,11 +103,18 @@ int readFile(char * filename, char * data, int len){ }; int readTextFile(char * filename, char * data, int len){ - UINT readbytes; + int readbytes; + if(len<1) return -1; readbytes=readFile(filename,data,len-1); - if(len>=0) - data[readbytes]=0; + if(readbytes<0){ + data[0]=0; + return readbytes; + }; + data[readbytes]=0; + while(readbytes>0 && data[readbytes-1]<0x20){ + data[--readbytes]=0; + }; return readbytes; }; diff --git a/firmware/l0dable/files/fahrplan.scd b/firmware/l0dable/files/fahrplan.scd index 44dba4d..287c261 100644 Binary files a/firmware/l0dable/files/fahrplan.scd and b/firmware/l0dable/files/fahrplan.scd differ diff --git a/firmware/l0dable/files/fp-mini.scd b/firmware/l0dable/files/fp-mini.scd deleted file mode 100644 index 54a8d46..0000000 Binary files a/firmware/l0dable/files/fp-mini.scd and /dev/null differ diff --git a/firmware/lcd/render.c b/firmware/lcd/render.c index 37f0110..24bd604 100644 --- a/firmware/lcd/render.c +++ b/firmware/lcd/render.c @@ -384,7 +384,7 @@ int DoChar(int sx, int sy, int c){ }; #define UTF8 -// decode 2 and 4-byte utf-8 strings. +// decode 2 and 3-byte utf-8 strings. #define UT2(a) ( ((a[0]&31)<<6) + (a[1]&63) ) #define UT3(a) ( ((a[0]&15)<<12) + ((a[1]&63)<<6) + (a[2]&63) ) diff --git a/firmware/main.c b/firmware/main.c index 67c740f..277a196 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -50,6 +50,7 @@ void main(void) { // initialise basic badge functions rbInit(); + initUUID(); // Cache UUID values. lcdInit(); // display @@ -80,5 +81,5 @@ void main(void) { } int getrelease(void){ - return 0x0000010d; + return 0x0000010e; }; diff --git a/tools/mesh/.gitignore b/tools/mesh/.gitignore new file mode 100644 index 0000000..39624cc --- /dev/null +++ b/tools/mesh/.gitignore @@ -0,0 +1 @@ +BEACON diff --git a/tools/mesh/beacon-udp.pl b/tools/mesh/beacon-udp.pl new file mode 100755 index 0000000..a68e7df --- /dev/null +++ b/tools/mesh/beacon-udp.pl @@ -0,0 +1,190 @@ +#!/usr/bin/perl +# +# vim:set ts=4 sw=4: + +use strict; +use warnings; +use POSIX qw(strftime); +#use Time::HiRes qw(time); +use Digest::CRC qw(crcccitt); + +use FindBin; +use lib "$FindBin::Bin/lib"; +use r0ket; + +$|=1; + +use Getopt::Long; +my $server = "127.0.0.1"; +my $port = 2342; +my $id = 1234; +my $verbose = 0; +my $fast = 0; +my $channel = 81; +my $mac = "0102030201"; +my $ser = undef; +my $help = 0; +my $intvl = 2; +my $lintvl = 60; +GetOptions ( + "server=s" => \$server, + "port=n" => \$port, + "id=n" => \$id, + "dev=s" => \$ser, + "fast" => \$fast, + "verbose" => \$verbose, + "channel=n" => \$channel, + "mac=s" => \$mac, + "help" => \$help, + ); + +if($help){ + die "Currently no help. Please check the source\n"; +}; + +$ser=r0ket::r0ket_init($ser); + +# Default openbeacon settings. +r0ket::set_txmac(pack("H*",$mac)); # Not really needed. +r0ket::set_rxmac(pack("H*",$mac)); +r0ket::set_channel($channel); +r0ket::set_rxlen(16); +$r0ket::quiet=1; # Hackety-hack :) + +my %bdata; + +use Socket; +use Sys::Hostname; + +my($iaddr,$proto,$paddr); +$iaddr = gethostbyname(hostname()); +$iaddr = pack('C4', 0,0,0,0); +$proto = getprotobyname('udp'); +$paddr = sockaddr_in(0, $iaddr); # 0 means let kernel pick + +socket(SOCKET, PF_INET, SOCK_DGRAM, $proto) || die "socket: $!"; +bind(SOCKET, $paddr) || die "bind: $!"; + +my $hisiaddr = inet_aton($server) || die "unknown server name"; +my $hispaddr = sockaddr_in($port, $hisiaddr); + +###send(SOCKET, 0, 0, $hispaddr); + +my $xterm=0; +my $screen=1; + +my $crcerr=0; +my $errors=0; +my $ctr=0; +my($lcrcerr,$lctr,$lerrors)=(0,0,0); +if($verbose){ + my($dev)=$ser; + if(!defined $dev){ + $dev=""; + }else{ + $dev=~s!/dev/!!; + }; + print "OpenBeacon Reader $id sending [$dev] to [$server:$port]\n"; + if($xterm){ + print "\e]2;", + "$id\[$dev] -> $server:$port @ ", + strftime("%Y-%m-%d %H:%M:%S ",localtime), + "\a"; + }elsif($screen){ + print "\ek", + "$id\[$dev]", + "\e\\"; + }; + print "\n"; +}; + +sub interrupt { + if($xterm){ + print "\e]2;", "", "\a"; + }elsif($screen){ + print "\ek", `hostname`, "\e\\"; + }; + exit; +} +if($verbose){ + $SIG{INT} = \&interrupt; +}; +my $lasttime=time; +my $llasttime=time; +my $pkt; +my $donl=0; + +my($typenick,$typebeacon,$typeunknown)=(0,0,0); +my($ltypenick,$ltypebeacon,$ltypeunknown)=(0,0,0); +while(1){ + $pkt=r0ket::get_packet(); + + if($verbose){ + if(time-$lasttime >= $intvl){ + print "\r"; + if(time-$llasttime >= $lintvl){ + $donl=1; + $llasttime=time; + }; + $lasttime=time; + print strftime("%Y-%m-%d %H:%M:%S ",localtime); + printf "[%ds] cnt=%3d [b=%3d, n=%3d, ?=%3d] errs=%3d crcerr=%3d ", + $intvl, + ($ctr-$lctr), + ($typebeacon-$ltypebeacon), + ($typenick-$ltypenick), + ($typeunknown-$ltypeunknown), + ($errors-$lerrors), + ($crcerr-$lcrcerr); + ($lctr,$lerrors,$lcrcerr)= ($ctr,$errors,$crcerr); + ($ltypenick,$ltypebeacon,$ltypeunknown)= ($typenick,$typebeacon,$typeunknown); + if($donl){ + $donl=0; + print "\n"; + }; + }; + }; + + next if($pkt eq "ack"); # in-band signalling. + if(length($pkt) != 16){ # Sanity check + $errors++; + next; + }; + $ctr++; + + my $idoff=0; + if(substr($pkt,12,1) eq "\xee"){ + $idoff=1000; + }; + + my $hdr= pack("CCnnNN", + 1, # proto (BEACONLOG_SIGHTING) + 0, # interface (we only have one antenna per "reader") + $id+$idoff, # readerid + length($pkt)+16, # size + $ctr, # sequence + time # timestamp + ); + my $crc=pack("n",0xffff ^ crcccitt($hdr.$pkt)); + + send(SOCKET, $crc.$hdr.$pkt,0,$hispaddr); + + next if($fast); + + my $p=r0ket::nice_beacon($pkt); + if($p->{crc} ne "ok"){ + $crcerr++; + next; + }; + if($p->{type} eq "beacon"){ + $typebeacon++; + }elsif($p->{type} eq "nick"){ + $typenick++; + }else{ + $typeunknown++; + }; + if($idoff){ + $typeunknown++; + }; +}; +r0ket::rest(); diff --git a/tools/mesh/beacontrace.pl b/tools/mesh/beacontrace.pl index fe90f61..ea632fc 100755 --- a/tools/mesh/beacontrace.pl +++ b/tools/mesh/beacontrace.pl @@ -7,12 +7,18 @@ use Curses; use POSIX qw(strftime); use Time::HiRes qw(time); -use lib '.'; +use FindBin; +use lib "$FindBin::Bin/lib"; use r0ket; $|=1; -r0ket::r0ket_init(); +my $ser; +if($ARGV[0] eq "-d"){ + shift; + $ser=shift; +}; +r0ket::r0ket_init($ser); # Default openbeacon settings. r0ket::set_txmac(pack("H*","0102030201")); diff --git a/tools/mesh/r0ket.pm b/tools/mesh/lib/r0ket.pm similarity index 82% rename from tools/mesh/r0ket.pm rename to tools/mesh/lib/r0ket.pm index 38baaab..0087c6b 100755 --- a/tools/mesh/r0ket.pm +++ b/tools/mesh/lib/r0ket.pm @@ -13,12 +13,20 @@ use Time::HiRes; our $verbose=0; our $bridge; # Open device +our $quiet=0; +our $timediff=60*60*2; + +my $rxlen=0; # Filter for get_pkt() ### Utility sub sprint{ return join("",map { if (ord($_)>30 && ord($_)<127){ - $_; + if(ord($_)==92){ + "\\\\"; + }else{ + $_; + }; }else{ # "[x".unpack("H*",$_)."]"; "\\".unpack("C",$_); @@ -91,8 +99,9 @@ sub writebeacon{ ### Packet mgmt our $buffer; -our $firstpkt=2; -sub get_packet{ +our $firstpkt=1; +sub get_data{ + my $filter=shift||0; sub _get_bytes{ my $rr; sysread($bridge,$rr,1024); @@ -100,35 +109,57 @@ sub get_packet{ select(undef,undef,undef,0.05); }; $buffer.=$rr; +# print "recv: ",unpack("H*",$rr),"\n"; }; my $cnt=0; - while(++$cnt<100){ + while(1){ if(length($buffer)<2){ _get_bytes(); - }elsif($buffer !~ /^\\[12]/){ - $buffer=~s/^(.[^\\]*)//s; + }elsif($buffer !~ /^\\[1-9]/){ + if($buffer =~ /[^\\]\\[1-9]/){ + $buffer =~ s/^(.*?[^\\])(\\[1-9])/\2/s; + }else{ + $buffer = s/(.*)//s; + }; if($firstpkt){ $firstpkt--; }else{ - print STDERR "Unparseable stuff: <",sprint($1),">\n"; + print STDERR "Unparseable stuff: <",sprint($1),">\n" if(!$quiet); }; - }elsif ($buffer =~ s/^\\2\\0//s){ - return 'ack'; # In-band signalling. Evil %) - }elsif ($buffer =~ s/^\\1(.*?)\\0//s){ - my $str=$1; + }elsif ($buffer =~ s/^\\(\d)(.*?)\\0//s){ + my ($type,$str)=($1,$2); $str=~s/\\\\/\\/g; # dequote - return $str; +# print STDERR "ret:pkt[$type]=",(sprint $str),"\n"; + if($filter==0){ + return ($type,$str); + }elsif($filter==$type){ + return $str; + }; }else{ _get_bytes(); }; + if(++$cnt%100 == 0){ + if(!$quiet){ + print STDERR "No packets for 5 seconds?\n"; + }; + }; + }; +}; + +sub get_packet{ + my $pkt; + while(1){ + $pkt=get_data(1); + if($rxlen==0 || length($pkt)==$rxlen){ + return $pkt; + }; }; - die "No packets for 5seconds?\n"; }; sub rest{ if(length($buffer)>0){ - print "rest: <", sprint($buffer), ">\n"; + print "rest: <", sprint($buffer), ">\n" if(!$quiet); }; }; @@ -149,7 +180,7 @@ sub nice_mesh{ $out->{string}.=sprintf " t=%s (%+4d) rel=%s beacon=%s", strftime("%Y-%m-%d %H:%M:%S",gmtime $out->{time}), - $out->{time}-(Time::HiRes::time+3600), + $out->{time}-(Time::HiRes::time+$timediff), $out->{release}, resolvebeacon($out->{beacon}); }elsif($type eq "i"){ @@ -255,7 +286,7 @@ sub nice_beacon{ $out->{idx}, $out->{beacon}; if(unpack("H*",substr($pkt,12,2)) ne "ffff"){ - print "unused=",unpack("H*",substr($pkt,12,2))," "; + print "unused=",unpack("H*",substr($pkt,12,2))," " if (!$quiet); }; }elsif($type eq "\x23"){ $out->{type}= "nick"; @@ -265,6 +296,7 @@ sub nice_beacon{ $out->{string}=sprintf "NICK beacon=%s nick=%s", $out->{beacon}, $out->{nick}; + addbeacon($out->{beacon},$out->{nick}); }else{ $out->{string}=""; }; @@ -283,11 +315,7 @@ sub nice_beacon{ }; sub r0ket_init{ - my $ser; - if ($ARGV[0] eq "-s"){ - shift; - $ser=shift; - }; + my $ser=shift; if(!defined $ser){ if (defined $ENV{R0KETBRIDGE} && -e $ENV{R0KETBRIDGE}){ $ser=$ENV{R0KETBRIDGE} @@ -300,6 +328,7 @@ sub r0ket_init{ if($verbose){ print "using: $ser\n"; }; + return $ser; }; sub send_raw { @@ -329,15 +358,16 @@ sub set_channel { send_pkt_num(pack("C",shift),5); }; sub set_rxlen { + $rxlen=$_[0]; send_pkt_num(pack("C",shift),6); }; sub wait_ok { - my $pkt; - $pkt=get_packet(); - while($pkt ne "ack"){ - print "pkt=",(sprint $pkt),"\n"; - $pkt=get_packet(); + my ($type,$pkt); + ($type,$pkt)=get_data(); + while($type ne "2"){ + print "pkt[$type]=[",length($pkt),"]",(sprint $pkt),"\n"; + ($type,$pkt)=get_data(); }; print "ok!\n"; return 1; diff --git a/tools/mesh/meshtrace.pl b/tools/mesh/meshtrace.pl index 2788083..0b285e9 100755 --- a/tools/mesh/meshtrace.pl +++ b/tools/mesh/meshtrace.pl @@ -6,12 +6,18 @@ use strict; use Curses; use POSIX qw(strftime); -use lib '.'; +use FindBin; +use lib "$FindBin::Bin/lib"; use r0ket; $|=1; -r0ket::r0ket_init(); +my $ser; +if($ARGV[0] eq "-d"){ + shift; + $ser=shift; +}; +r0ket::r0ket_init($ser); # Default mesh settings. r0ket::set_txmac("ORBIT"); @@ -55,7 +61,7 @@ while(1){ $p->{generation}, $p->{release}, strftime("%Y-%m-%d %H:%M:%S",gmtime $p->{time}), - $p->{time}-(time+3600), + $p->{time}-(time+$r0ket::timediff), r0ket::getbeacon($p->{beacon}) ); $win->refresh; diff --git a/tools/mesh/rf b/tools/mesh/rf index 5bf5b17..332ada4 100755 --- a/tools/mesh/rf +++ b/tools/mesh/rf @@ -9,22 +9,31 @@ use Digest::CRC qw(crcccitt); use POSIX qw(strftime); use FindBin; -use lib "$FindBin::Bin"; +use lib "$FindBin::Bin/lib"; use r0ket; $|=1; -r0ket::r0ket_init(); +### Commandline options +use Getopt::Long; +my $ser = undef; +my $help = 0; +my $writend = 0; +GetOptions ( + "dev=s" => \$ser, + "help" => \$help, + "write" => \$writend, + ); -my @fh; -my $read; +$help=1 if($ARGV[0] =~ /^[h?]/); -if ($ARGV[0] =~ /^-?-?h/){ +if ($help){ print STDERR "Mini-Help:\n"; - print STDERR "-s (or \$R0KETBRIDGE)\n"; + print STDERR "-d (or \$R0KETBRIDGE)\n"; print STDERR "-w write beacon2nick file\n"; print STDERR "\n"; print STDERR "recv: receive (number) pakets\n"; + print STDERR " - r : try to autodetect packet format\n"; print STDERR " - r hex : hexdump packets\n"; print STDERR " - r ascii : asciidump packets\n"; print STDERR " - r beacon : parse as openbeacon\n"; @@ -47,22 +56,23 @@ if ($ARGV[0] =~ /^-?-?h/){ print STDERR "- c tx - set txmac\n"; print STDERR "- c len - set rxlength\n"; print STDERR "- c ch - set channel\n"; - print STDERR "- c hex - set any option via hex string\n"; + print STDERR "- c hex - set any of the previous option via hex string\n"; + print STDERR "- c id - read beacon id\n"; print STDERR "\n"; print STDERR "etc...\n"; exit(1); }; -my $writend=0; -if ($ARGV[0] eq "-w"){ - shift; - $writend=1; -}; - END{ r0ket::writebeacon if($writend); }; +r0ket::r0ket_init($ser); +$r0ket::verbose=1; + +my @fh; +my $read; + my $cmd=shift; if($cmd =~ /^r/){ @@ -158,6 +168,10 @@ if($cmd =~ /^r/){ r0ket::set_channel(shift); }elsif ($set =~ /^len/){ r0ket::set_rxlen(shift); + }elsif ($set =~ /^id/){ + r0ket::send_pkt_num("",7); + my $id=r0ket::get_data(7); + print "r0ket id: ",r0ket::hprint($id),"\n"; }else{ die "Unknown config argument $set\n"; }; @@ -181,7 +195,7 @@ if($cmd =~ /^r/){ if($scmd eq "t"){ $pkt.="T"; $pkt.=chr(shift); #gen - $pkt.=pack("N",scalar(time)+1*60*60); + $pkt.=pack("N",scalar(time)+$r0ket::timediff); $pkt.=pack("N",0); $pkt.=pack("N",0); @@ -192,7 +206,7 @@ if($cmd =~ /^r/){ }elsif($scmd eq "a"){ $pkt.="A"; $pkt.=chr(shift); #gen - $pkt.=pack("N",scalar(time)+1*60*60+ 300); + $pkt.=pack("N",scalar(time)+$r0ket::timediff+ 300); $pkt.= pack("C",shift||0); $pkt.= pack("C",0); @@ -207,7 +221,7 @@ if($cmd =~ /^r/){ }elsif($scmd eq "b"){ $pkt.="B"; $pkt.=chr(shift); #gen - $pkt.=pack("N",scalar(time)+1*60*60+ 600); + $pkt.=pack("N",scalar(time)+$r0ket::timediff+ 600); $pkt.= pack("C",shift||0); $pkt.= pack("C",0); @@ -222,7 +236,7 @@ if($cmd =~ /^r/){ }elsif($scmd eq "c"){ $pkt.="\x1"; $pkt.=chr(shift); #gen - $pkt.=pack("N",scalar(time)+1*60*60+ 600); + $pkt.=pack("N",scalar(time)+$r0ket::timediff+ 600); $pkt.= pack("C",shift||0); $pkt.= pack("C",0); diff --git a/tools/smartflash/.gitignore b/tools/smartflash/.gitignore index b211c62..15221b8 100644 --- a/tools/smartflash/.gitignore +++ b/tools/smartflash/.gitignore @@ -1,2 +1,3 @@ firmware.bin +bridge.bin files diff --git a/tools/smartflash/Makefile b/tools/smartflash/Makefile index acd9615..878746e 100644 --- a/tools/smartflash/Makefile +++ b/tools/smartflash/Makefile @@ -27,6 +27,11 @@ setup: @echo @echo "Now run ./smartflash (as root)" +bridge: + cd ../../firmware && make APP=bridge TABLE=NO USBSERIAL=YES clean all + cp ../../firmware/bridge.bin . + sudo ./smartflash bridge.bin + run: sudo ./smartflash diff --git a/tools/smartflash/flash b/tools/smartflash/flash index b2307a9..4e09e00 100755 --- a/tools/smartflash/flash +++ b/tools/smartflash/flash @@ -1,3 +1,11 @@ #!/bin/sh -dd if=firmware.bin seek=4 of=/dev/$1 2>/dev/null -echo "FLASH done: $1 @ $2" +bin=frimware.bin +if [ ! -z "$3" ] ; then + bin=$3 +fi +dd if=$3 seek=4 of=/dev/$1 2>/dev/null +if [ -z "$3" ] ; then + echo "FLASH done: $1 @ $2" +else + echo "=== FLASH of $3 done: $1 @ $2" +fi diff --git a/tools/smartflash/smartflash b/tools/smartflash/smartflash index 76d5728..001d715 100755 --- a/tools/smartflash/smartflash +++ b/tools/smartflash/smartflash @@ -5,6 +5,8 @@ $|=1; my $DEV="/sys/bus/usb/devices"; +my $arg=$ARGV[0]; + sub getline{ my($path)=@_; open(my $f,"<",$DEV."/".$path) || do { @@ -110,15 +112,21 @@ sub dwim{ return 1; }; print "flash $dev -> $sdev\n"; - system("./flash $sdev $dev"); + system("./flash $sdev $dev $arg"); $done{$dev}=2; return 1; }; + if("$ve:$pr" eq "239a:1002") { + return 1 if $done{$dev}==3; + my $sdev=getdev($dev); + $done{$dev}=3; + print "BRIDGE r0ket @ $dev, ignoring\n"; + return 0; + }; print "$ve:$pr [$mf] @ "; return -1; }; -my %disable; while(1){ opendir(my $dh, $DEV); my @paths=grep {/^[^.]/} readdir($dh); @@ -126,15 +134,15 @@ while(1){ # print "f: ",join(",",@files),"\n"; device: for my $path (@paths){ - next if ($disable{$path}); next if $path =~ /^usb/; next if $path =~ /:/; # print "p $path\n"; $found{$path}=1; - my $res=dwim($path); + my $res=0; + $res=dwim($path) unless ($done{$path}==-1); if($res==-1){ - print "$path -- ignoring it forever\n"; - $disable{$path}=1; + print "$path -- unknown device, skipping\n"; + $done{$path}=-1; }; }; for my $a (keys %done){