diff --git a/README.md b/README.md index be02b5b..1016259 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,17 @@ M3-Python Utilities and software libraries for the [M3 ecosystem](http://cubeworks.us) and interfacing with the [ICE board](http://mbus.io/ice.html). +M3-Python supports CPython 3.9. Install the local checkout with: + ```bash $ pip install m3 $ # Program the board via the optical interface: $ m3_ice goc flash program.bin ``` -The `m3_ice` utility should handle most use cases, however users are free to write their scripts against the `ice` library directly. +The simulator and integration suite require `socat` and Unix PTYs. Run them on Linux, or use WSL instead of native Windows, with `tox -e py39`. + +The `m3_ice` utility should handle most use cases, however users are free to write their scripts against the `m3.ice` library directly. Developers are encouraged to consider some of the higher-level interfaces provided by `m3_common`. m3_ice diff --git a/m3/ice.py b/m3/ice.py index 53bfd28..aefb094 100644 --- a/m3/ice.py +++ b/m3/ice.py @@ -2,18 +2,12 @@ ################################################################################ -# Coerce Py2k to act more like Py3k -from __future__ import (absolute_import, division, print_function, unicode_literals) -from builtins import ( - ascii, bytes, chr, dict, filter, hex, input, int, isinstance, list, map, - next, object, oct, open, pow, range, round, str, super, zip, - ) - import binascii from copy import copy from copy import deepcopy import errno import functools +import logging import socket import struct import sys @@ -22,7 +16,7 @@ try: from . import m3_logging -except: +except ImportError: import m3_logging logger = m3_logging.getLogger(__name__) @@ -52,7 +46,7 @@ class ICE(object): VERSIONS = ((0,1),(0,2),(0,3),(0,4),(0,5)) - ONEYEAR = 365 * 24 * 60 * 60 + ONEYEAR = min(365 * 24 * 60 * 60, threading.TIMEOUT_MAX) class ICE_Error(Exception): ''' @@ -223,7 +217,7 @@ def find_baud(self, serial_device): with serial.Serial(serial_device, baudrates[0], timeout=0.05 ) as tmpSerial: - if not tmpSerial.isOpen(): + if not tmpSerial.is_open: raise self.ICE_Error("Failed to connect to temporary serial device") for baudrate in baudrates: @@ -266,7 +260,7 @@ def connect(self, serial_device, baudrate=115200): logger.warn("Skipping baudrate?") self.dev = serial.Serial(serial_device, timeout=0.5) - if self.dev.isOpen(): + if self.dev.is_open: logger.info("Connected to serial device at " + self.dev.portstr + " at " + str(baudrate) + " baud") else: @@ -320,14 +314,14 @@ def spawn_handler(self, msg_type, event_id, length, msg): logger.warn("WARNING: No handler registered for message type: " + str(msg_type)) logger.warn("Known Types:") - for t,f in self.msg_handler.iteritems(): + for t,f in self.msg_handler.items(): logger.warn("%s\t%s" % (t, str(f))) logger.warn(" Dropping packet:") logger.warn("") logger.warn(" Type: %s" % (msg_type)) logger.warn("Event ID: %d" % (event_id)) logger.warn(" Length: %d" % (length)) - logger.warn(" Message:" + msg.encode('hex')) + logger.warn(" Message:" + msg.hex()) except Exception as e: logger.warn("Unhandled exception trying to report unknown message.") logger.warn(str(e)) @@ -345,7 +339,7 @@ def spawn_handler(self, msg_type, event_id, length, msg): logger.debug(" Type: %s" % (msg_type)) logger.debug("Event ID: %d" % (event_id)) logger.debug(" Length: %d" % (length)) - logger.debug(" Message:" + msg.encode('hex')) + logger.debug(" Message:" + msg.hex()) except Exception as e: logger.debug("Unhandled exception trying to report unknown message.") logger.debug(str(e)) @@ -363,11 +357,11 @@ def useful_read(self, length, check_timeout = False): rxBuf += rx assert len(rxBuf) == length - logger.debug('Raw Read: ' + binascii.hexlify(rxBuf) ) + logger.debug('Raw Read: ' + rxBuf.hex()) return rxBuf def communicator(self): - while not self.communicator_stop_request.isSet(): + while not self.communicator_stop_request.is_set(): try: # Read has a timeout of .1 s. Polling is the easiest way to # do x-platform cancellation @@ -376,16 +370,13 @@ def communicator(self): continue except (serial.SerialException, OSError): break - msg_type = ord(msg_type) - event_id = ord(event_id) - length = ord(length) #print("Got msg type", msg_type, chr(msg_type), length) try: msg = self.useful_read(length, check_timeout = True) except self.TimeoutError: logger.warn("Timeout error occured, skipping rest of packet!") continue - #print(msg.encode('hex')) + #print(msg.hex()) if event_id == self.last_event_id: logger.warn("WARNING: Duplicate event_id! THIS IS A BUG [somewhere]!!") @@ -394,7 +385,7 @@ def communicator(self): logger.warn(" Type: %d" % (msg_type)) logger.warn("Event ID: %d" % (event_id)) logger.warn(" Length: %d" % (length)) - logger.warn(" Message:" + msg.encode('hex')) + logger.warn(" Message:" + msg.hex()) else: self.last_event_id = event_id @@ -413,7 +404,7 @@ def communicator(self): logger.warn(" Type: %s" % (["ACK","NAK"][msg_type])) logger.warn("Event ID: %d" % (event_id)) logger.warn(" Length: %d" % (length)) - logger.warn(" Message:" + msg.encode('hex')) + logger.warn(" Message:" + msg.hex()) else: msg_type = chr(msg_type) logger.debug("Got an async message of type: " + msg_type) @@ -577,9 +568,9 @@ def common_bB_formatter(self, msg_type, event_id, length, msg, b_type): try: logger.warn("No handler registered for B++ (formatted, snooped MBus) messages") logger.warn("Dropping message:") - logger.warn("\taddr: " + binascii.hexlify(addr)) - logger.warn("\tdata: " + binascii.hexlify(data)) - logger.warn("\tstat: " + binascii.hexlify(cb)) + logger.warn("\taddr: " + addr.hex()) + logger.warn("\tdata: " + data.hex()) + logger.warn("\tstat: " + msg[-1:].hex()) logger.warn("") except Exception as e: logger.warn("Unhandled exception trying to report missing B++ handler.") @@ -647,8 +638,8 @@ def negotiate_version(self): logger.debug("Sending version probe") resp = self.send_message_until_acked('V') - if (len(resp) is 0) or (len(resp) % 2): - raise self.FormatError("Version response: " + resp) + if (len(resp) == 0) or (len(resp) % 2): + raise self.FormatError("Version response: {}".format(resp)) logger.info("This ICE board supports versions...") self.major = None @@ -748,7 +739,7 @@ def ice_query_capabilities(self): characters from the ICE board, which requires the caller to know the ICE protocol. ''' - resp = self.send_message_until_acked('?', struct.pack("B", ord('?'))) + resp = self.send_message_until_acked('?', struct.pack("B", ord('?'))).decode('ascii') self.capabilities = resp return resp @@ -890,7 +881,7 @@ def goc_ein_get_freq_divisor_max_0_2(self): resp = self.send_message_until_acked('O', struct.pack("B", ord('c'))) if len(resp) != 3: raise self.FormatError("Wrong response length from `Oc': " + str(resp)) - setting = struct.unpack("!I", "\x00"+resp)[0] + setting = struct.unpack("!I", b"\x00"+resp)[0] return setting @min_proto_version("0.3") @@ -911,7 +902,7 @@ def goc_ein_get_freq_divisor(self): @max_proto_version("0.2") def goc_ein_set_freq_divisor_max_0_2(self, divisor): packed = struct.pack("!I", divisor) - if packed[0] != '\x00': + if packed[0] != 0: raise self.ParameterError("Out of range.") msg = struct.pack("B", ord('c')) + packed[1:] self.send_message_until_acked('o', msg) @@ -1015,7 +1006,7 @@ def _goc_freq_in_hz_to_divisor(self, freq_in_hz): NOMINAL = 2e6 else: NOMINAL = 4e6 - return NOMINAL / freq_in_hz; + return int(NOMINAL / freq_in_hz) @min_proto_version("0.1") @capability('o') @@ -1099,7 +1090,7 @@ def i2c_get_speed(self): raise self.FormatError return struct.unpack("B", msg)[0] * 2 - ret = ord(msg[0]) + ret = msg[0] msg = msg[1:] if ret == errno.ENODEV: # XXX Generalize me w.r.t. version? @@ -1133,7 +1124,7 @@ def i2c_set_speed(self, speed): if ack == 0: return speed - ret = ord(msg[0]) + ret = msg[0] msg = msg[1:] if ret == errno.EINVAL: raise self.ICE_Error("ICE reports: Invalid argument.") @@ -1683,7 +1674,7 @@ def _gpio_get_level_0_2(self): resp = self.send_message_until_acked('G', struct.pack('B', ord('l'))) if len(resp) != 3: raise self.FormatError("Bad response from `Gl':" + str(resp)) - high,mid,low = map(ord, resp) + high,mid,low = resp return low | (mid << 8) | (high << 16) @min_proto_version("0.2") @@ -1697,7 +1688,7 @@ def _gpio_get_direction_0_2(self): resp = self.send_message_until_acked('G', struct.pack('B', ord('d'))) if len(resp) != 3: raise self.FormatError("Bad response from `Gd#':" + str(resp)) - high,mid,low = map(ord, resp) + high,mid,low = resp return low | (mid << 8) | (high << 16) @min_proto_version("0.2") @@ -1747,7 +1738,7 @@ def gpio_get_interrupt_enable_mask(self): resp = self.send_message_until_acked('G', struct.pack('B', ord('i'))) if len(resp) != 3: raise self.FormatError("Bad response from `Gi':" + str(resp)) - high,mid,low = map(ord, resp) + high,mid,low = resp return low | (mid << 8) | (high << 16) @min_proto_version("0.2") diff --git a/m3/ice_simulator.py b/m3/ice_simulator.py index e0e0cc0..bc4bcfc 100755 --- a/m3/ice_simulator.py +++ b/m3/ice_simulator.py @@ -1,12 +1,5 @@ #!/usr/bin/env python -# Coerce Py2k to act more like Py3k -from __future__ import (absolute_import, division, print_function, unicode_literals) -from builtins import ( - ascii, bytes, chr, dict, filter, hex, input, int, isinstance, list, map, - next, object, oct, open, pow, range, round, str, super, zip, - ) - CAPABILITES = "?_dIifnOoBbMmeGgPp" MAX_GPIO = 24 DEFAULT_BAUD_DIVIDER = 0x00AE @@ -45,11 +38,11 @@ import traceback try: - import m3_logging - from ice import ICE -except: from . import m3_logging from .ice import ICE +except ImportError: + import m3_logging + from ice import ICE logger = m3_logging.get_logger(__name__) @@ -126,7 +119,7 @@ def __init__(self, args=None): logger.error(" socat -x pty,link=/tmp/com1,raw,echo=0 pty,link=/tmp/com2,raw,echo=0") logger.error("") raise - if not self.s.isOpen(): + if not self.s.is_open: logger.error('Could not open serial port at: ' + self.args.serial) raise IOError("Failed to open serial port") @@ -253,13 +246,13 @@ def transaction_mode(self): Replays a series of ICE transactions with timing information ''' def read_raw_message(): - msg_type, event_id, length = self.s.read(3) - length_int = ord(length) - logger.debug("Got a message of type: " + msg_type + - ' length: ' + str(length_int)) - msg = self.s.read(length_int) + header = self.s.read(3) + length = header[2] + logger.debug("Got a message of type: " + chr(header[0]) + + ' length: ' + str(length)) + msg = self.s.read(length) - return msg_type + event_id + length + msg + return header + msg logger.info("Transaction beginning") last_ts = None @@ -284,11 +277,11 @@ def read_raw_message(): rxMsg = b'' rxMsg = read_raw_message() - logger.debug('Read: ' + binascii.hexlify(rxMsg)) - logger.info(' vs : ' + binascii.hexlify(data)) + logger.debug('Read: ' + rxMsg.hex()) + logger.info(' vs : ' + data.hex()) if (rxMsg != data): - rx = binascii.hexlify(rxMsg) - buf = binascii.hexlify(data) + rx = rxMsg.hex() + buf = data.hex() raise Exception('Read vs. Expect: ' + \ str(rx) + ' vs. ' + str(buf) + \ ' ascii: ' + str(rx==buf)) @@ -299,7 +292,7 @@ def read_raw_message(): hex_tex = line.split('SEND')[1].strip() hex_tex = hex_tex.replace('0x', '').lower() data = binascii.unhexlify(hex_tex) - print ('SENDING: ' + binascii.hexlify(data)) + print ('SENDING: ' + data.hex()) self.s.write(data) self.s.flush() @@ -333,10 +326,11 @@ def min_proto(proto): raise UnknownCommandException try: - msg_type, event_id, length = self.s.read(3) + header = self.s.read(3) + msg_type = chr(header[0]) logger.debug("Got a message of type: " + msg_type) - event_id = ord(event_id) - length = ord(length) + event_id = header[1] + length = header[2] msg = self.s.read(length) #slight hack to simplify respond() @@ -365,27 +359,27 @@ def min_proto(proto): CLOCK_FREQ = 2e6 minor = 1 else: - logger.error("Request for unknown version: " + msg) + logger.error("Request for unknown version: " + msg.hex()) raise Exception logger.info("Negotiated to protocol version 0."+ str(minor)) self.ack() elif msg_type == '?': min_proto(2) - if msg[0] == '?': + if msg[0] == ord('?'): logger.info("Responded to query capabilites with " + CAPABILITES) self.respond(CAPABILITES) - elif msg[0] == 'b': + elif msg[0] == ord('b'): logger.info("Responded to query for ICE baudrate (divider: 0x%04X)" % (self.baud_divider)) self.respond(struct.pack('>H', self.baud_divider)) else: - logger.error("Bad '?' subtype: " + msg[0]) + logger.error("Bad '?' subtype: %c", msg[0]) raise UnknownCommandException elif msg_type == '_': min_proto(2) - if msg[0] == 'b': - high = ord(msg[1]) - low = ord(msg[2]) + if msg[0] == ord('b'): + high = msg[1] + low = msg[2] new_div = low | (high << 8) if new_div not in (0x00AE, 0x000A, 0x0007): logger.error("Bad baudrate divider: 0x%04X" % (new_div)) @@ -409,14 +403,14 @@ def min_proto(proto): self.baud_divider = new_div logger.info("New baud divider set: " + str(self.baud_divider)) else: - logger.error("bad '_' subtype: " + msg[0]) + logger.error("bad '_' subtype: %c", msg[0]) raise UnknownCommandException elif msg_type == 'b': min_proto(2) self.mbus_msg += msg if len(msg) != 255: logger.info("Got a MBus message:") - logger.info(" message: " + binascii.hexlify(self.mbus_msg)) + logger.info(" message: " + self.mbus_msg.hex()) self.mbus_msg = bytes() if self.mbus_should_interrupt: logger.info("Message would have interrupted") @@ -432,16 +426,16 @@ def min_proto(proto): elif msg_type == 'd': self.i2c_msg += msg if not self.i2c_match: - if not self.match_mask(ord(msg[0]), self.i2c_mask_ones, self.i2c_mask_zeros): + if not self.match_mask(msg[0], self.i2c_mask_ones, self.i2c_mask_zeros): logger.info("I2C address %02x did not match mask %02x %02x", - ord(msg[0]), self.i2c_mask_ones, self.i2c_mask_zeros) + msg[0], self.i2c_mask_ones, self.i2c_mask_zeros) self.respond(struct.pack('B', 0), ack=False) continue self.i2c_match = True if len(msg) != 255: logger.info("Got i2c message:") - logger.info(" addr: " + binascii.hexlify(self.i2c_msg[0:1])) - logger.info(" data: " + binascii.hexlify(self.i2c_msg[1:])) + logger.info(" addr: " + self.i2c_msg[0:1].hex()) + logger.info(" data: " + self.i2c_msg[1:].hex()) self.i2c_msg = bytes() self.i2c_match = False else: @@ -452,7 +446,7 @@ def min_proto(proto): self.ein_msg += msg if len(msg) != 255: logger.info("Got a EIN message:") - logger.info(" message: " + binascii.hexlify(self.ein_msg)) + logger.info(" message: " + self.ein_msg.hex()) self.ein_msg = bytes() else: logger.debug("Got EIN fragment") @@ -461,7 +455,7 @@ def min_proto(proto): self.flow_msg += msg if len(msg) != 255: logger.info("Got f/n-type message in %s mode:", ('EIN','GOC')[ein_goc_toggle]) - logger.info(" message: " + binascii.hexlify(self.flow_msg)) + logger.info(" message: " + self.flow_msg.hex()) self.flow_msg = bytes() else: logger.debug("Got f/n-type fragment in %s mode", ('EIN','GOC')[ein_goc_toggle]) @@ -476,215 +470,215 @@ def min_proto(proto): elif msg_type == 'G': # GPIO changed completely between v0.1 and v0.2 if minor == 1: - if msg[0] == 'l': - logger.info("Responded to request for GPIO %d Dir (%s)", ord(msg[1]), self.gpios[ord(msg[1])]) - self.respond(struct.pack("B", self.gpios[ord(msg[1])].level)) - elif msg[0] == 'd': - logger.info("Responded to request for GPIO %d Level (%s)", ord(msg[1]), self.gpios[ord(msg[1])]) - self.respond(struct.pack("B", self.gpios[ord(msg[1])].direction)) + if msg[0] == ord('l'): + logger.info("Responded to request for GPIO %d Dir (%s)", msg[1], self.gpios[msg[1]]) + self.respond(struct.pack("B", self.gpios[msg[1]].level)) + elif msg[0] == ord('d'): + logger.info("Responded to request for GPIO %d Level (%s)", msg[1], self.gpios[msg[1]]) + self.respond(struct.pack("B", self.gpios[msg[1]].direction)) else: - logger.error("bad 'G' subtype: " + msg[0]) + logger.error("bad 'G' subtype: %c", msg[0]) raise Exception else: - if msg[0] == 'l': + if msg[0] == ord('l'): mask = 0 for i in range(len(self.gpios)): mask |= (self.gpios[i].level << i) logger.info("Responded to request for GPIO level mask (%06x)", mask) self.respond(struct.pack('>I', mask)[1:]) - elif msg[0] == 'd': + elif msg[0] == ord('d'): mask = 0 for i in range(len(self.gpios)): mask |= (self.gpios[i].direction << i) logger.info("Responded to request for GPIO direction mask (%06x)", mask) self.respond(struct.pack('>I', mask)[1:]) - elif msg[0] == 'i': + elif msg[0] == ord('i'): mask = 0 for i in range(len(self.gpios)): mask |= (self.gpios[i].interrupt << i) logger.info("Responded to request for GPIO interrupt mask (%06x)", mask) self.respond(struct.pack('>I', mask)[1:]) else: - logger.error("bad 'G' subtype: " + msg[0]) + logger.error("bad 'G' subtype: %c", msg[0]) raise Exception elif msg_type == 'g': # GPIO changed completely between v0.1 and v0.2 if minor == 1: - if msg[0] == 'l': - self.gpios[ord(msg[1])].level = (ord(msg[2]) == True) - logger.info("Set GPIO %d Level: %s", ord(msg[1]), self.gpios[ord(msg[1])]) + if msg[0] == ord('l'): + self.gpios[msg[1]].level = (msg[2] == True) + logger.info("Set GPIO %d Level: %s", msg[1], self.gpios[msg[1]]) self.ack() - elif msg[0] == 'd': - self.gpios[ord(msg[1])].direction = ord(msg[2]) - logger.info("Set GPIO %d Dir: %s", ord(msg[1]), self.gpios[ord(msg[1])]) + elif msg[0] == ord('d'): + self.gpios[msg[1]].direction = msg[2] + logger.info("Set GPIO %d Dir: %s", msg[1], self.gpios[msg[1]]) self.ack() else: - logger.error("bad 'g' subtype: " + msg[0]) + logger.error("bad 'g' subtype: %c", msg[0]) raise Exception else: - if msg[0] == 'l': - high,mid,low = map(ord, msg[1:]) + if msg[0] == ord('l'): + high,mid,low = msg[1:] mask = low | mid << 8 | high << 16 for i in range(24): self.gpios[i].level = (mask >> i) & 0x1 logger.info("Set GPIO level mask to: %06x", mask) self.ack() - elif msg[0] == 'd': - high,mid,low = map(ord, msg[1:]) + elif msg[0] == ord('d'): + high,mid,low = msg[1:] mask = low | mid << 8 | high << 16 for i in range(24): self.gpios[i].direction = (mask >> i) & 0x1 logger.info("Set GPIO direction mask to: %06x", mask) self.ack() - elif msg[0] == 'i': - high,mid,low = map(ord, msg[1:]) + elif msg[0] == ord('i'): + high,mid,low = msg[1:] mask = low | mid << 8 | high << 16 for i in range(24): self.gpios[i].interrupt = (mask >> i) & 0x1 logger.info("Set GPIO interrupt mask to: %06x", mask) self.ack() else: - logger.error("bad 'g' subtype: " + msg[0]) + logger.error("bad 'g' subtype: %c", msg[0]) raise Exception elif msg_type == 'I': - if msg[0] == 'c': + if msg[0] == ord('c'): logger.info("Responded to query for I2C bus speed (%d kHz)", self.i2c_speed_in_khz) self.respond(struct.pack("B", self.i2c_speed_in_khz // 2)) - elif msg[0] == 'a': + elif msg[0] == ord('a'): logger.info("Responded to query for ICE I2C mask (%02x ones %02x zeros)", self.i2c_mask_ones, self.i2c_mask_zeros) self.respond((self.i2c_mask_ones, self.i2c_mask_zeros)) else: - logger.error("bad 'I' subtype: " + msg[0]) + logger.error("bad 'I' subtype: %c", msg[0]) raise Exception elif msg_type == 'i': - if msg[0] == 'c': - self.i2c_speed_in_khz = ord(msg[1]) * 2 + if msg[0] == ord('c'): + self.i2c_speed_in_khz = msg[1] * 2 logger.info("I2C Bus Speed set to %d kHz", self.i2c_speed_in_khz) self.ack() - elif msg[0] == 'a': - self.i2c_mask_ones = ord(msg[1]) - self.i2c_mask_zeros = ord(msg[2]) + elif msg[0] == ord('a'): + self.i2c_mask_ones = msg[1] + self.i2c_mask_zeros = msg[2] logger.info("ICE I2C mask set to 0x%02x ones, 0x%02x zeros", self.i2c_mask_ones, self.i2c_mask_zeros) self.ack() else: - logger.error("bad 'i' subtype: " + msg[0]) + logger.error("bad 'i' subtype: %c", msg[0]) raise Exception elif msg_type == 'M': min_proto(2) - if msg[0] == 'l': + if msg[0] == ord('l'): logger.info("Responded to query for MBus full prefix mask (%06x ones %06x zeros)", self.mbus_full_prefix_ones, self.mbus_full_prefix_zeros) r = struct.pack('>I', self.mbus_full_prefix_ones)[1:] r += struct.pack('>I', self.mbus_full_prefix_zeros)[1:] self.respond(r) - elif msg[0] == 's': + elif msg[0] == ord('s'): logger.info("Responded to query for MBus short prefix (%02x)", self.mbus_short_prefix) self.respond(struct.pack("B", self.mbus_short_prefix)) - elif msg[0] == 'S': + elif msg[0] == ord('S'): logger.info("Responded to query for MBus snoop enabled (%d)", self.mbus_snoop_enabled) self.respond(struct.pack("B", self.mbus_snoop_enabled)) - elif msg[0] == 'b': + elif msg[0] == ord('b'): logger.info("Responded to query for MBus broadcast mask (%02x ones %02x zeros)", self.mbus_broadcast_mask_ones, self.mbus_broadcast_mask_zeros) self.respond(struct.pack("BB", self.mbus_broadcast_mask_ones, self.mbus_broadcast_mask_zeros)) - elif msg[0] == 'B': + elif msg[0] == ord('B'): logger.info("Responded to query for MBus snoop broadcast mask (%02x ones %02x zeros)", self.mbus_snoop_broadcast_mask_ones, self.mbus_snoop_broadcast_mask_zeros) self.respond(struct.pack("BB", self.mbus_snoop_broadcast_mask_ones, self.mbus_snoop_broadcast_mask_zeros)) - elif msg[0] == 'm': + elif msg[0] == ord('m'): logger.info("Responded to query for MBus master state (%s)", ("off", "on")[self.mbus_ismaster]) self.respond(struct.pack("B", self.mbus_ismaster)) - elif msg[0] == 'c': + elif msg[0] == ord('c'): raise NotImplementedError("MBus clock not defined") - elif msg[0] == 'i': + elif msg[0] == ord('i'): logger.info("Responded to query for MBus should interrupt (%d)", self.mbus_should_interrupt) self.respond(struct.pack("B", self.mbus_should_interrupt)) - elif msg[0] == 'p': + elif msg[0] == ord('p'): logger.info("Responded to query for MBus should use priority arb (%d)", self.mbus_should_prio) self.respond(struct.pack("B", self.mbus_should_prio)) - elif msg[0] == 'r': + elif msg[0] == ord('r'): logger.info("Responded to query for MBus internal reset (%d)", self.mbus_force_reset) self.respond(struct.pack("B", self.mbus_force_reset)) else: - logger.error("bad 'M' subtype: " + msg[0]) + logger.error("bad 'M' subtype: %c", msg[0]) elif msg_type == 'm': min_proto(2) - if msg[0] == 'l': - self.mbus_full_prefix_ones = ord(msg[3]) - self.mbus_full_prefix_ones |= ord(msg[2]) << 8 - self.mbus_full_prefix_ones |= ord(msg[1]) << 16 - self.mbus_full_prefix_zeros = ord(msg[6]) - self.mbus_full_prefix_zeros |= ord(msg[5]) << 8 - self.mbus_full_prefix_zeros |= ord(msg[4]) << 16 + if msg[0] == ord('l'): + self.mbus_full_prefix_ones = msg[3] + self.mbus_full_prefix_ones |= msg[2] << 8 + self.mbus_full_prefix_ones |= msg[1] << 16 + self.mbus_full_prefix_zeros = msg[6] + self.mbus_full_prefix_zeros |= msg[5] << 8 + self.mbus_full_prefix_zeros |= msg[4] << 16 logger.info("MBus full prefix mask set to ones %06x zeros %06x", self.mbus_full_prefix_ones, self.mbus_full_prefix_zeros) self.ack() - elif msg[0] == 's': - self.mbus_short_prefix = ord(msg[1]) + elif msg[0] == ord('s'): + self.mbus_short_prefix = msg[1] logger.info("MBus short prefix set to %02x", self.mbus_short_prefix) self.ack() - elif msg[0] == 'S': - self.mbus_snoop_enabled = ord(msg[1]) + elif msg[0] == ord('S'): + self.mbus_snoop_enabled = msg[1] if self.mbus_snoop_enabled: self.s_en_event.set() logger.info("MBus snoop enabled set to %d", self.mbus_snoop_enabled) self.ack() - elif msg[0] == 'b': - self.mbus_broadcast_mask_ones = ord(msg[1]) - self.mbus_broadcast_mask_zeros = ord(msg[2]) + elif msg[0] == ord('b'): + self.mbus_broadcast_mask_ones = msg[1] + self.mbus_broadcast_mask_zeros = msg[2] logger.info("MBus broadcast mask set to ones %02x zeros %02x", self.mbus_broadcast_mask_ones, self.mbus_broadcast_mask_zeros) self.ack() - elif msg[0] == 'B': - self.mbus_snoop_broadcast_mask_ones = ord(msg[1]) - self.mbus_snoop_broadcast_mask_zeros = ord(msg[2]) + elif msg[0] == ord('B'): + self.mbus_snoop_broadcast_mask_ones = msg[1] + self.mbus_snoop_broadcast_mask_zeros = msg[2] logger.info("MBus snoop broadcast mask set to ones %02x zeros %02x", self.mbus_snoop_broadcast_mask_ones, self.mbus_snoop_broadcast_mask_zeros) self.ack() - elif msg[0] == 'm': - self.mbus_ismaster = bool(ord(msg[1])) + elif msg[0] == ord('m'): + self.mbus_ismaster = bool(msg[1]) logger.info("MBus master mode set " + ("off", "on")[self.mbus_ismaster]) self.ack() - elif msg[0] == 'c': + elif msg[0] == ord('c'): raise NotImplementedError("MBus clock not defined") - elif msg[0] == 'i': - self.mbus_should_interrupt = ord(msg[1]) + elif msg[0] == ord('i'): + self.mbus_should_interrupt = msg[1] logger.info("MBus should interrupt set to %d", self.mbus_should_interrupt) self.ack() - elif msg[0] == 'p': - self.mbus_should_prio = ord(msg[1]) + elif msg[0] == ord('p'): + self.mbus_should_prio = msg[1] logger.info("MBus should use priority arbitration set to %d", self.mbus_should_prio) self.ack() - elif msg[0] == 'r': - self.mbus_force_reset = ord(msg[1]) + elif msg[0] == ord('r'): + self.mbus_force_reset = msg[1] logger.info("MBus internal reset set to %d", self.mbus_force_reset) self.ack() else: - logger.error("bad 'm' subtype: " + msg[0]) + logger.error("bad 'm' subtype: %c", msg[0]) elif msg_type == 'O': - if msg[0] == 'c': + if msg[0] == ord('c'): logger.info("Responded to query for FLOW clock (%.2f Hz)", self.flow_clock_in_hz) div = int(CLOCK_FREQ / self.flow_clock_in_hz) - resp = '' + resp = b'' if minor >= 3: resp = struct.pack(">I", div) else: resp = struct.pack(">I", div)[1:] self.respond(resp) - elif msg[0] == 'o': + elif msg[0] == ord('o'): if minor > 1: logger.info("Responded to query for FLOW power (%s)", ('off','on')[self.flow_onoff]) self.respond(struct.pack("B", self.flow_onoff)) @@ -692,103 +686,103 @@ def min_proto(proto): logger.error("Request for protocol 0.2 command (Oo), but the") logger.error("negotiated protocol was 0.1") else: - logger.error("bad 'O' subtype: " + msg[0]) + logger.error("bad 'O' subtype: %c", msg[0]) elif msg_type == 'o': - if msg[0] == 'c': + if msg[0] == ord('c'): if minor >= 3: - div = (ord(msg[1]) << 24) | (ord(msg[2]) << 16) | (ord(msg[3]) << 8) | ord(msg[4]) + div = (msg[1] << 24) | (msg[2] << 16) | (msg[3] << 8) | msg[4] else: - div = (ord(msg[1]) << 16) | (ord(msg[2]) << 8) | ord(msg[3]) + div = (msg[1] << 16) | (msg[2] << 8) | msg[3] self.flow_clock_in_hz = CLOCK_FREQ / div logger.info("Set FLOW clock to %.2f Hz", self.flow_clock_in_hz) self.ack() - elif msg[0] == 'o': + elif msg[0] == ord('o'): min_proto(2) if minor > 1: - self.flow_onoff = bool(ord(msg[1])) + self.flow_onoff = bool(msg[1]) logger.info("Set FLOW power to %s", ('off','on')[self.flow_onoff]) self.ack() - elif msg[0] == 'p': + elif msg[0] == ord('p'): min_proto(2) - ein_goc_toggle = bool(ord(msg[1])) + ein_goc_toggle = bool(msg[1]) logger.info("Set GOC/EIN toggle to %s mode", ('EIN','GOC')[ein_goc_toggle]) self.ack() else: assert False - logger.error("bad 'o' subtype: " + msg[0]) + logger.error("bad 'o' subtype: %c", msg[0]) assert False elif msg_type == 'P': - pwr_idx = ord(msg[1]) + pwr_idx = msg[1] if pwr_idx not in (0,1,2): logger.error("Illegal power index: %d", pwr_idx) raise Exception - if msg[0] == 'v': - if pwr_idx is 0: + if msg[0] == ord('v'): + if pwr_idx == 0: logger.info("Query 0.6V rail (vset=%d, vout=%.2f)", self.vset_0p6, (0.537 + 0.0185 * self.vset_0p6) * DEFAULT_POWER_0P6) self.respond(struct.pack("BB", pwr_idx, self.vset_0p6)) - elif pwr_idx is 1: + elif pwr_idx == 1: logger.info("Query 1.2V rail (vset=%d, vout=%.2f)", self.vset_1p2, (0.537 + 0.0185 * self.vset_1p2) * DEFAULT_POWER_1P2) self.respond(struct.pack("BB", pwr_idx, self.vset_1p2)) - elif pwr_idx is 2: + elif pwr_idx == 2: logger.info("Query VBatt rail (vset=%d, vout=%.2f)", self.vset_vbatt, (0.537 + 0.0185 * self.vset_vbatt) * DEFAULT_POWER_VBATT) self.respond(struct.pack("BB", pwr_idx, self.vset_vbatt)) - elif msg[0] == 'o': - if pwr_idx is 0: + elif msg[0] == ord('o'): + if pwr_idx == 0: logger.info("Query 0.6V rail (%s)", ('off','on')[self.power_0p6_on]) self.respond(struct.pack("B", self.power_0p6_on)) - elif pwr_idx is 1: + elif pwr_idx == 1: logger.info("Query 1.2V rail (%s)", ('off','on')[self.power_1p2_on]) self.respond(struct.pack("B", self.power_1p2_on)) - elif pwr_idx is 2: + elif pwr_idx == 2: logger.info("Query vbatt rail (%s)", ('off','on')[self.power_vbatt_on]) self.respond(struct.pack("B", self.power_vbatt_on)) - elif pwr_idx is 3: + elif pwr_idx == 3: logger.info("Query goc rail (%s)", ('off','on')[self.power_goc_on]) self.respond(struct.pack("B", self.power_goc_on)) else: - logger.error("bad 'p' subtype: " + msg[0]) + logger.error("bad 'p' subtype: %c", msg[0]) raise Exception elif msg_type == 'p': - pwr_idx = ord(msg[1]) - if msg[0] == 'v': - if pwr_idx is ICE.POWER_0P6: - self.vset_0p6 = ord(msg[2]) + pwr_idx = msg[1] + if msg[0] == ord('v'): + if pwr_idx == ICE.POWER_0P6: + self.vset_0p6 = msg[2] logger.info("Set 0.6V rail to vset=%d, vout=%.2f", self.vset_0p6, (0.537 + 0.0185 * self.vset_0p6) * DEFAULT_POWER_0P6) - elif pwr_idx is ICE.POWER_1P2: - self.vset_1p2 = ord(msg[2]) + elif pwr_idx == ICE.POWER_1P2: + self.vset_1p2 = msg[2] logger.info("Set 1.2V rail to vset=%d, vout=%.2f", self.vset_1p2, (0.537 + 0.0185 * self.vset_1p2) * DEFAULT_POWER_1P2) - elif pwr_idx is ICE.POWER_VBATT: - self.vset_vbatt = ord(msg[2]) + elif pwr_idx == ICE.POWER_VBATT: + self.vset_vbatt = msg[2] logger.info("Set VBatt rail to vset=%d, vout=%.2f", self.vset_vbatt, (0.537 + 0.0185 * self.vset_vbatt) * DEFAULT_POWER_VBATT) else: logger.error("Illegal power index: %d", pwr_idx) raise Exception self.ack() - elif msg[0] == 'o': - if pwr_idx is ICE.POWER_0P6: - self.power_0p6_on = bool(ord(msg[2])) + elif msg[0] == ord('o'): + if pwr_idx == ICE.POWER_0P6: + self.power_0p6_on = bool(msg[2]) logger.info("Set 0.6V rail %s", ('off','on')[self.power_0p6_on]) - elif pwr_idx is ICE.POWER_1P2: - self.power_1p2_on = bool(ord(msg[2])) + elif pwr_idx == ICE.POWER_1P2: + self.power_1p2_on = bool(msg[2]) logger.info("Set 1.2V rail %s", ('off','on')[self.power_1p2_on]) - elif pwr_idx is ICE.POWER_VBATT: - self.power_vbatt_on = bool(ord(msg[2])) + elif pwr_idx == ICE.POWER_VBATT: + self.power_vbatt_on = bool(msg[2]) logger.info("Set VBatt rail %s", ('off','on')[self.power_vbatt_on]) - elif minor >= 3 and pwr_idx is ICE.POWER_GOC: - self.power_goc_on = bool(ord(msg[2])) + elif minor >= 3 and pwr_idx == ICE.POWER_GOC: + self.power_goc_on = bool(msg[2]) logger.info("Set GOC circuit %s", ('off','on')[self.power_goc_on]) else: logger.error("Illegal power index: %d", pwr_idx) raise Exception self.ack() else: - logger.error("bad 'p' subtype: " + msg[0]) + logger.error("bad 'p' subtype: %c", msg[0]) raise UnknownCommandException else: logger.error("Unknown msg type: " + msg_type) @@ -809,6 +803,11 @@ def min_proto(proto): raise def respond(self, msg, ack=True): + if isinstance(msg, str): + msg = msg.encode('ascii') + elif not isinstance(msg, bytes): + msg = bytes(msg) + with self.s_lock: if (ack): self.s.write(bytes((0,))) @@ -819,18 +818,15 @@ def respond(self, msg, ack=True): self.event %= 256 self.s.write(bytes((len(msg),))) - if type(msg) != bytes: - msg = bytes(msg, 'utf-8') - if len(msg): self.s.write(msg) logger.debug("Sent a response of length: " + str(len(msg))) def ack(self): - self.respond('') + self.respond(b'') def nak(self): - self.respond('', ack=False) + self.respond(b'', ack=False) @staticmethod @@ -909,13 +905,13 @@ def __repr__(self): return self.__str__() def __setattr__(self, name, value): - if name is 'direction': + if name == 'direction': if value not in (Gpio.GPIO_INPUT, Gpio.GPIO_OUTPUT, Gpio.GPIO_TRISTATE): raise ValueError("Attempt to set illegal direction {}".format(value)) - if name is 'level': + if name == 'level': if value not in (True, False): raise ValueError("GPIO level must be true or false. Got {}".format(value)) - if name is 'interrupt': + if name == 'interrupt': if value not in (True, False): raise ValueError("GPIO interrupt must be true or false. Got {}".format(value)) object.__setattr__(self, name, value) diff --git a/m3/m3_common.py b/m3/m3_common.py index 91281a1..0db8f96 100755 --- a/m3/m3_common.py +++ b/m3/m3_common.py @@ -1,12 +1,5 @@ #!/usr/bin/env python -# Coerce Py2k to act more like Py3k -from __future__ import (absolute_import, division, print_function, unicode_literals) -from builtins import ( - ascii, bytes, chr, dict, filter, hex, input, int, isinstance, list, map, - next, object, oct, open, pow, range, round, str, super, zip, - ) - import argparse import atexit import binascii @@ -26,16 +19,10 @@ # if Py2K: import imp -try: - from __init__ import __version__ - import m3_logging - from ice import ICE - from ice_simulator import _FAKE_SERIAL_CONNECTTO_ENDPOINT -except: - from . import __version__ - from . import m3_logging - from .ice import ICE - from .ice_simulator import _FAKE_SERIAL_CONNECTTO_ENDPOINT +from . import __version__ +from . import m3_logging +from .ice import ICE +from .ice_simulator import _FAKE_SERIAL_CONNECTTO_ENDPOINT logger = m3_logging.getLogger(__name__) @@ -70,8 +57,7 @@ def default_value(self, prompt, default, extra=None, invert=False): if self.args.yes: fn = print else: - try: fn = raw_input - except NameError: fn = input #Py3 version + fn = input if extra: r = fn(prompt + ' [' + default + extra + ']: ') else: @@ -596,10 +582,6 @@ def pick_serial(): for i in range(len(candidates)): logger.info("\t[{}] {}".format(i, candidates[i])) try: - resp = raw_input("Choose a serial port "\ - "(Ctrl-C to quit): ").strip() - except NameError: - #Py3 resp = input("Choose a serial port "\ "(Ctrl-C to quit): ").strip() except KeyboardInterrupt: @@ -631,7 +613,7 @@ def guess_type_is_hex(binfile): hexencoded += line[0:2].upper() else: binfd = open(binfile, 'rb') - hexencoded = binascii.hexlify(binfd.read()).upper() + hexencoded = binascii.hexlify(binfd.read()).decode('ascii').upper() if (len(hexencoded) % 2 == 0) and (len(hexencoded) % 4 != 0): hexencoded += '00' # use of 8-bit variables can lead to byte-aligned bin files @@ -872,7 +854,7 @@ def cmd_message(self): # TODO: The encode/decode at various points is a bit silly? data = binascii.unhexlify(data) data = data[::-1] - data = binascii.hexlify(data) + data = binascii.hexlify(data).decode('ascii') if self.m3_ice.args.dont_run_after: run_after = False @@ -1167,7 +1149,7 @@ def cmd(self): #mbus_addr = struct.pack(">I", mbus_long_addr) else: raise Exception("Bad MBUS Addr") - logger.info('MBus_PRC_Addr: ' + binascii.hexlify(mbus_addr)) + logger.info('MBus_PRC_Addr: ' + binascii.hexlify(mbus_addr).decode('ascii')) # 0x0 = mbus register write mbus_regwr = struct.pack(">I", ( prc_addr << 4) | 0x0 ) @@ -1210,9 +1192,9 @@ def cmd(self): for mem_addr, payload in zip(payload_addrs, payload_chunks): mem_addr = struct.pack(">I", mem_addr) - logger.debug('Mem Addr: ' + binascii.hexlify(mem_addr)) + logger.debug('Mem Addr: ' + binascii.hexlify(mem_addr).decode('ascii')) - logger.debug('Payload: ' + binascii.hexlify(payload)) + logger.debug('Payload: ' + binascii.hexlify(payload).decode('ascii')) data = mem_addr + payload #logger.debug( 'data: ' + binascii.hexlify(data )) @@ -1299,12 +1281,12 @@ def _callback_runner(self): def callback_print(self, _time, address, data, cb0, cb1): print("@ Time: " + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(_time)) - + " ADDR: 0x" + binascii.hexlify(address) - + " DATA: 0x" + binascii.hexlify(data) + + " ADDR: 0x" + binascii.hexlify(address).decode('ascii') + + " DATA: 0x" + binascii.hexlify(data).decode('ascii') + " (ACK: " + str(not cb1) + ")") def callback_csv(self, _time, address, data, cb0, cb1): - self._csv_writer.writerow((_time, binascii.hexlify(address), binascii.hexlify(data), cb0, cb1)) + self._csv_writer.writerow((_time, binascii.hexlify(address).decode('ascii'), binascii.hexlify(data).decode('ascii'), cb0, cb1)) def __init__(self, args, ice, callbacks=None): self.args = args @@ -1316,7 +1298,7 @@ def __init__(self, args, ice, callbacks=None): self.callbacks.append(self.callback_print) if self.args.csv is not None: - self._csv_file = open(self.args.csv, 'wb') + self._csv_file = open(self.args.csv, 'w', newline="") self._csv_writer = csv.writer(self._csv_file) self.callbacks.append(self.callback_csv) diff --git a/m3/m3_gdb.py b/m3/m3_gdb.py index 5388e56..83b525a 100644 --- a/m3/m3_gdb.py +++ b/m3/m3_gdb.py @@ -7,13 +7,6 @@ # # -# Coerce Py2k to act more like Py3k -from __future__ import (absolute_import, division, print_function, unicode_literals) -from builtins import ( - ascii, bytes, chr, dict, filter, hex, input, int, isinstance, list, map, - next, object, oct, open, pow, range, round, str, super, zip, - ) - import binascii import logging import os @@ -24,15 +17,14 @@ import threading import time -from m3.m3_mbus import MBusInterface -from m3.m3_mbus import Memory -from m3.m3_mbus import RegFile +from .m3_mbus import MBusInterface +from .m3_mbus import Memory +from .m3_mbus import RegFile #inspired by # https://github.com/0vercl0k/ollydbg2-python/blob/master/samples/gdbserver/gdbserver.py#L147 -try: from . import m3_logging -except ValueError: import logging as m3_logging +from . import m3_logging class GdbRemote(object): ''' @@ -65,7 +57,7 @@ def __init__(this, tcp_port = 10001, log_level = logging.WARN): except socket.error as msg: this.log.error('Bind to port: ' + str(tcp_port) + \ ' failed. Error Code : ' + \ - str(msg[0]) + ' Message ' + msg[1] ) + str(msg.errno) + ' Message ' + msg.strerror ) raise this.PortTakenException() this.log.info( 'Bound to port: ' + str(tcp_port)) @@ -114,7 +106,7 @@ def _gdb_rx(this): #grab the opening '+' this.log.debug('Grabbing opening +') plus = conn.recv(1) - assert(plus == '+') + assert(plus == b'+') # start a response thread TxTid = threading.Thread( target=this._gdb_tx, args=(conn,) ) @@ -153,7 +145,7 @@ def _gdb_tx(this, conn): return elif msg == '+': this.log.debug('TX: ' + str(msg)) - conn.send(msg) + conn.sendall(msg.encode('ascii')) else: this._gdb_resp(conn, msg) @@ -223,7 +215,7 @@ def _gdb_recv(this, conn): this.log.debug('RX: ' + str(rawdata) ) # CTRL+C - if chr(0x03) in rawdata: + if b'\x03' in rawdata: raise this.CtrlCException() # static buffer to tack on the new data @@ -232,24 +224,24 @@ def _gdb_recv(this, conn): except AttributeError: this._buf_data = rawdata # acks "+" at the beginning can be safely removed - if this._buf_data[0] == '+': + if this._buf_data[0:1] == b'+': this._buf_data= this._buf_data[1:] msg = None - chkIdx = this._buf_data.find('#') + chkIdx = this._buf_data.find(b'#') # look for a checksum marker + 2 checksum bytes if (chkIdx > 0) and (len(this._buf_data) >= chkIdx + 3): #this.log.debug('Found # at: ' + str(chkIdx) ) # get the message and checksum - assert(this._buf_data[0] == '$') + assert(this._buf_data[0:1] == b'$') msg = this._buf_data[1:chkIdx] msgSum = int(this._buf_data[chkIdx+1:chkIdx+3],16) calcSum= 0 for byte in msg: - calcSum = (calcSum + ord(byte)) & 0xff + calcSum = (calcSum + byte) & 0xff if calcSum != msgSum: raise Exception("Checksum Error") @@ -257,6 +249,8 @@ def _gdb_recv(this, conn): #this.log.debug('Checksum pass') pass + msg = msg.decode('latin-1') + if '}' in msg: raise Exception("FIXME: escape sequence") @@ -290,7 +284,7 @@ def _gdb_resp(this, conn, msg): gdb_msg = '$%s#%.2x' % (msg, chkSum) this.log.debug('TX: ' + str(gdb_msg)) - conn.send( gdb_msg ) + conn.sendall(gdb_msg.encode('ascii')) @@ -428,7 +422,7 @@ def _halt_thread(this): halt management thread, waits for halt to be triggered, then calls halt_cb("S05") if halt_cb is valid ''' - while not this.stop.isSet(): + while not this.stop.is_set(): try: mbus_addr, mbus_data = this.queue.get( True, 10) this.log.debug("HALT triggered") @@ -552,7 +546,7 @@ def cmd_M(this, subcmd): data = binascii.unhexlify(data) while size_bytes > 0: - b = struct.unpack("B", data[0])[0] + b = data[0] this.log.debug('Writing ' + hex(b) + ' to ' \ + hex(addr)) @@ -634,7 +628,7 @@ def cmd_m(this, subcmd): encode_str = this.encode_str[read_bytes] val = this.mem[(addr,read_bytes * 8)] this.log.debug('mem read: ' + hex(addr) + ' ' + hex(val)) - val = struct.pack(encode_str, val).encode('hex')#lit endian + val = struct.pack(encode_str, val).hex()#lit endian resp += val addr += read_bytes size_bytes -= read_bytes @@ -649,7 +643,7 @@ def cmd_p(this, subcmd): val = this.rf[reg] if reg == 'pc': val -= 4 - val = struct.pack(encode ,val).encode('hex') #lit endian + val = struct.pack(encode ,val).hex() #lit endian val = '00' * this.regsPads[reg] + val # add some front-padding return val @@ -804,7 +798,7 @@ def cmd_M(this, subcmd): this.log.info('mem write: ' + hex(addr) + ' of ' + str(size_bytes)) data = binascii.unhexlify(data) while size_bytes > 0: - b = struct.unpack("B", data[0])[0] + b = data[0] this.log.debug('Writing ' + hex(b) + ' to ' \ + hex(addr)) @@ -850,15 +844,15 @@ def cmd_m(this, subcmd): addr,size_bytes = map(lambda x: int(x, 16), [addr, size_bytes]) this.log.info('mem read: ' + hex(addr) + ' of ' + str(size_bytes)) if size_bytes == 4: - return struct.pack('I", mbus_long_addr) else: raise Exception("Bad MBUS Addr") - logger.debug('MBus_PRC_Addr: ' + binascii.hexlify(mbus_addr)) + logger.debug('MBus_PRC_Addr: ' + binascii.hexlify(mbus_addr).decode('ascii')) # 0x0 = mbus register write mbus_regwr = struct.pack(">I", ( prc_addr << 4) | 0x0 ) @@ -540,9 +529,9 @@ def cmd_program(self): for mem_addr, payload in zip(payload_addrs, payload_chunks): mem_addr = struct.pack(">I", mem_addr) - logger.debug('Mem Addr: ' + binascii.hexlify(mem_addr)) + logger.debug('Mem Addr: ' + binascii.hexlify(mem_addr).decode('ascii')) - logger.debug('Payload: ' + binascii.hexlify(payload)) + logger.debug('Payload: ' + binascii.hexlify(payload).decode('ascii')) data = mem_addr + payload #logger.debug( 'data: ' + binascii.hexlify(data )) @@ -585,7 +574,7 @@ class InputManager(object): ''' def run(this): pass def get(this): - s = raw_input("<: ") + s = input("<: ") if len(s) == 1: return s[0], (), {} elif s[0] == '_': diff --git a/setup.py b/setup.py index eb9aab6..94e94df 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,4 @@ -try: - from setuptools import setup -except ImportError: - from distutils.core import setup +from setuptools import setup from m3 import __version__ @@ -9,6 +6,7 @@ 'name': 'm3', 'packages': ['m3'], 'version': __version__, + 'python_requires': '>=3.9,<3.10', 'author': 'Pat Pannuto', 'author_email': 'pat.pannuto@gmail.com', 'url': 'https://github.com/mbus/m3-python', @@ -33,22 +31,18 @@ "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python", - #"Programming Language :: Python :: 2", - #"Programming Language :: Python :: 2.7", - #"Programming Language :: Python :: 3", + "Programming Language :: Python :: 3", #"Programming Language :: Python :: 3.3", #"Programming Language :: Python :: 3.4", #"Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.9", - #"Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: CPython", #"Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development :: Embedded Systems", ], 'install_requires': [ - 'future', - 'nose', - 'pyserial', + 'pyserial>=3.5,<4', ], 'entry_points': { 'console_scripts': [ diff --git a/tests/baud_tests.py b/tests/baud_tests.py index 5cd030a..5ba59a3 100644 --- a/tests/baud_tests.py +++ b/tests/baud_tests.py @@ -95,9 +95,9 @@ def test_baudrate(self): result = nose.run( defaultTest=__name__, ) if result == True: - print 'TESTS PASSED' + print('TESTS PASSED') else: - print 'TESTS FAILED' + print('TESTS FAILED') logger.info('') diff --git a/tests/chip_id_tests.py b/tests/chip_id_tests.py index 5e14d36..65e6fb7 100644 --- a/tests/chip_id_tests.py +++ b/tests/chip_id_tests.py @@ -190,7 +190,7 @@ def test_goc_flash_default(self): '2c030000240300003412cdab08a30600', ]) fd, tmp_path = tempfile.mkstemp() - f = open(tmp_path, 'w') + f = open(tmp_path, 'wb') f.write( binascii.unhexlify(program)) f.close() os.close(fd) @@ -225,8 +225,8 @@ def test_goc_flash_default(self): result = nose.run( argv=['--processes=0'], defaultTest=__name__) if result == True: - print 'TESTS PASSED' + print('TESTS PASSED') else: - print 'TESTS FAILED' + print('TESTS FAILED') diff --git a/tests/gdb_session_test.py b/tests/gdb_session_test.py index 4a2b1f0..3654b71 100644 --- a/tests/gdb_session_test.py +++ b/tests/gdb_session_test.py @@ -22,6 +22,12 @@ import m3.m3_ice from m3.m3_gdb import * +def send_text(sock, msg): + sock.sendall(msg.encode('ascii')) + +def recv_text(sock, size): + return sock.recv(size).decode('ascii') + class TestGdbFull(object): # magic nose variable @@ -80,16 +86,16 @@ def serv_thread(driver): def cmd_noresp(sock, cmd): this.log.debug('TX: ' + cmd) - s.send(cmd) - plus = s.recv(1) + send_text(s, cmd) + plus = recv_text(s, 1) this.log.debug('plus: ' + plus) assert(plus == '+') def cmd(sock, cmd): cmd_noresp(sock, cmd) - rx_resp = s.recv(4096) + rx_resp = recv_text(s, 4096) this.log.debug('resp: ' + rx_resp) - s.send('+') + send_text(s, '+') return rx_resp this.log.info("Testing GDB Session") @@ -115,7 +121,7 @@ def cmd(sock, cmd): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect( ('localhost',this.port)) - s.send('+') + send_text(s, '+') this.log.info("starting transaction") @@ -283,9 +289,9 @@ def cmd(sock, cmd): ## CTRL-C occurs a little differently :( this.log.debug("Sending CTRL-C") - s.send( chr(0x03)) # CTRL-C + send_text(s, chr(0x03)) # CTRL-C # no plus - rx_resp = s.recv(4096) + rx_resp = recv_text(s, 4096) this.log.debug('resp: ' + rx_resp) assert(rx_resp == '$S05#b8') @@ -524,7 +530,7 @@ def cmd(sock, cmd): result = nose.run( defaultTest=__name__, ) if result == True: - print 'TESTS PASSED' + print ('TESTS PASSED') else: - print 'TESTS FAILED' + print ('TESTS FAILED') diff --git a/tests/gdb_simple_test.py b/tests/gdb_simple_test.py index 44986d7..cf9593c 100644 --- a/tests/gdb_simple_test.py +++ b/tests/gdb_simple_test.py @@ -20,6 +20,23 @@ from m3.m3_gdb import GdbRemote from m3.m3_gdb import test_GdbCtrl +def send_text(sock, msg): + sock.sendall(msg.encode('ascii')) + +def recv_text(sock, size): + return sock.recv(size).decode('ascii') + +def test_gdb_recv_preserves_binary_bytes(): + gdb = GdbRemote(0) + client, server = socket.socketpair() + try: + client.sendall(b'$X0,1:\x80#9f') + assert(gdb._gdb_recv(server) == 'X0,1:\x80') + finally: + client.close() + server.close() + gdb.sock.close() + class TestGdbSimple(object): _multiprocess_shared_ = False @@ -59,23 +76,23 @@ def test_interface(this): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect( ('localhost',this.port)) - s.send('+') + send_text(s, '+') this.log.info("qSupported") tx_cmd ='$qSupported:multiprocess+;swbreak+;hwbreak+;qRelocInsn+#c9' - s.send(tx_cmd) + send_text(s, tx_cmd) rx_cmd, rx_subcmd, _ = this.gdb.get() print (rx_cmd) print (rx_subcmd) rx_cmd += rx_subcmd[0] assert( rx_cmd == tx_cmd[1:-3]) - plus = s.recv(1) + plus = recv_text(s, 1) assert( plus == '+') tx_cmd = '$PacketSize=4096#03' this.gdb.put(tx_cmd[1:-3]) - rx_cmd = s.recv(BUF_SIZE) + rx_cmd = recv_text(s, BUF_SIZE) assert( rx_cmd == tx_cmd) s.close() @@ -106,13 +123,13 @@ def ctrl(gdb): def cmd(sock, cmd): this.log.debug('TX: ' + cmd) - s.send(cmd) - plus = s.recv(1) + send_text(s, cmd) + plus = recv_text(s, 1) this.log.debug('plus: ' + cmd) assert(plus == '+') - rx_resp = s.recv(4096) + rx_resp = recv_text(s, 4096) this.log.debug('resp: ' + cmd) - s.send('+') + send_text(s, '+') return rx_resp # this time we launch a thread to run the ctrl interface @@ -122,7 +139,7 @@ def cmd(sock, cmd): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect( ('localhost',this.port)) - s.send('+') + send_text(s, '+') this.log.info("qSupported") tx_cmd ='$qSupported:multiprocess+;swbreak+;hwbreak+;qRelocInsn+#c9' diff --git a/tests/ice_tests.py b/tests/ice_tests.py index b3bedb0..b4228d2 100644 --- a/tests/ice_tests.py +++ b/tests/ice_tests.py @@ -68,12 +68,12 @@ def test_baudrate(self): def test_discrete_i2c(self): logger.info("Test d") - ret = TestICE.ice.i2c_send(0xa5, "12345678".decode('hex')) + ret = TestICE.ice.i2c_send(0xa5, bytes.fromhex("12345678")) if ret != 5: logger.error("Failed to send whole short I2C message") logger.info(" Did you set fake_TestICE.ice to ACK all addresses?") logger.info(" That is: ./fake_TestICE.ice.py /tmp/com2 xxxxxxxx") - ret = TestICE.ice.i2c_send(0x69, ("ab"*511).decode('hex')) + ret = TestICE.ice.i2c_send(0x69, bytes.fromhex("ab"*511)) if ret != (1+511): logger.error("Failed to send whole long I2C message") @@ -96,10 +96,10 @@ def test_i2c_address(self): def test_goc(self): logger.info("Test f") - ret = TestICE.ice.goc_send("a5".decode('hex'), show_progress=False) + ret = TestICE.ice.goc_send(bytes.fromhex("a5"), show_progress=False) if ret != 1: logger.error("Failed to send whole short GOC message") - ret = TestICE.ice.goc_send(("96"+"ba"*511).decode('hex'), show_progress=False) + ret = TestICE.ice.goc_send(bytes.fromhex("96"+"ba"*511), show_progress=False) if ret != (1+511): logger.error("Failed to send whole long GOC message") @@ -120,11 +120,11 @@ def test_goc_onoff(self): def test_mbus_message(self): logger.info("Test b") - ret = TestICE.ice.mbus_send("5a".decode('hex'), "87654321".decode('hex')) + ret = TestICE.ice.mbus_send(bytes.fromhex("5a"), bytes.fromhex("87654321")) # ret value from addr is always 4 if ret != 8: logger.error("Failed to send whole short MBus message") - ret = TestICE.ice.mbus_send("69".decode('hex'), ("ab"*511).decode('hex')) + ret = TestICE.ice.mbus_send(bytes.fromhex("69"), bytes.fromhex("ab"*511)) if ret != (4+511): logger.error("Failed to send whole long MBus message") @@ -201,7 +201,7 @@ def test_mbus_should_interrupt(self): if i != 1: logger.error("Set/get mismatch mbus should int (1)") logger.error("Expected 1 Got " + str(i)) - TestICE.ice.mbus_send("ec".decode('hex'), "beef".decode('hex')) + TestICE.ice.mbus_send(bytes.fromhex("ec"), bytes.fromhex("beef")) i = TestICE.ice.mbus_get_should_interrupt() if i != 0: logger.error("Should interrupt clear failed") @@ -210,7 +210,7 @@ def test_mbus_should_interrupt(self): i = TestICE.ice.mbus_get_should_interrupt() if i != 2: logger.error("Set/get mismatch mbus should int (2)") - TestICE.ice.mbus_send("ec".decode('hex'), "beef".decode('hex')) + TestICE.ice.mbus_send(bytes.fromhex("ec"), bytes.fromhex("beef")) i = TestICE.ice.mbus_get_should_interrupt() if i != 2: logger.error("Should interrupt persistance failed") @@ -222,7 +222,7 @@ def test_mbus_use_priority(self): i = TestICE.ice.mbus_get_use_priority() if i != 1: logger.error("Set/get mismatch mbus should int (1)") - TestICE.ice.mbus_send("db".decode('hex'), "bead".decode('hex')) + TestICE.ice.mbus_send(bytes.fromhex("db"), bytes.fromhex("bead")) i = TestICE.ice.mbus_get_use_priority() if i != 0: logger.error("Should use_priority clear failed") @@ -231,17 +231,17 @@ def test_mbus_use_priority(self): i = TestICE.ice.mbus_get_use_priority() if i != 2: logger.error("Set/get mismatch mbus should int (2)") - TestICE.ice.mbus_send("ec".decode('hex'), "beef".decode('hex')) + TestICE.ice.mbus_send(bytes.fromhex("ec"), bytes.fromhex("beef")) i = TestICE.ice.mbus_get_use_priority() if i != 2: logger.error("Should use_priority persistance failed") def test_ein(self): logger.info("Test e") - ret = TestICE.ice.ein_send("a5".decode('hex')) + ret = TestICE.ice.ein_send(bytes.fromhex("a5")) if ret != 1: logger.error("Failed to send whole short EIN message") - ret = TestICE.ice.ein_send(("96"+"ba"*511).decode('hex')) + ret = TestICE.ice.ein_send(bytes.fromhex("96"+"ba"*511)) if ret != (1+511): logger.error("Failed to send whole long EIN message") @@ -270,7 +270,7 @@ def test_gpio_interrupt_mask(self): logger.info("Test gi") TARGET_GPIO_INT_MASK = 0xa53 TestICE.ice.gpio_set_interrupt_enable_mask(TARGET_GPIO_INT_MASK) - if TestICE.ice.gpio_get_interrupt_enable_mask != TARGET_GPIO_INT_MASK: + if TestICE.ice.gpio_get_interrupt_enable_mask() != TARGET_GPIO_INT_MASK: logger.error("Set/get mismatch gpio interrupt mask") def test_voltage_state(self): diff --git a/tests/mbus_write_test.py b/tests/mbus_write_test.py index 10078fc..d8c9cf1 100644 --- a/tests/mbus_write_test.py +++ b/tests/mbus_write_test.py @@ -80,7 +80,7 @@ def setup_class(cls, ): '2c030000240300003412cdab08a30600', ]) fd, cls.tmp_path = tempfile.mkstemp() - f = open(cls.tmp_path, 'w') + f = open(cls.tmp_path, 'wb') f.write( binascii.unhexlify(program)) f.close() os.close(fd) diff --git a/tox.ini b/tox.ini index 9e4f2f4..37303e4 100644 --- a/tox.ini +++ b/tox.ini @@ -4,14 +4,14 @@ # and then run "tox" from this directory. [tox] -#envlist = py27, py33, py34, py35, pypy, jython envlist = py39 # Defaults should be serial, but weird failures motivate forcing this? [testenv] +basepython = python3.9 commands = - nosetests -vv --collect-only - nosetests --processes=0 + nosetests -vv --collect-only {toxinidir}/tests/baud_tests.py {toxinidir}/tests/chip_id_tests.py {toxinidir}/tests/gdb_session_test.py {toxinidir}/tests/gdb_simple_test.py {toxinidir}/tests/ice_tests.py {toxinidir}/tests/mbus_write_test.py {toxinidir}/tests/timeout_test.py + nosetests --processes=0 {toxinidir}/tests/baud_tests.py {toxinidir}/tests/chip_id_tests.py {toxinidir}/tests/gdb_session_test.py {toxinidir}/tests/gdb_simple_test.py {toxinidir}/tests/ice_tests.py {toxinidir}/tests/mbus_write_test.py {toxinidir}/tests/timeout_test.py deps = nose pyserial