| Home | Trees | Indices | Help |
|
|---|
|
|
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
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
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
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
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
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.
200 return self.capabilities.check(capab)
202 return self.capabilities.getlist()
203
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
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
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
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
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
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
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
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
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
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
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
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
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
485
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Mon Dec 30 17:49:14 2013 | http://epydoc.sourceforge.net |