Merge remote-tracking branch 'github/master'
This commit is contained in:
commit
50f14a3a5e
|
@ -8,12 +8,17 @@ r->h: \2\0
|
|||
Settings:
|
||||
h->r:\3<TXMAC>\0
|
||||
r->h: \2\0
|
||||
|
||||
h->r:\4<RXMAX>\0
|
||||
r->h: \2\0
|
||||
|
||||
h->r:\5<CHANNEL>\0
|
||||
r->h: \2\0
|
||||
h->r:\6<MACLEN>\0
|
||||
|
||||
h->r:\6<RXLEN>\0
|
||||
r->h: \2\0
|
||||
|
||||
h->r:\7\0
|
||||
r->h: \7<UUID>\0
|
||||
r->h: \2\0
|
||||
|
||||
|
|
|
@ -60,6 +60,8 @@ void main_bridge(void)
|
|||
GLOBAL(lcdbacklight)=10;
|
||||
GLOBAL(privacy) = 3;
|
||||
char input[64];
|
||||
char led1=0;
|
||||
char led2=0;
|
||||
|
||||
usbCDCInit();
|
||||
delayms(500);
|
||||
|
@ -71,6 +73,7 @@ void main_bridge(void)
|
|||
int l, i, status;
|
||||
CDC_OutBufAvailChar (&l);
|
||||
if(l>0){
|
||||
gpioSetValue (RB_LED0, led1);led1=1-led1;
|
||||
CDC_RdOutBuf (input, &l);
|
||||
for(i=0; i<l; i++){
|
||||
uint8_t cmd = serialmsg_put(input[i]);
|
||||
|
@ -116,6 +119,7 @@ void main_bridge(void)
|
|||
uint8_t buf[32];
|
||||
len=nrf_rcv_pkt_poll(sizeof(buf),buf);
|
||||
if( len > 0 ){
|
||||
gpioSetValue (RB_LED2, led2);led2=1-led2;
|
||||
puts("\\1");
|
||||
dump_encoded(len, buf);
|
||||
puts("\\0");
|
||||
|
|
Binary file not shown.
|
@ -4,11 +4,12 @@
|
|||
|
||||
use strict;
|
||||
|
||||
use IO::Select;
|
||||
package r0ket;
|
||||
use IO::Select;
|
||||
use Socket;
|
||||
|
||||
use Digest::CRC qw(crcccitt);
|
||||
use POSIX qw(strftime VTIME VMIN TCSANOW);
|
||||
use POSIX qw(strftime :termios_h);
|
||||
use Time::HiRes;
|
||||
|
||||
our $verbose=0;
|
||||
|
@ -98,14 +99,16 @@ sub writebeacon{
|
|||
|
||||
### Packet mgmt
|
||||
|
||||
our $buffer;
|
||||
my $buffer;
|
||||
our $firstpkt=1;
|
||||
sub get_data{
|
||||
my $filter=shift||0;
|
||||
|
||||
my $rin=''; # Select vector
|
||||
my $ein=''; # Select vector
|
||||
my ($rout,$eout);
|
||||
vec($rin,fileno($bridge),1) = 1;
|
||||
vec($ein,fileno($bridge),1) = 1;
|
||||
|
||||
while(1){
|
||||
|
||||
|
@ -118,6 +121,7 @@ sub get_data{
|
|||
}elsif($filter==$type){
|
||||
return $str;
|
||||
};
|
||||
print "got a 2: ",length($str)," $str \n" if ($type==2);
|
||||
next; # If rejected, look for next packet.
|
||||
};
|
||||
|
||||
|
@ -132,9 +136,8 @@ sub get_data{
|
|||
redo; # Try parsing the rest.
|
||||
};
|
||||
};
|
||||
|
||||
my ($nfound,$timeleft) =
|
||||
select($rout=$rin, undef, $eout=$rin, 1);
|
||||
select($rout=$rin, undef, $eout=$ein, 1);
|
||||
if($nfound==0){
|
||||
if($filter==0){
|
||||
return (0,'');
|
||||
|
@ -142,17 +145,18 @@ sub get_data{
|
|||
print STDERR "No packets for 1 second...\n";
|
||||
};
|
||||
};
|
||||
if($eout eq $rin){
|
||||
if($eout eq $ein){ # Doesn't get triggered?
|
||||
die "Error on bridge socket: $!\n";
|
||||
};
|
||||
if($rout eq $rin){
|
||||
my $rr;
|
||||
my $rr="";
|
||||
sysread($bridge,$rr,1024);
|
||||
# print "len=",length($rr),"\n";
|
||||
$buffer.=$rr;
|
||||
die "Nothing to read?" if(length($rr)==0); # Probably device gone.
|
||||
# print "recv: ",unpack("H*",$rr),"\n";
|
||||
};
|
||||
|
||||
# print "recv: ",unpack("H*",$rr),"\n";
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -330,6 +334,25 @@ sub r0ket_init{
|
|||
$ser=$ENV{R0KETBRIDGE}
|
||||
};
|
||||
};
|
||||
if($ser =~ /:/){
|
||||
my ($remote, $port, $iaddr, $paddr, $proto, $line);
|
||||
|
||||
$ser =~ /(.*):(.*)/;
|
||||
$remote = $1;
|
||||
$port = $2;
|
||||
$iaddr = inet_aton($remote) || die "no host: $remote";
|
||||
$paddr = sockaddr_in($port, $iaddr);
|
||||
|
||||
$proto = getprotobyname("tcp");
|
||||
use Fcntl;
|
||||
socket($bridge, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
|
||||
connect($bridge, $paddr) || die "connect: $!";
|
||||
|
||||
my $old_flags = fcntl($bridge, F_GETFL, 0)
|
||||
or die "can't get flags: $!";
|
||||
fcntl($bridge, F_SETFL, $old_flags | O_NONBLOCK)
|
||||
or die "can't set non blocking: $!";
|
||||
}else{
|
||||
if(!defined $ser){
|
||||
do {$ser=$_ if ( -e $_ ) } for qw(/dev/ttyACM0);
|
||||
};
|
||||
|
@ -343,7 +366,9 @@ sub r0ket_init{
|
|||
$term->getattr(fileno($bridge));
|
||||
$term->setcc(VTIME,1);
|
||||
$term->setcc(VMIN,0);
|
||||
$term->setcc(ECHO,0);
|
||||
$term->setattr(fileno($bridge),TCSANOW);
|
||||
};
|
||||
|
||||
#empty buffer, in case there is old data
|
||||
my $dummy;
|
||||
|
@ -389,7 +414,7 @@ sub set_rxlen {
|
|||
};
|
||||
sub get_id {
|
||||
send_pkt_num("",7);
|
||||
my $id=get_data(7);
|
||||
my $id=unpack("H*",get_data(7));
|
||||
wait_ok(1);
|
||||
return $id;
|
||||
};
|
||||
|
|
|
@ -73,6 +73,17 @@ $r0ket::verbose=1;
|
|||
my @fh;
|
||||
my $read;
|
||||
|
||||
my @args=@ARGV;
|
||||
my $sidx=0;
|
||||
for my $eidx (0..$#args){
|
||||
if($args[$eidx] eq ","){
|
||||
dwim(@args[$sidx..$eidx-1]);
|
||||
$sidx=$eidx+1;
|
||||
}
|
||||
};
|
||||
dwim(@args[$sidx..$#args]);
|
||||
|
||||
sub dwim{
|
||||
my $cmd=shift;
|
||||
|
||||
if($cmd =~ /^r/){
|
||||
|
@ -170,7 +181,7 @@ if($cmd =~ /^r/){
|
|||
r0ket::set_rxlen(shift);
|
||||
}elsif ($set =~ /^id/){
|
||||
my $id=r0ket::get_id();
|
||||
print "r0ket id: ",r0ket::hprint($id),"\n";
|
||||
print "r0ket id: ",$id,"\n";
|
||||
}else{
|
||||
die "Unknown config argument $set\n";
|
||||
};
|
||||
|
@ -271,6 +282,7 @@ if($cmd =~ /^r/){
|
|||
}else{
|
||||
die "Option not understood\n";
|
||||
};
|
||||
};
|
||||
|
||||
#if (@fh = $sel->can_read(10)) {
|
||||
# sysread($fh[0],$read,1024);
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
ifneq "$(TUPLE)" ""
|
||||
PREFIX=$(TUPLE)-
|
||||
ARCH=$(shell echo $(TUPLE)|sed 's/-.*//')
|
||||
else
|
||||
PREFIX=
|
||||
ARCH=$(shell uname -m)
|
||||
endif
|
||||
|
||||
CC = $(PREFIX)gcc
|
||||
STRIP = $(PREFIX)strip
|
||||
|
||||
CFLAGS = -Wall -O2
|
||||
EXE = obreader
|
||||
FILES = obreader.c
|
||||
|
||||
$(ARCH)-$(EXE): $(FILES)
|
||||
$(CC) $(CFLAGS) -o $@ $(FILES)
|
||||
$(STRIP) $@
|
||||
|
||||
|
||||
# Using OpenWRT crossbuild environment, see
|
||||
# <URL:http://wiki.openwrt.org/doc/devel/crosscompile>
|
||||
# for setup instructions.
|
||||
WRT=~/r0ket/openwrt/trunk/staging_dir
|
||||
STAGING_DIR=$(WRT)/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2
|
||||
|
||||
mips:
|
||||
STAGING_DIR=$(STAGING_DIR) \
|
||||
PATH=${PATH}:$(STAGING_DIR)/bin \
|
||||
$(MAKE) TUPLE=mips-openwrt-linux
|
||||
|
||||
clean:
|
||||
rm -f *-$(EXE)
|
|
@ -10,6 +10,7 @@ use Digest::CRC qw(crcccitt);
|
|||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/lib";
|
||||
use lib "$FindBin::Bin/../mesh/lib";
|
||||
use r0ket;
|
||||
|
||||
$|=1;
|
||||
|
@ -162,14 +163,15 @@ while(1){
|
|||
|
||||
if(length($pkt) != 16){ # Sanity check
|
||||
$errors++;
|
||||
print STDERR "Length check\n";
|
||||
next;
|
||||
};
|
||||
$ctr++;
|
||||
|
||||
my $idoff=0;
|
||||
if(substr($pkt,12,1) eq "\xee"){
|
||||
$idoff=1000;
|
||||
};
|
||||
# if(substr($pkt,12,1) eq "\xee"){
|
||||
# $idoff=1000;
|
||||
# };
|
||||
|
||||
my $hdr= pack("CCnnNN",
|
||||
1, # proto (BEACONLOG_SIGHTING)
|
||||
|
@ -198,8 +200,8 @@ while(1){
|
|||
}else{
|
||||
$typeunknown++;
|
||||
};
|
||||
if($idoff){
|
||||
$typeunknown++;
|
||||
};
|
||||
# if($idoff){
|
||||
# $typeunknown++;
|
||||
# };
|
||||
};
|
||||
r0ket::rest();
|
|
@ -0,0 +1,33 @@
|
|||
#!/usr/bin/perl
|
||||
#
|
||||
# vim:set ts=4 sw=4:
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Socket;
|
||||
|
||||
our $port=514;
|
||||
my $hispaddr;
|
||||
|
||||
my $socket;
|
||||
|
||||
my($iaddr,$proto,$paddr);
|
||||
$iaddr = pack('C4', 0,0,0,0);
|
||||
$proto = getprotobyname('udp');
|
||||
$paddr = sockaddr_in($port, $iaddr); # 0 means let kernel pick
|
||||
|
||||
socket($socket, PF_INET, SOCK_DGRAM, $proto) || die "socket: $!";
|
||||
bind($socket, $paddr) || die "bind: $!";
|
||||
|
||||
my ($hisiaddr,$host);
|
||||
my $buf;
|
||||
while (1){
|
||||
$hispaddr = recv($socket, $buf, 2048, 0) || die "recv: $!";
|
||||
($port, $hisiaddr) = sockaddr_in($hispaddr);
|
||||
# $host = gethostbyaddr($hisiaddr, AF_INET);
|
||||
$host=join(".",unpack("CCCC",$hisiaddr));
|
||||
chomp($buf);
|
||||
$buf =~ y!a-zA-Z0-9.:,; _()[]{}<>/?-!!cd;
|
||||
print substr(scalar(localtime),11,8)," ",$host," ",$buf,"\n";
|
||||
};
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
#!/usr/bin/perl
|
||||
#
|
||||
# vim:set ts=4 sw=4:
|
||||
|
||||
use strict;
|
||||
use POSIX;
|
||||
use Socket;
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/lib";
|
||||
use l0gger;
|
||||
|
||||
l0gger::init();
|
||||
|
||||
|
||||
use constant AF_NETLINK => 16;
|
||||
#use Socket::Netlink;
|
||||
|
||||
# Netlink setup
|
||||
socket my $sock,AF_NETLINK,SOCK_RAW,0 #(domain, type, bus//protocol)
|
||||
or die "socket: $!\n";
|
||||
bind $sock, pack("vvVV",AF_NETLINK,0,0,1) #(domain, zero , pid, group);
|
||||
or die "bind: $!\n";
|
||||
|
||||
while(1){
|
||||
sysread($sock,my $msg, 65535) or die "recv: $!";
|
||||
my ($ifname,$state)=(undef,undef);
|
||||
|
||||
# print unpack("H*",substr($message,0,16)),"\n"; # ifi_type etc.
|
||||
$msg=substr($msg,16);
|
||||
|
||||
my (undef,undef,undef,undef,undef,$type)=unpack("nnnnCC",$msg);
|
||||
$msg=substr($msg,16);
|
||||
# print "Type=$type\n";
|
||||
next if($type!=16); # RTM_NEWLINK
|
||||
|
||||
while(length($msg)){
|
||||
my($len,$type)=unpack("vv",$msg);
|
||||
# print "len= $len,type=$type\n";
|
||||
last if($len<4);
|
||||
|
||||
$msg=substr($msg,4);
|
||||
if ($type == 3){ # IFLA_IFNAME
|
||||
$ifname=unpack("Z*",$msg);
|
||||
}elsif($type == 16){ # IFLA_OPERSTATE
|
||||
$state=unpack("v",$msg);
|
||||
}else{
|
||||
# print "content=",unpack("H*",substr($msg,0,$len-4)),"\n";
|
||||
};
|
||||
|
||||
$len=(int(($len-1)/4))*4; # 4-byte alignment
|
||||
$msg=substr($msg,$len);
|
||||
};
|
||||
next if(!defined($ifname) || !defined($state));
|
||||
# print "ifname=$ifname, state=$state\n";
|
||||
# IF_OPER_UNKNOWN (0):
|
||||
# Interface is in unknown state, neither driver nor userspace has set
|
||||
# operational state. Interface must be considered for user data as
|
||||
# setting operational state has not been implemented in every driver.
|
||||
# IF_OPER_NOTPRESENT (1):
|
||||
# Unused in current kernel (notpresent interfaces normally disappear),
|
||||
# just a numerical placeholder.
|
||||
# IF_OPER_DOWN (2):
|
||||
# Interface is unable to transfer data on L1, f.e. ethernet is not
|
||||
# plugged or interface is ADMIN down.
|
||||
# IF_OPER_LOWERLAYERDOWN (3):
|
||||
# Interfaces stacked on an interface that is IF_OPER_DOWN show this
|
||||
# state (f.e. VLAN).
|
||||
# IF_OPER_TESTING (4):
|
||||
# Unused in current kernel.
|
||||
# IF_OPER_DORMANT (5):
|
||||
# Interface is L1 up, but waiting for an external event, f.e. for a
|
||||
# protocol to establish. (802.1X)
|
||||
# IF_OPER_UP (6):
|
||||
# Interface is operational up and can be used.
|
||||
if($state==6){
|
||||
l0gger::send("$ifname up");
|
||||
};
|
||||
}
|
|
@ -0,0 +1,514 @@
|
|||
/* obreader.c by Sec <sec@42.org>
|
||||
* vim:set cin sm ts=4:
|
||||
*
|
||||
* Do whatever you want with this code, but give credit
|
||||
*
|
||||
* This program reads packets from an USB-Serial R0ket
|
||||
* and sends them off via TCP/UDP to a central host
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <pwd.h>
|
||||
#include <stdlib.h>
|
||||
#include <termios.h>
|
||||
|
||||
#define INTERVAL 1
|
||||
|
||||
#define BUFSIZE 100
|
||||
#define PORT 2342
|
||||
char *SRV_IP="127.0.0.1";
|
||||
|
||||
#define TYPE_UDP
|
||||
#undef TYPE_TCP
|
||||
|
||||
/* rotating buffer */
|
||||
#define ELEMSIZE 32
|
||||
unsigned int bufstart=0,bufend=0; /* rotating buffer */
|
||||
#define BUFIDX(a) (a*ELEMSIZE)
|
||||
#define BUFPUSH() do{ bufend++; if(bufend==BUFSIZE){ bufend=0; }; if(bufend==bufstart){ BUFPOP();}; }while(0)
|
||||
#define BUFPOP() do{ bufstart++; if(bufstart==BUFSIZE){ bufstart=0; }; }while(0)
|
||||
unsigned char buffer[BUFIDX(BUFSIZE)];
|
||||
|
||||
time_t the_time;
|
||||
|
||||
static u_int16_t
|
||||
crc16 (const unsigned char *buffer, int size)
|
||||
{
|
||||
u_int16_t crc = 0xFFFF;
|
||||
|
||||
if (buffer && size)
|
||||
while (size--)
|
||||
{
|
||||
crc = (crc >> 8) | (crc << 8);
|
||||
crc ^= *buffer++;
|
||||
crc ^= ((unsigned char) crc) >> 4;
|
||||
crc ^= crc << 12;
|
||||
crc ^= (crc & 0xFF) << 5;
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
void setnonblocking(int fd) {
|
||||
int opts;
|
||||
|
||||
opts = fcntl(fd,F_GETFL);
|
||||
if (opts < 0) {
|
||||
perror("fcntl(F_GETFL)");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
opts = (opts | O_NONBLOCK);
|
||||
if (fcntl(fd,F_SETFL,opts) < 0) {
|
||||
perror("fcntl(F_SETFL)");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void setupserial(int fd){
|
||||
struct termios config;
|
||||
|
||||
if(!isatty(fd)) {
|
||||
fprintf(stderr,"fd %d is not a tty?",fd);
|
||||
exit(EXIT_FAILURE);
|
||||
};
|
||||
if(tcgetattr(fd, &config) < 0) {
|
||||
perror("tcgetattr");
|
||||
exit(EXIT_FAILURE);
|
||||
};
|
||||
//
|
||||
// Input flags - Turn off input processing
|
||||
// convert break to null byte, no CR to NL translation,
|
||||
// no NL to CR translation, don't mark parity errors or breaks
|
||||
// no input parity check, don't strip high bit off,
|
||||
// no XON/XOFF software flow control
|
||||
//
|
||||
config.c_iflag &= ~(IGNBRK | BRKINT | ICRNL |
|
||||
INLCR | PARMRK | INPCK | ISTRIP | IXON);
|
||||
//
|
||||
// Output flags - Turn off output processing
|
||||
// no CR to NL translation, no NL to CR-NL translation,
|
||||
// no NL to CR translation, no column 0 CR suppression,
|
||||
// no Ctrl-D suppression, no fill characters, no case mapping,
|
||||
// no local output processing
|
||||
//
|
||||
// config.c_oflag &= ~(OCRNL | ONLCR | ONLRET |
|
||||
// ONOCR | ONOEOT| OFILL | OLCUC | OPOST);
|
||||
config.c_oflag = 0;
|
||||
//
|
||||
// No line processing:
|
||||
// echo off, echo newline off, canonical mode off,
|
||||
// extended input processing off, signal chars off
|
||||
//
|
||||
config.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
|
||||
//
|
||||
// Turn off character processing
|
||||
// clear current char size mask, no parity checking,
|
||||
// no output processing, force 8 bit input
|
||||
//
|
||||
config.c_cflag &= ~(CSIZE | PARENB);
|
||||
config.c_cflag |= CS8;
|
||||
//
|
||||
// One input byte is enough to return from read()
|
||||
// Inter-character timer off
|
||||
//
|
||||
config.c_cc[VMIN] = 1;
|
||||
config.c_cc[VTIME] = 0;
|
||||
//
|
||||
// Communication speed (simple version, using the predefined
|
||||
// constants)
|
||||
//
|
||||
/*
|
||||
if(cfsetispeed(&config, B9600) < 0 || cfsetospeed(&config, B9600) < 0) {
|
||||
perror("cfset[io]speed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
*/
|
||||
//
|
||||
// Finally, apply the configuration
|
||||
//
|
||||
if(tcsetattr(fd, TCSAFLUSH, &config) < 0) {
|
||||
perror("tcsetattr");
|
||||
exit(EXIT_FAILURE);
|
||||
};
|
||||
};
|
||||
|
||||
/* Reference is https://r0ket.badge.events.ccc.de/tracking:reader */
|
||||
void pkt_cleanup(int idx){
|
||||
static u_int32_t ctr;
|
||||
|
||||
buffer[BUFIDX(idx)+2]=1; // BEACONLOG_SIGHTING
|
||||
buffer[BUFIDX(idx)+3]=0; // interface 0
|
||||
*(u_int16_t*)(buffer+BUFIDX(idx)+4)=htons(1234); // reader id
|
||||
*(u_int16_t*)(buffer+BUFIDX(idx)+6)=htons(32); // size
|
||||
*(u_int32_t*)(buffer+BUFIDX(idx)+8)=htonl(ctr++);
|
||||
*(u_int32_t*)(buffer+BUFIDX(idx)+12)=htonl(the_time);
|
||||
|
||||
*(u_int16_t*)(buffer+BUFIDX(idx)+0)=htons(0xffff ^ crc16(buffer+BUFIDX(idx)+2,30));
|
||||
}
|
||||
|
||||
void write_r0ket(int fd,char * buf,int len){
|
||||
int r;
|
||||
r=write(fd,buf,len);
|
||||
if(r!=len){
|
||||
printf("wrote only %d bytes of %d to device\n",r,len);
|
||||
exit(EXIT_FAILURE);
|
||||
};
|
||||
}
|
||||
|
||||
void setup_r0ket(int fd){
|
||||
unsigned char buf[256];
|
||||
int x,r;
|
||||
u_int32_t uuid=0;
|
||||
|
||||
write_r0ket(fd,"\\7\\0",4); /* Get UUID */
|
||||
write_r0ket(fd,"\\4\001\002\003\002\001\\0",9); /* Set rx_mac */
|
||||
write_r0ket(fd,"\\5\x51\\0",5); /* Set channel */
|
||||
write_r0ket(fd,"\\6\x10\\0",5); /* Set rx_len */
|
||||
|
||||
usleep(100000); /* wait 100ms for an answer */
|
||||
r=read(fd,buf,sizeof(buf));
|
||||
/* try to find uuid in reply. Could be nicer, but it works. */
|
||||
if(r>7){
|
||||
for(x=0;x<r-7;x++){
|
||||
if(buf[x]=='\\' && buf[x+1]=='7' &&
|
||||
buf[x+6]=='\\' && buf[x+7] == '0'){
|
||||
uuid=ntohl(*(u_int32_t*)(buf+x+2));
|
||||
break;
|
||||
};
|
||||
};
|
||||
};
|
||||
if(uuid){
|
||||
printf("uuid=%x\n",uuid);
|
||||
return;
|
||||
}else{
|
||||
printf("No uuid?\n");
|
||||
exit(EXIT_FAILURE);
|
||||
};
|
||||
};
|
||||
|
||||
signed int read_r0ket(int fd){
|
||||
int r,t,o,x;
|
||||
static unsigned char data[64];
|
||||
static unsigned char offset=0;
|
||||
static unsigned char firstread=1;
|
||||
|
||||
r=read(fd,data+offset,sizeof(data)-offset);
|
||||
if(r<0){
|
||||
perror("read(device)");
|
||||
exit(EXIT_FAILURE);
|
||||
};
|
||||
if(r==0){
|
||||
printf("eof(device)");
|
||||
close(fd);
|
||||
return -1;
|
||||
};
|
||||
#if 0
|
||||
for(t=offset;t<offset+r;t++){
|
||||
printf("%02x",data[t]);
|
||||
};
|
||||
printf (" read %d bytes, offset was %d\n",r,offset);
|
||||
#endif
|
||||
r+=offset;
|
||||
offset=0;
|
||||
|
||||
/* find frame start */
|
||||
while(data[0] != '\\' && r>0){
|
||||
if(!firstread)
|
||||
printf("ignoring garbage: %02X\n",data[0]);
|
||||
memmove(data,data+1,sizeof(data)-1);
|
||||
r--;
|
||||
};
|
||||
if(r==0){ /* no data left */
|
||||
return 0;
|
||||
};
|
||||
|
||||
if(data[1]=='1'){
|
||||
firstread=0;
|
||||
/* find frame end */
|
||||
for(x=2;x<r-1;x++){
|
||||
if(data[x]=='\\' && data[x+1]=='0')
|
||||
break;
|
||||
}
|
||||
if(x>=r-1){ /* no EOF found */
|
||||
if(r>60){
|
||||
printf("serial frame content overflow\n");
|
||||
return 0;
|
||||
};
|
||||
offset=r; /* keep unused data for next round */
|
||||
return 0;
|
||||
};
|
||||
|
||||
// printf("consume %d: ",x);
|
||||
o=16;
|
||||
BUFPUSH();
|
||||
for(t=2;t<x;t++){
|
||||
if(o>=ELEMSIZE) /* "buffer" overflow protection */
|
||||
break;
|
||||
buffer[BUFIDX(bufend)+o]=data[t];
|
||||
if(data[t]!='\\')
|
||||
o++;
|
||||
// printf("%02x",data[t]);
|
||||
};
|
||||
pkt_cleanup(bufend);
|
||||
x+=2; /* also consume end of frame marker */
|
||||
// printf("\n");
|
||||
}else if(data[1]=='7'){ /* beaconid frame */
|
||||
/* find frame end */
|
||||
for(x=2;x<r-1;x++){
|
||||
if(data[x]=='\\' && data[x+1]=='0')
|
||||
break;
|
||||
}
|
||||
if(x>=r-1){ /* no EOF found */
|
||||
if(r>60){
|
||||
printf("serial frame content overflow\n");
|
||||
return 0;
|
||||
};
|
||||
offset=r; /* keep unused data for next round */
|
||||
return 0;
|
||||
};
|
||||
/* XXX: do something with beaconid */
|
||||
BUFPUSH();
|
||||
for(t=0;t<16;t++){ /* clear buffer */
|
||||
buffer[BUFIDX(bufend)+16+t]=0;
|
||||
};
|
||||
buffer[BUFIDX(bufend)+16]=22; // RFBPROTO_READER_ANNOUNCE
|
||||
*(u_int16_t*)(buffer+BUFIDX(bufend)+16+14)= \
|
||||
htons(crc16(buffer+BUFIDX(bufend)+16,14));
|
||||
pkt_cleanup(bufend);
|
||||
x=8;
|
||||
}else if(data[1]=='2'){ /* command ack frame */
|
||||
x=4; /* just consume, and do nothing */
|
||||
}else{
|
||||
if(!firstread)
|
||||
printf("invalid frame type: %02x\n",data[1]);
|
||||
x=2;
|
||||
};
|
||||
if(x==r) /* all data consumed */
|
||||
return 0;
|
||||
/* keep unconsumed data */
|
||||
memmove(data,data+x,r-x);
|
||||
offset=r-x;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void write_socket(int sockfd){
|
||||
BUFPOP();
|
||||
if (send(sockfd, buffer+BUFIDX(bufstart), ELEMSIZE, 0)==-1){
|
||||
perror("send");
|
||||
// exit(EXIT_FAILURE);
|
||||
};
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv){
|
||||
int c; /* getopt return value */
|
||||
char *device="/dev/ttyACM0";
|
||||
int devfd=-1,sockfd=-1,listenfd=-1; /* FD for device & socket */
|
||||
int maxfd=0;
|
||||
int cnt;
|
||||
fd_set rset,wset; /* file descriptors for select() */
|
||||
struct timeval timeout; /* Timeout for select */
|
||||
struct sockaddr_in si_other; /* target socket */
|
||||
time_t ot,heartbeat=0;
|
||||
|
||||
time(&ot);
|
||||
|
||||
/* The big getopt loop */
|
||||
while ((c = getopt(argc, argv, "s:d:")) != EOF)
|
||||
switch (c)
|
||||
{
|
||||
case 'd':
|
||||
device=(char *)malloc(strlen(optarg)+2);
|
||||
strcpy(device,optarg);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
SRV_IP=(char *)malloc(strlen(optarg)+2);
|
||||
strcpy(SRV_IP,optarg);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Usage: %s [options] \n\n\
|
||||
This program reads packets from an USB-Serial R0ket\n\
|
||||
and sends them off via TCP/UDP to a central host\n\n\
|
||||
-d <device> Open a different device instead of '%s'\n\
|
||||
-h This help\n",
|
||||
argv[0],
|
||||
device
|
||||
);
|
||||
exit(255);
|
||||
}
|
||||
|
||||
/* argc -= optind; argv += optind; *//* only if we want more args */
|
||||
|
||||
/* Open & prep input device */
|
||||
if((devfd=open(device,O_RDWR)) == -1){
|
||||
perror("open(device)");
|
||||
exit(EXIT_FAILURE);
|
||||
};
|
||||
setupserial(devfd);
|
||||
setnonblocking(devfd);
|
||||
setup_r0ket(devfd);
|
||||
|
||||
/* Open & prep outout device */
|
||||
#ifdef TYPE_UDP
|
||||
if ((sockfd=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1){
|
||||
perror("socket(udp)");
|
||||
exit(EXIT_FAILURE);
|
||||
};
|
||||
memset((char *) &si_other, 0, sizeof(si_other));
|
||||
si_other.sin_family = AF_INET;
|
||||
si_other.sin_port = htons(PORT);
|
||||
if (inet_aton(SRV_IP, &si_other.sin_addr)==0) {
|
||||
perror("inet_aton()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if(connect(sockfd,(struct sockaddr*)&si_other,sizeof(si_other))<0){
|
||||
perror("connect");
|
||||
exit(EXIT_FAILURE);
|
||||
};
|
||||
setnonblocking(sockfd);
|
||||
#endif
|
||||
#ifdef TYPE_TCP
|
||||
if((listenfd = socket(AF_INET, SOCK_STREAM, 0))<0){
|
||||
perror("socket(tcpserver)");
|
||||
exit(EXIT_FAILURE);
|
||||
};
|
||||
memset((char *) &si_other, 0, sizeof(si_other));
|
||||
si_other.sin_family = AF_INET;
|
||||
si_other.sin_addr.s_addr = INADDR_ANY;
|
||||
si_other.sin_port = htons(PORT);
|
||||
if(bind(listenfd,(struct sockaddr*)&si_other,sizeof(si_other))<0){
|
||||
perror("bind");
|
||||
exit(EXIT_FAILURE);
|
||||
};
|
||||
if(listen(listenfd,1)!=0){
|
||||
perror("listen");
|
||||
exit(EXIT_FAILURE);
|
||||
};
|
||||
#endif
|
||||
|
||||
while(1){
|
||||
/* prepare stuff for select */
|
||||
timeout.tv_sec = 1;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
if(devfd>maxfd)
|
||||
maxfd=devfd;
|
||||
if(sockfd>maxfd)
|
||||
maxfd=sockfd;
|
||||
if(listenfd>maxfd)
|
||||
maxfd=listenfd;
|
||||
|
||||
FD_ZERO(&rset);
|
||||
if(devfd==-1){
|
||||
fprintf(stderr,"Can't yet deal with disappearing device\n");
|
||||
exit(EXIT_FAILURE);
|
||||
};
|
||||
FD_SET(devfd,&rset);
|
||||
if(sockfd!=-1){
|
||||
#ifdef TYPE_TCP
|
||||
FD_SET(sockfd,&rset);
|
||||
#endif
|
||||
}else if(listenfd!=-1){
|
||||
FD_SET(listenfd,&rset);
|
||||
};
|
||||
|
||||
FD_ZERO(&wset);
|
||||
if(bufstart!=bufend && sockfd!=-1){
|
||||
FD_SET(sockfd,&wset);
|
||||
};
|
||||
|
||||
cnt = select(maxfd+1, &rset, &wset, NULL, &timeout);
|
||||
|
||||
|
||||
/* First run timer stuff */
|
||||
time(&the_time);
|
||||
if(the_time-ot>=INTERVAL){
|
||||
ot=the_time;
|
||||
printf("[running: buf=%d, sockfd=%d]\n",(BUFSIZE+bufend-bufstart)%BUFSIZE,sockfd);
|
||||
};
|
||||
|
||||
if(the_time-heartbeat>=1){
|
||||
heartbeat=the_time;
|
||||
write_r0ket(devfd,"\\7\\0",4); /* Get UUID */
|
||||
};
|
||||
|
||||
/* Now check select / fds*/
|
||||
if (cnt<0){
|
||||
perror("select");
|
||||
exit(EXIT_FAILURE);
|
||||
};
|
||||
|
||||
if (cnt==0){ /* timeout */
|
||||
printf("[timeout]\n");
|
||||
continue;
|
||||
};
|
||||
|
||||
if (FD_ISSET(devfd,&rset)){
|
||||
if(read_r0ket(devfd)<0){
|
||||
close(devfd);
|
||||
devfd=-1;
|
||||
};
|
||||
if(--cnt ==0) continue;
|
||||
};
|
||||
|
||||
if (sockfd!=-1 && FD_ISSET(sockfd,&rset)){
|
||||
int r;
|
||||
unsigned char dummy[32];
|
||||
r=read(sockfd,dummy,32);
|
||||
if(r<0){
|
||||
perror("read(socket)");
|
||||
exit(EXIT_FAILURE);
|
||||
};
|
||||
if(r==0){
|
||||
printf("eof() on socket\n");
|
||||
close(sockfd);
|
||||
sockfd=-1;
|
||||
};
|
||||
if(r>0){
|
||||
printf("read [%d] bytes from socket and ignored them.\n",r);
|
||||
};
|
||||
|
||||
if(--cnt ==0) continue;
|
||||
};
|
||||
|
||||
if (sockfd!=-1 && FD_ISSET(sockfd,&wset)){
|
||||
write_socket(sockfd);
|
||||
if(--cnt ==0) continue;
|
||||
};
|
||||
|
||||
if (listenfd!=-1 && FD_ISSET(listenfd,&rset)){
|
||||
if(sockfd!=-1){ // close old connection
|
||||
close(sockfd);
|
||||
};
|
||||
unsigned int size=sizeof(si_other);
|
||||
if((sockfd=accept(listenfd,(struct sockaddr*)&si_other,&size))<0){
|
||||
perror("accept");
|
||||
continue; // Do not exit, we can handle this :-)
|
||||
};
|
||||
printf("New connection from %s (fd %d)\n", inet_ntoa(si_other.sin_addr), sockfd);
|
||||
if(--cnt ==0) continue;
|
||||
};
|
||||
|
||||
printf("unknwon select left over: cnt=%d, ",cnt);
|
||||
printf("rset: ");
|
||||
for(cnt=0;cnt<maxfd+1;cnt++){
|
||||
printf(FD_ISSET(cnt,&rset)?"1":"0");
|
||||
};
|
||||
printf("wset: ");
|
||||
for(cnt=0;cnt<maxfd+1;cnt++){
|
||||
printf(FD_ISSET(cnt,&wset)?"1":"0");
|
||||
};
|
||||
printf("\n");
|
||||
};
|
||||
return(0);
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use POSIX ":sys_wait_h"; # for nonblocking read
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/lib";
|
||||
use lib "$FindBin::Bin/../mesh/lib";
|
||||
use r0ket;
|
||||
use l0gger;
|
||||
|
||||
$|=1;
|
||||
|
||||
my $DEV="/dev";
|
||||
|
||||
my %run;
|
||||
my %childs;
|
||||
my %config;
|
||||
|
||||
my @exec;
|
||||
|
||||
$SIG{CHLD} = sub {
|
||||
# don't change $! and $? outside handler
|
||||
local ($!, $?);
|
||||
my $pid = waitpid(-1, WNOHANG);
|
||||
return if $pid == -1;
|
||||
return unless defined $childs{$pid};
|
||||
delete $run{$childs{$pid}}; # cleanup?
|
||||
delete $childs{$pid};
|
||||
};
|
||||
|
||||
# read config
|
||||
|
||||
sub readcfg{
|
||||
%config=();
|
||||
open(R,"<","reader.cf")|| die "Can't find reader.cf\n";
|
||||
while(<R>){
|
||||
chomp;
|
||||
next unless /(.*?)=(.*)/;
|
||||
$config{$1}=$2;
|
||||
};
|
||||
close(R);
|
||||
@exec=$config{"prog"},split(/\s+/,$config{"args"});
|
||||
delete $config{prog};
|
||||
delete $config{args};
|
||||
};
|
||||
|
||||
readcfg();
|
||||
l0gger::init();
|
||||
|
||||
while(1){
|
||||
opendir(my $dh, $DEV);
|
||||
my @paths=grep {/^ttyACM/} readdir($dh);
|
||||
close $dh;
|
||||
# print "f: ",join(",",@files),"\n";
|
||||
for my $path (@paths){
|
||||
next if $run{$path};
|
||||
|
||||
my $id = eval {
|
||||
r0ket::r0ket_init($DEV."/".$path);
|
||||
return r0ket::get_id();
|
||||
};
|
||||
# print "r0id: $id\n";
|
||||
if(!defined $config{$id}){
|
||||
print "No config for r0ket $id @ $path, skipping...\n";
|
||||
next;
|
||||
};
|
||||
$run{$path}=$id;
|
||||
|
||||
my $pid = fork();
|
||||
die "cannot fork" unless defined $pid;
|
||||
if ($pid == 0) {
|
||||
exec @exec,'-d',$DEV."/".$path,'-i',$config{$id};
|
||||
} else {
|
||||
print "Started $path : $id @ $pid\n";
|
||||
l0gger::send("started $path : $id @ $pid");
|
||||
$childs{$pid}=$path;
|
||||
}
|
||||
};
|
||||
sleep(1);
|
||||
print join(",",map {$run{$childs{$_}}."@".$childs{$_}."[$_]"} sort {$childs{$a}cmp$childs{$b}} keys %childs),"\n";
|
||||
};
|
Loading…
Reference in New Issue