#!/usr/bin/env python #GoodFET Chipcon SPI Client # (C) 2011 Travis Goodspeed #N.B., #Might be CC2420 Specific import sys; import binascii; import array, time; from GoodFETCCSPI import GoodFETCCSPI; if(len(sys.argv)==1): print "Usage: %s verb [objects]\n" % sys.argv[0]; print "%s info" % sys.argv[0]; print "%s regs" % sys.argv[0]; print "%s test" % sys.argv[0]; print "%s peek 0x$start [0x$stop]" % sys.argv[0]; print "%s poke 0x$adr 0x$val" % sys.argv[0]; print "%s txtest" % sys.argv[0]; print "\n%s rssi" % sys.argv[0]; print "%s sniff [chan]" % sys.argv[0]; print "%s bsniff [chan]" % sys.argv[0]; print "%s sniffdissect" % sys.argv[0]; print "\n%s txtoscount [-i|-r] TinyOS BlinkToLED" % sys.argv[0]; print "%s reflexjam [channel=11] [delay=0]" % sys.argv[0]; sys.exit(); #Initialize FET and set baud rate client=GoodFETCCSPI(); client.serInit() client.setup(); #Dummy read. #Might read as all ones if chip has a startup delay. if(sys.argv[1]=="carrier"): if len(sys.argv)>2: client.RF_setfreq(eval(sys.argv[2])); while 1: client.RF_carrier(); while(1): time.sleep(1); if(sys.argv[1]=="modulated_spectrum"): if len(sys.argv)>2: client.RF_setfreq(eval(sys.argv[2])); while 1: client.RF_modulated_spectrum(); while(1): time.sleep(1); if(sys.argv[1]=="reflexjam" or sys.argv[1]=="reflexjamack"): #Setup the radio to listen promiscously on a frequency client.RF_promiscuity(1); client.RF_autocrc(0); if len(sys.argv)>2: freq=eval(sys.argv[2]); if freq>100: client.RF_setfreq(freq); else: client.RF_setchan(freq); duration=0; if len(sys.argv)>3: duration=eval(sys.argv[3]); client.CC_RFST_RX(); print "Reflexively jamming on %i MHz" % (client.RF_getfreq()/10**6); #Now we let the firmware take over, watching for packets and jamming them. if sys.argv[1]=="reflexjam": client.RF_reflexjam(duration); elif sys.argv[1]=="reflexjamack": client.RF_reflexjam_autoack(); if(sys.argv[1]=="info"): print "Found %s" % client.identstr(); print "Freq: %05f MHz" % (client.RF_getfreq()/(10**6)); print "Status: %s" % client.status(); if(sys.argv[1]=="regs"): for adr in range(0x10,0x40): #*1024): val=client.peek(adr); print "%04x:=0x%04x" % (adr,val); if(sys.argv[1]=="test"): data=client.trans([0x20, 0xde, 0xad]); print "%02x %02x" % (ord(data[1]), ord(data[2])); data=client.trans([0x40|0x20, 0xde, 0xad]); print "%02x %02x" % (ord(data[1]), ord(data[2])); if(sys.argv[1]=="rssi"): if len(sys.argv)>2: freq=eval(sys.argv[2]); if freq>100: client.RF_setfreq(freq); else: client.RF_setchan(freq); print "Listening on %f MHz." % (client.RF_getfreq()/10.0**6); client.strobe(0x02); #Calibrate time.sleep(1); while 1: client.CC_RFST_RX(); #client.strobe(0x03); #SRXON rssi=client.RF_getrssi(); #client.CC_RFST_IDLE(); #idle time.sleep(0.01); string=""; for foo in range(0,rssi>>2): string=("%s."%string); print "%02x %04i %s" % (rssi,rssi, string); if(sys.argv[1]=="sniff" or sys.argv[1]=="sniffdissect"): #Promiscuous mode. client.RF_promiscuity(1); client.RF_autocrc(0); if len(sys.argv)>2: freq=eval(sys.argv[2]); if freq>100: client.RF_setfreq(freq); else: client.RF_setchan(freq); client.CC_RFST_RX(); print "Listening as %010x on %i MHz" % (client.RF_getsmac(), client.RF_getfreq()/10**6); #Now we're ready to get packets. while 1: packet=None; while packet==None: packet=client.RF_rxpacket(); if sys.argv[1]=="sniffdissect": client.printdissect(packet); else: client.printpacket(packet); sys.stdout.flush(); if(sys.argv[1]=="bsniff"): #Just broadcast. client.RF_promiscuity(0); client.RF_setsmac(0xFFFFFFFF); client.RF_autocrc(1); if len(sys.argv)>2: freq=eval(sys.argv[2]); if freq>100: client.RF_setfreq(freq); else: client.RF_setchan(freq); client.CC_RFST_RX(); print "Listening as %010x on %i MHz" % (client.RF_getsmac(), client.RF_getfreq()/10**6); #Now we're ready to get packets. while 1: packet=None; while packet==None: packet=client.RF_rxpacket(); client.printpacket(packet); sys.stdout.flush(); if(sys.argv[1]=="txtest"): if len(sys.argv)>2: freq=eval(sys.argv[2]); if freq>100: client.RF_setfreq(freq); else: client.RF_setchan(freq); print "Transmitting DEADBEEF as %010x on %i MHz" % ( client.RF_getsmac(), client.RF_getfreq()/10**6); while 1: client.RF_txpacket([0x0f, 0x01, 0x08, 0x82, 0xff, 0xff, 0xff, 0xff, 0xde, 0xad, 0xbe, 0xef, 0xba, 0xbe, 0xc0]); if(sys.argv[1]=="txtoscount"): ''' Clone of what TinyOS's RadioCountToLeds demo code does. Specify a channel a TinyOS mote programmed with RadioCountToLeds is on, and this will act as the second device. ''' if (len(sys.argv)<=3): print "Provide -r to work via replays or -i to work via incrementing itself."; sys.exit(1); if (sys.argv[3]=="-r"): client.RF_promiscuity(1); client.RF_autocrc(1); if len(sys.argv)>2: freq=eval(sys.argv[2]); if freq>100: client.RF_setfreq(freq); else: client.RF_setchan(freq); if (sys.argv[3]=="-r"): client.CC_RFST_RX(); print "Listening as %010x on %i MHz" % (client.RF_getsmac(), client.RF_getfreq()/10**6); print "Transmitting like the TinyOS CountToRadio program on %i MHz" % (client.RF_getfreq()/10**6); if (sys.argv[3]=="-i"): i = 0; countpkt = [0x0f, 0x41, 0x88, 0xFF, 0x22, 0x00, 0xff, 0xff, 0x01, 0x00, 0x3f, 0x06, 0x00, 0xFF]; while 1: if (sys.argv[3]=="-r"): #give -r to do via replays from the other device packet=None; while packet==None: packet=client.RF_rxpacket(); pkt = packet[:14]; client.RF_txpacket(pkt); elif (sys.argv[3]=="-i"): #give -i to have it increment and send #Use this code for it to actually do increments itself: pkt = countpkt[:]; pkt[3] = i; pkt[13] = i+1; client.RF_txpacket(pkt); if i >= 31: i = 0; else: i += 1; time.sleep(0.5); if(sys.argv[1]=="txpiptest" or sys.argv[1]=="txpipscapy"): if len(sys.argv)>2: freq=eval(sys.argv[2]); if freq>100: client.RF_setfreq(freq); else: client.RF_setchan(freq); print "Transmitting on as %010x on %i MHz" % ( client.RF_getsmac(), client.RF_getfreq()/10**6); client.RF_setsync(0xFFFF); while 1: if(sys.argv[1]=="txpiptest"): client.RF_txpacket([ 0x7f, #Real header, must begin with SFD. 0x00, 0x00, 0x00, 0x00, 0xA7, #Length 0x1f, 0x01, 0x08, 0x82, 0xDF, 0xff, 0xff, 0xff, 0xde, 0xad, 0xbe, 0xef, 0xba, 0xbe, 0xc0, #Preamble 0x00, 0x00, 0x00, #SFD 0x00, 0xA7, #CC2420 SFD #Packet In Packet 0x0f, 0x01, 0x08, 0x82, 0xff, 0xff, 0xff, 0xff, 0xde, 0xad, 0xbe, 0xef, 0xba, 0xbe, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ]); elif(sys.argv[1]=="txpipscapy"): try: from scapy.all import Dot15d4, Dot15d4FCS, Dot15d4Data, Raw import struct except ImportError: print "To use packet building, Scapy must be installed and have the dot15d4 extension present." print "try: hg clone http://hg.secdev.org/scapy-com"; print " sudo ./setup.py install"; #Overall method is to build from the inner packet outwards in the pkt string # Make inner packet scapyinner = Dot15d4FCS(seqnum=130)/Dot15d4Data()/Raw('\xde\xad\xbe\xef'); #pkt = str(scapyinner)[:-2] + '\xba\xbe\xc0'; pkt = str(scapyinner); #build inner pkt to bytes, adding FCS automatically #pkt = '\x0f'+pkt pkt = struct.pack('b', len(pkt)) + pkt #prepend with its length pkt = "\x00\x00\x00\x00\xA7" + pkt #add preamble and SFD to inner packet # Make outer (wrapping) packet scapyouter = Dot15d4(seqnum=130)/Dot15d4Data(dest_panid=0xffdf)/Raw('\xde\xad\xbe\xef\xba\xbe\xc0') #TODO why need these last 3 bytes? pkt = str(scapyouter) + pkt pkt = struct.pack('b', len(pkt)) + pkt #prepend with its length pkt = '\x00\x00\x00\x00\xA7' + pkt + ('\xff'*28) #start with preamble/SFD and add 0xff fill at end pkt = struct.pack('b', len(pkt)) + pkt #prepend with its length (originally used \x7f) client.printpacket(pkt) client.RF_autocrc(1); client.RF_txpacket(pkt) if(sys.argv[1]=="peek"): start=0x0000; if(len(sys.argv)>2): start=int(sys.argv[2],16); stop=start; if(len(sys.argv)>3): stop=int(sys.argv[3],16); print "Peeking from %04x to %04x." % (start,stop); while start<=stop: print "%04x: 0x%04x" % (start,client.peek(start)); start=start+1; if(sys.argv[1]=="poke"): start=0x0000; val=0x00; if(len(sys.argv)>2): start=int(sys.argv[2],16); if(len(sys.argv)>3): val=int(sys.argv[3],16); print "Poking r%02x to become 0x%04x." % (start,val); client.poke(start,val);