Package killerbee :: Module dev_rzusbstick
[hide private]
[frames] | no frames]

Source Code for Module killerbee.dev_rzusbstick

  1  # Import USB support depending on version of pyUSB 
  2  try: 
  3      import usb.core 
  4      import usb.util 
  5      USBVER=1 
  6      import sys 
  7      print >>sys.stderr, "Warning: You are using pyUSB 1.x, support is in beta." 
  8  except ImportError: 
  9      import usb 
 10      #print("Warning: You are using pyUSB 0.x, future deprecation planned.") 
 11      USBVER=0 
 12   
 13  import time 
 14  import struct 
 15  from datetime import datetime 
 16  from kbutils import KBCapabilities 
 17   
 18  # Functions for RZUSBSTICK, not all are implemented in firmware 
 19  # Functions not used are commented out but retained for prosperity 
 20  #RZ_CMD_SIGN_OFF             = 0x00 
 21  #RZ_CMD_SIGN_ON              = 0x01 
 22  #RZ_CMD_GET_PARAMETER        = 0x02 
 23  #RZ_CMD_SET_PARAMETER        = 0x03 
 24  #RZ_CMD_SELF_TEST            = 0x04 
 25  #RZ_CMD_CHECK_STACK_USAGE    = 0x05 
 26  #RZ_CMD_MEMORY_TEST          = 0x06 
 27  RZ_CMD_SET_MODE             = 0x07  #: RZUSB opcode to specify operating mode 
 28  RZ_CMD_SET_CHANNEL          = 0x08  #: RZUSB opcode to specify the channel 
 29  RZ_CMD_OPEN_STREAM          = 0x09  #: RZUSB opcode to open a stream for packet injection 
 30  RZ_CMD_CLOSE_STREAM         = 0x0A  #: RZUSB opcode to close a stream for packet injection 
 31  #RZ_CMD_CHANNEL_SCAN         = 0x0B 
 32  #RZ_CMD_CHANNEL_SCAN_STOP    = 0x0C 
 33  RZ_CMD_INJECT_FRAME         = 0x0D  #: RZUSB opcode to specify a frame to inject 
 34  RZ_CMD_JAMMER_ON            = 0x0E  #: RZUSB opcode to turn the jammer function on 
 35  RZ_CMD_JAMMER_OFF           = 0x0F  #: RZUSB opcode to turn the jammer function off 
 36   
 37  # Operating modes following RZ_CMD_SET_MODE function 
 38  RZ_CMD_MODE_AC              = 0x00  #: RZUSB mode for aircapture (inject + sniff) 
 39  #RZ_CMD_MODE_HAL             = 0x01 
 40  #RZ_CMD_MODE_MAC             = 0x02 
 41  #RZ_CMD_MODE_NWK             = 0x03 
 42  RZ_CMD_MODE_NONE            = 0x04 #: RZUSB no mode specified 
 43   
 44  RZ_RESP_LOCAL_TIMEOUT       = 0x00 #: RZUSB Response: Local Timeout Error 
 45  RZ_RESP_SUCCESS             = 0x80 #: RZUSB Response: Success 
 46  RZ_RESP_SYNTACTICAL_ERROR   = 0x81 #: RZUSB Response: Syntactical Error 
 47  RZ_RESP_SEMANTICAL_ERROR    = 0x82 #: RZUSB Response: Semantical Error 
 48  RZ_RESP_HW_TIMEOUT          = 0x83 #: RZUSB Response: Hardware Timeout 
 49  RZ_RESP_SIGN_ON             = 0x84 #: RZUSB Response: Sign On 
 50  RZ_RESP_GET_PARAMETER       = 0x85 #: RZUSB Response: Get Parameter 
 51  RZ_RESP_TRX_READ_REGISTER   = 0x86 #: RZUSB Response: Transceiver Read Register Error 
 52  RZ_RESP_TRX_READ_FRAME      = 0x87 #: RZUSB Response: Transceiver Read Frame Error 
 53  RZ_RESP_TRX_READ_SRAM       = 0x88 #: RZUSB Response: Transceiver Read SRAM Error 
 54  RZ_RESP_TRX_GET_PIN         = 0x89 #: RZUSB Response: Transceiver Get PIN Error 
 55  RZ_RESP_TRX_BUSY            = 0x8A #: RZUSB Response: Transceiver Busy Error 
 56  RZ_RESP_PRITMITIVE_FAILED   = 0x8B #: RZUSB Response: Primitive Failed Error 
 57  RZ_RESP_PRITMITIVE_UNKNOWN  = 0x8C #: RZUSB Response: Primitive Unknown Error 
 58  RZ_RESP_COMMAND_UNKNOWN     = 0x8D #: RZUSB Response: Command Unknown Error 
 59  RZ_RESP_BUSY_SCANING        = 0x8E #: RZUSB Response: Busy Scanning Error 
 60  RZ_RESP_BUSY_CAPTURING      = 0x8F #: RZUSB Response: Busy Capturing Error 
 61  RZ_RESP_OUT_OF_MEMORY       = 0x90 #: RZUSB Response: Out of Memory Error  
 62  RZ_RESP_BUSY_JAMMING        = 0x91 #: RZUSB Response: Busy Jamming Error 
 63  RZ_RESP_NOT_INITIALIZED     = 0x92 #: RZUSB Response: Not Initialized Error 
 64  RZ_RESP_NOT_IMPLEMENTED     = 0x93 #: RZUSB Response: Opcode Not Implemented Error 
 65  RZ_RESP_PRIMITIVE_FAILED    = 0x94 #: RZUSB Response: Primitive Failed Error 
 66  RZ_RESP_VRT_KERNEL_ERROR    = 0x95 #: RZUSB Response: Could not execute due to vrt_kernel_error 
 67  RZ_RESP_BOOT_PARAM          = 0x96 #: RZUSB Response: Boot Param Error 
 68   
 69  RZ_EVENT_STREAM_AC_DATA          = 0x50 #: RZUSB Event Opcode: AirCapture Data 
 70  #RZ_EVENT_SNIFFER_SCAN_COMPLETE   = 0x51 #: RZUSB Event Opcode: Sniffer Scan Complete 
 71  #RZ_EVENT_SNIFFER_ERROR           = 0x52 #: RZUSB Event Opcode: Sniffer Error 
 72  #RZ_EVENT_NWK_DATA                = 0x53 #: RZUSB Event Opcode: NWK Data 
 73  #RZ_EVENT_NWK_JOIN                = 0x54 #: RZUSB Event Opcode: NWK Join Event 
 74  #RZ_EVENT_NWK_LEAVE               = 0x55 #: RZUSB Event Opcode: NWK Leave Event 
 75   
 76   
 77  RESPONSE_MAP = {RZ_RESP_LOCAL_TIMEOUT: "Local Timeout Error", 
 78                  RZ_RESP_SUCCESS : "Success", 
 79                  RZ_RESP_SYNTACTICAL_ERROR : "Syntactical Error", 
 80                  RZ_RESP_SEMANTICAL_ERROR : "Semantical Error", 
 81                  RZ_RESP_HW_TIMEOUT : "Hardware Timeout", 
 82                  RZ_RESP_SIGN_ON : "Sign On", 
 83                  RZ_RESP_GET_PARAMETER : "Get Parameter", 
 84                  RZ_RESP_TRX_READ_REGISTER : "Transceiver Read Register", 
 85                  RZ_RESP_TRX_READ_FRAME : "Transceiver Read Frame", 
 86                  RZ_RESP_TRX_READ_SRAM : "Transceiver Read SRAM", 
 87                  RZ_RESP_TRX_GET_PIN : "Transceiver Get PIN", 
 88                  RZ_RESP_TRX_BUSY : "Transceiver Busy", 
 89                  RZ_RESP_PRITMITIVE_FAILED : "Primitive Failed", 
 90                  RZ_RESP_PRITMITIVE_UNKNOWN : "Unknown Primitive", 
 91                  RZ_RESP_COMMAND_UNKNOWN : "Unknown Command", 
 92                  RZ_RESP_BUSY_SCANING : "Busy Scanning", 
 93                  RZ_RESP_BUSY_CAPTURING : "Busy Capturing", 
 94                  RZ_RESP_OUT_OF_MEMORY : "Out of Memory", 
 95                  RZ_RESP_BUSY_JAMMING : "Busy Jamming", 
 96                  RZ_RESP_NOT_INITIALIZED : "Not Initialized", 
 97                  RZ_RESP_NOT_IMPLEMENTED : "Not Implemented by USB firmware", 
 98                  RZ_RESP_PRIMITIVE_FAILED : "Primitive Failed", 
 99                  RZ_RESP_VRT_KERNEL_ERROR : "Could not execute due to vrt_kernel_error", 
100                  RZ_RESP_BOOT_PARAM : "Boot Param Error"} #: Dictionary of RZUSB error to strings 
101   
102  RZ_USB_VEND_ID                = 0x03EB #: RZUSB USB VID 
103  RZ_USB_PROD_ID                = 0x210A #: RZUSB USB PID 
104  RZ_USB_COMMAND_EP             = 0x02 #: RZUSB USB Command Endpoint Identifier 
105  RZ_USB_RESPONSE_EP            = 0x84 #: RZUSB USB Response Endpoint Identifier 
106  RZ_USB_PACKET_EP              = 0x81 #: RZUSB USB Packet Endpoint Identifier 
107   
108 -class RZUSBSTICK:
109 - def __init__(self, dev, bus):
110 #TODO deprecate bus param, and dev becomes a usb.core.Device object, not a string in pyUSB 1.x use 111 ''' 112 Instantiates the KillerBee class for the RZUSBSTICK hardware. 113 114 @type dev: TODO 115 @param dev: USB device identifier 116 @type bus: TODO 117 @param bus: Identifies the USB bus the device is on 118 @return: None 119 @rtype: None 120 ''' 121 self._channel = None 122 self.handle = None 123 self.dev = dev 124 self.__bus = bus 125 126 if self.dev != None: 127 self.__handle_open() 128 else: 129 raise Exception('No interface found') 130 131 # Tracking the command operating mode (None or AirCapture Mode) 132 self.__cmdmode = RZ_CMD_MODE_NONE 133 134 # Tracking if the RZ_CMD_OPEN_STREAM parameter is set for packet reception 135 self.__stream_open = False 136 137 # Capabilities list 138 self.capabilities = KBCapabilities() 139 self.__set_capabilities()
140
141 - def __handle_open(self):
142 ''' 143 Opens the device identified as self.dev, populating self.handle. 144 An RZUSBSTICK has a hierarchy of: 145 \_ Config value: 1 146 \_ Interface number 0, with alternate setting 0 147 |- Endpoint 132 for responses 148 |- Endpoint 2 for control 149 |- Endpoint 129 for packets 150 ''' 151 if USBVER == 0: 152 self.__handle_open_v0x() 153 else: #pyUSB 1.x 154 self.__dev_setup_v1x()
155
156 - def __dev_setup_v1x(self):
157 # See http://pyusb.sourceforge.net/docs/1.0/tutorial.html for reference 158 try: 159 self.dev.set_configuration() 160 except usb.core.USBError: 161 raise Exception("Unable to open device. " + 162 "Ensure the device is free and plugged-in. You may need sudo.")
163 164 #self.dev.reset() 165 #self.dev.set_configuration(1) # could also provide no config number 166 #self.dev.set_interface_altsetting(interface = 0, alternate_setting = 0) 167 #TODO alternative setup code: 168 #self.dev.set_configuration() 169 #cfg = self.dev.get_active_configuration() 170 #interface_number = cfg[(0,0)].bInterfaceNumber 171 #alternate_settting = usb.control.get_interface(interface_number) 172 #intf = usb.util.find_descriptor(cfg, bInterfaceNumber=interface_number, bAlternateSetting=alternate_setting) 173 #self.handle = usb.util.find_descriptor(intf, custom_match=lambda e: (e.bEndpointAddress == TODO_TARGET_ENDPOINT)) 174
175 - def __handle_open_v0x(self):
176 try: 177 config = self.dev.configurations[0] 178 intf = config.interfaces[0] 179 alt = intf[0] 180 self.handle = self.dev.open() 181 self.handle.reset() 182 self.handle.setConfiguration(config) 183 self.handle.claimInterface(alt) 184 self.handle.setAltInterface(alt) 185 except: 186 raise Exception("Unable to open device. " + 187 "Ensure the device is free and plugged-in. You may need sudo.")
188
189 - def close(self):
190 ''' 191 Closes the device handle. To be re-used, class should be re-instantiated. 192 @return: None 193 @rtype: None 194 ''' 195 if USBVER == 0: 196 self.handle.releaseInterface()
197 198 # KillerBee implements these, maybe it shouldn't and instead leave it to the driver as needed.
199 - def check_capability(self, capab):
200 return self.capabilities.check(capab)
201 - def get_capabilities(self):
202 return self.capabilities.getlist()
203
204 - def __set_capabilities(self):
205 ''' 206 Sets the capability information for RZUSB devices. 207 @rtype: None 208 @return: None 209 ''' 210 # Examine the product string for this device, setting the capability information appropriately. 211 prod = self.get_dev_info()[1] # returns a list, with second element being product string 212 213 if prod == "RZUSBSTICK": 214 self.capabilities.setcapab(KBCapabilities.FREQ_2400, True) 215 self.capabilities.setcapab(KBCapabilities.SNIFF, True) 216 self.capabilities.setcapab(KBCapabilities.SETCHAN, True) 217 elif prod == "KILLERB001": 218 self.capabilities.setcapab(KBCapabilities.FREQ_2400, True) 219 self.capabilities.setcapab(KBCapabilities.SNIFF, True) 220 self.capabilities.setcapab(KBCapabilities.SETCHAN, True) 221 self.capabilities.setcapab(KBCapabilities.INJECT, True) 222 else: 223 pass
224
225 - def get_dev_info(self):
226 ''' 227 Returns device information in a list identifying the device identifier, 228 product string and serial number in a list of strings. 229 @rtype: List 230 @return: List of 3 strings identifying device. 231 ''' 232 if USBVER == 0: 233 return [''.join([self.__bus.dirname, ":", self.dev.filename]), self.dev.open().getString(self.dev.iProduct, 50), self.dev.open().getString(self.dev.iSerialNumber, 12)] 234 elif USBVER == 1: 235 return ["{0}:{1}".format(self.dev.bus, self.dev.address), \ 236 usb.util.get_string(self.dev, 50, self.dev.iProduct), \ 237 usb.util.get_string(self.dev, 50, self.dev.iSerialNumber) ]
238
239 - def __usb_write(self, endpoint, data):
240 ''' 241 Write data to the USB device opened as self.handle. 242 243 @type endpoint: Integer 244 @param endpoint: The USB endpoint to write to 245 @type data: Mixed 246 @param data: The data to send to the USB endpoint 247 ''' 248 if USBVER == 0: 249 try: 250 self.handle.bulkWrite(endpoint, data) 251 # Returns a tuple, first value is an int as the RZ_RESP_* code 252 response = self.handle.bulkRead(RZ_USB_RESPONSE_EP, 1)[0] 253 except usb.USBError, e: 254 if e.args != ('No error',): # http://bugs.debian.org/476796 255 raise e 256 time.sleep(0.0005) 257 if response != RZ_RESP_SUCCESS: 258 if response in RESPONSE_MAP: 259 raise Exception("Error: %s" % RESPONSE_MAP[response]) 260 else: 261 raise Exception("Unknown USB write error: 0x%02x" % response) 262 else: #pyUSB 1.x 263 res = self.dev.write(endpoint, data)#, 0, 100) 264 if len(data) != res: 265 raise Exception("Issue writing USB data {0} to endpoint {1}, got a return of {2}.".format(data, endpoint, res)) 266 try: 267 response = self.dev.read(RZ_USB_RESPONSE_EP, self.dev.bMaxPacketSize0, 0, 500) 268 response = response.pop() 269 except usb.core.USBError as e: 270 if e.errno != 110: #Not Operation timed out 271 print "Error args:", e.args 272 raise e 273 elif e.errno == 110: 274 print "DEBUG: Received operation timed out error ...attempting to continue." 275 time.sleep(0.0005) 276 if response != RZ_RESP_SUCCESS: 277 if response in RESPONSE_MAP: 278 raise Exception("Error: %s" % RESPONSE_MAP[response]) 279 else: 280 raise Exception("Unknown USB write error: 0x%02x" % response)
281
282 - def _set_mode(self, mode=RZ_CMD_MODE_AC):
283 ''' 284 Change the operating mode of the USB device to one of the RZ_CMD_MODE_* 285 values. Currently, RZ_CMD_MODE_AC (Air Capture) is the only mode that is 286 used other than RZ_CMD_MODE_NONE. 287 @type mode: Integer 288 @param mode: Operating mode for the USB stick 289 @rtype: None 290 ''' 291 self.__usb_write(RZ_USB_COMMAND_EP, [RZ_CMD_SET_MODE, mode]) 292 self.__cmdmode = mode
293
294 - def _open_stream(self):
295 ''' 296 Opens a data stream for receiving packets. 297 ''' 298 self.__usb_write(RZ_USB_COMMAND_EP, [RZ_CMD_OPEN_STREAM]) 299 self.__stream_open = True
300
301 - def _close_stream(self):
302 ''' 303 Closes a data stream. 304 ''' 305 self.__usb_write(RZ_USB_COMMAND_EP, [RZ_CMD_CLOSE_STREAM]) 306 self.__stream_open = False
307 308 # KillerBee expects the driver to implement this function
309 - def sniffer_on(self, channel=None):
310 ''' 311 Turns the sniffer on such that pnext() will start returning observed 312 data. Will set the command mode to Air Capture if it is not already 313 set. 314 @type channel: Integer 315 @param channel: Sets the channel, optional 316 @rtype: None 317 ''' 318 self.capabilities.require(KBCapabilities.SNIFF) 319 320 if self.__cmdmode != RZ_CMD_MODE_AC: 321 self._set_mode(RZ_CMD_MODE_AC) 322 323 if channel != None: 324 self.set_channel(channel) 325 326 self._open_stream()
327 328 # KillerBee expects the driver to implement this function
329 - def sniffer_off(self):
330 ''' 331 Turns the sniffer off, freeing the hardware for other functions. It is 332 not necessary to call this function before closing the interface with 333 close(). 334 @rtype: None 335 ''' 336 self._close_stream()
337
338 - def jammer_on(self, channel=None):
339 ''' 340 Not yet implemented. Stay tuned. 341 @type channel: Integer 342 @param channel: Sets the channel, optional 343 @rtype: None 344 ''' 345 self.capabilities.require(KBCapabilities.PHYJAM) 346 347 if self.__cmdmode != RZ_CMD_MODE_AC: 348 self._set_mode(RZ_CMD_MODE_AC) 349 350 if channel != None: 351 self.set_channel(channel) 352 353 self.__usb_write(RZ_USB_COMMAND_EP, [RZ_CMD_JAMMER_ON])
354
355 - def jammer_off(self, channel=None):
356 ''' 357 Not yet implemented. Stay tuned. 358 @return: None 359 @rtype: None 360 ''' 361 self.__usb_write(RZ_USB_COMMAND_EP, [RZ_CMD_JAMMER_OFF])
362 363 # KillerBee expects the driver to implement this function
364 - def set_channel(self, channel):
365 ''' 366 Sets the radio interface to the specifid channel. Currently, support is 367 limited to 2.4 GHz channels 11 - 26. 368 @type channel: Integer 369 @param channel: Sets the channel, optional 370 @rtype: None 371 ''' 372 self.capabilities.require(KBCapabilities.SETCHAN) 373 374 if self.__cmdmode != RZ_CMD_MODE_AC: 375 self._set_mode(RZ_CMD_MODE_AC) 376 377 if 10 <= channel <= 26: 378 self._channel = channel #update driver's notion of current channel 379 self.__usb_write(RZ_USB_COMMAND_EP, [RZ_CMD_SET_CHANNEL, channel]) 380 else: 381 raise Exception('Invalid channel')
382 383 # KillerBee expects the driver to implement this function
384 - def inject(self, packet, channel=None, count=1, delay=0):
385 ''' 386 Injects the specified packet contents. 387 @type packet: String 388 @param packet: Packet contents to transmit, without FCS. 389 @type channel: Integer 390 @param channel: Sets the channel, optional 391 @type count: Integer 392 @param count: Transmits a specified number of frames, def=1 393 @type delay: Float 394 @param delay: Delay between each frame, def=1 395 @rtype: None 396 ''' 397 self.capabilities.require(KBCapabilities.INJECT) 398 399 if self.__cmdmode != RZ_CMD_MODE_AC: 400 self._set_mode(RZ_CMD_MODE_AC) 401 402 if len(packet) < 1: 403 raise Exception('Empty packet') 404 if len(packet) > 125: # 127 - 2 to accommodate FCS 405 raise Exception('Packet too long') 406 407 if channel != None: 408 self.set_channel(channel) 409 410 # Append two bytes to be replaced with FCS by firmware. 411 packet += "\x00\x00" 412 413 for pnum in xrange(count): 414 # Format for packet is opcode RZ_CMD_INJECT_FRAME, one-byte length, 415 # packet data 416 self.__usb_write(RZ_USB_COMMAND_EP, struct.pack("BB", RZ_CMD_INJECT_FRAME, len(packet)) + packet) 417 time.sleep(delay)
418 419 # KillerBee expects the driver to implement this function
420 - def pnext(self, timeout=100):
421 ''' 422 Returns packet data as a string, else None. 423 @type timeout: Integer 424 @param timeout: Timeout to wait for packet reception in usec 425 @rtype: List 426 @return: Returns None is timeout expires and no packet received. When a packet is received, a list is returned, in the form [ String: packet contents | Bool: Valid CRC | Int: Unscaled RSSI ] 427 ''' 428 if self.__stream_open == False: 429 # Turn the sniffer on 430 self.sniffer_on() 431 432 # The RZ_USB_PACKET_EP doesn't return error codes like the standard 433 # RZ_USB_RESPONSE_EP does, so we don't use __usb_read() here. 434 pdata = None 435 if USBVER == 0: 436 try: 437 pdata = self.handle.bulkRead(RZ_USB_PACKET_EP, timeout) 438 except usb.USBError, e: 439 if e.args != ('No error',): # http://bugs.debian.org/476796 440 if e.args[0] != "Connection timed out": # USB timeout issue 441 print "Error args:", e.args 442 raise e 443 else: # pyUSB 1.x 444 try: 445 pdata = self.dev.read(RZ_USB_PACKET_EP, self.dev.bMaxPacketSize0)#1, 0, 100) 446 except usb.core.USBError as e: 447 if e.errno != 110: #Operation timed out 448 print "Error args:", e.args 449 raise e 450 #TODO error handling enhancements for USB 1.0 451 452 # PyUSB returns an empty tuple occasionally, handle as "no data" 453 #TODO added len(pdata) check as some arrays were failing 454 if pdata == None or pdata == () or len(pdata)==0: 455 return None 456 457 if pdata[0] == RZ_EVENT_STREAM_AC_DATA: 458 rssi = int(pdata[6]) 459 validcrc = True if (pdata[7] == 1) else False 460 frame = pdata[9:] 461 # Convert the tuple response data to a string (by way of a list) 462 framedata = [] 463 for byteval in frame: 464 framedata.append(struct.pack("B", byteval)) 465 # Bugfix rmspeers 12.17.2010 466 # Remove the junk \xff byte at the end, instead of overwriting it in zbdump with a \x00 byte 467 framedata = ''.join(framedata[:-1]) 468 #Return in a nicer dictionary format, so we don't have to reference by number indicies. 469 #Note that 0,1,2 indicies inserted twice for backwards compatibility. 470 return {0:framedata, 1:validcrc, 2:rssi, \ 471 'bytes':framedata, 'validcrc':validcrc, 'rssi':rssi, \ 472 'dbm':rssi,'datetime':datetime.now()} 473 #TODO calculate dbm based on RSSI conversion formula for the chip 474 else: 475 return None
476 #raise Exception("Unrecognized AirCapture Data Response: 0x%02x" % pdata[0]) 477
478 - def ping(self, da, panid, sa, channel=None):
479 ''' 480 Not yet implemented. 481 @return: None 482 @rtype: None 483 ''' 484 raise Exception('Not yet implemented')
485