예제 #1
0
    def receivePackets(self, timeout):
        packets = []
        endTime = time.time() + timeout

        while 1:
            if len(packets):
                self._s.setblocking(0)
            else:
                newTimeout = endTime - time.time()
                if newTimeout < 0:
                    self._s.setblocking(0)
                else:
                    self._s.settimeout(newTimeout)

            try:
                frame = self._s.recvfrom(16)[0]
            except (socket.timeout, BlockingIOError):
                break

            packet = self._decodeFrame(frame)
            if not self._filterXcp or packet.data[0] == 0xFF or packet.data[
                    0] == 0xFE:
                packets.append(packet)
                if self._dumpTraffic:
                    print('RX ' + CANInterface.ID(packet.ident).getString() +
                          ' ' + CANInterface.getDataHexString(packet.data))
        return packets
예제 #2
0
    def _doTransmit(self, data, ident):
        if self._dumpTraffic:
            print('TX ' + CANInterface.ID(ident).getString() + ' ' +
                  CANInterface.getDataHexString(data))

        self._setTXTypeByIdent(ident)
        self._updateBitrateTXType()

        if self._cfgdHeaderIdent != ident:
            if ident & 0x80000000:
                self._runCmdWithCheck(
                    b'ATCP' +
                    bytes('{:02x}'.format((ident >> 24) & 0x1F), 'utf-8'))
                self._runCmdWithCheck(
                    b'ATSH' +
                    bytes('{:06x}'.format(ident & 0xFFFFFF), 'utf-8'))
            else:
                self._runCmdWithCheck(b'ATSH' +
                                      bytes('{:03x}'.format(ident
                                                            & 0x7FF), 'utf-8'))
            self._cfgdHeaderIdent = ident
        else:
            self._io.syncAndGetPrompt(
                self._intfcTimeout
            )  # Not synchronized by calling _runCmdWithCheck(), so do it here

        self._io.write(binascii.hexlify(data) + b'\r')
예제 #3
0
    def receivePackets(self, timeout):
        assert self._cfgdBitrate != None and self._cfgdFilter != None
        packets = []
        endTime = time.time() + timeout

        while 1:
            try:
                if len(packets):
                    packet = self._io.getReceived(timeout=0)
                else:
                    newTimeout = endTime - time.time()
                    if newTimeout < 0:
                        packet = self._io.getReceived(timeout=0)
                    else:
                        packet = self._io.getReceived(timeout=newTimeout)
            except queue.Empty:
                break

            if len(packet.data) > 0 and (packet.data[0] == 0xFF
                                         or packet.data[0] == 0xFE):
                packets.append(packet)
                if self._dumpTraffic:
                    print('RX ' + CANInterface.ID(packet.ident).getString() +
                          ' ' + CANInterface.getDataHexString(packet.data))
        return packets
예제 #4
0
 def transmitTo(self, data, ident):
     if self._dumpTraffic:
         print('TX ' + CANInterface.ID(ident).getString() + ' ' +
               CANInterface.getDataHexString(data))
     frame = self._buildFrame(data, ident)
     import binascii
     print(binascii.hexlify(frame).decode('utf-8'))
     self._sendFrame(frame)
예제 #5
0
    def transmitTo(self, data, ident):
        assert self._cfgdBitrate != None

        if self._dumpTraffic:
            print('TX ' + CANInterface.ID(ident).getString() + ' ' +
                  CANInterface.getDataHexString(data))
        frame = self._build_frame(data, ident)
        res = self._dll.icsneoTxMessages(self._neoObject, ctypes.byref(frame),
                                         self._icsNetId, 1)
        if res != 1:
            raise CANInterface.Error()
예제 #6
0
    def receive(self, timeout):
        assert self._cfgdBitrate != None

        if self._slaveAddr.resId.raw == 0xFFFFFFFF:
            return []

        packets = []

        if timeout != 0:
            endTime = time.time() + timeout
        else:
            endTime = None

        while 1:
            if endTime != None:
                newTimeout = int((endTime - time.time()) * 1000)
                if newTimeout > 0:
                    self._dll.icsneoWaitForRxMessagesWithTimeOut(
                        self._neoObject, newTimeout)
                else:
                    break
            else:
                endTime = 0  # allow one pass, then return on the next

            icsMsgs = (_ICSSpyMessage * 20000)()
            icsNMsgs = ctypes.c_int()
            icsNErrors = ctypes.c_int()

            res = self._dll.icsneoGetMessages(self._neoObject, icsMsgs,
                                              ctypes.byref(icsNMsgs),
                                              ctypes.byref(icsNErrors))
            if res != 1:
                raise CANInterface.Error()

            for iMsg in range(icsNMsgs.value):
                if icsMsgs[iMsg].NetworkID == self._icsNetId:
                    ident, data = self._decode_frame(icsMsgs[iMsg])
                    if len(data
                           ) > 0 and ident == self._slaveAddr.resId.raw and (
                               data[0] == 0xFF or data[0] == 0xFE):
                        if self._dumpTraffic:
                            print('RX ' + self._slaveAddr.resId.getString() +
                                  ' ' + CANInterface.getDataHexString(data))
                        packets.append(data)

            if len(packets) != 0:
                break
        return packets
예제 #7
0
    def receive(self, timeout):
        assert self._cfgdBitrate != None and self._cfgdFilter != None
        if self._slaveAddr.resId.raw == 0xFFFFFFFF:
            return []

        msgs = []
        endTime = time.time() + timeout

        while 1:
            try:
                if len(msgs):
                    packet = self._io.getReceived(timeout=0)
                else:
                    newTimeout = endTime - time.time()
                    if newTimeout < 0:
                        packet = self._io.getReceived(timeout=0)
                    else:
                        packet = self._io.getReceived(timeout=newTimeout)
            except queue.Empty:
                break

            if packet.ident == self._slaveAddr.resId.raw and (
                    packet.data[0] == 0xFF or packet.data[0] == 0xFE):
                msgs.append(packet.data)
                if self._dumpTraffic:
                    print('RX ' + self._slaveAddr.resId.getString() + ' ' +
                          CANInterface.getDataHexString(packet.data))
        return msgs
예제 #8
0
 def do_connect(self, cmdLine):
     'Connect to an XCP slave: connect'
     parser = ShellArgParser(prog='connect', description=__doc__)
     args = parser.parse_args(shlex.split(cmdLine))
     slave = CANInterface.XCPSlaveCANAddr(args.commandId, args.responseId)
     self.interface.connect(slave)
     self.connection = XCPConnection.Connection(self.interface)
예제 #9
0
    def receive(self, timeout):
        if self._slaveAddr.resId.raw == 0xFFFFFFFF:
            return []

        msgs = []
        endTime = time.time() + timeout

        while 1:
            if len(msgs):
                self._s.setblocking(0)
            else:
                newTimeout = endTime - time.time()
                if newTimeout < 0:
                    self._s.setblocking(0)
                else:
                    self._s.settimeout(newTimeout)

            try:
                frame = self._s.recvfrom(16)[0]
            except (socket.timeout, BlockingIOError):
                break

            packet = self._decodeFrame(frame)
            if not self._filterXcp or packet.data[0] == 0xFF or packet.data[
                    0] == 0xFE:
                msgs.append(packet.data)
                if self._dumpTraffic:
                    print('RX ' + self._slaveAddr.resId.getString() + ' ' +
                          CANInterface.getDataHexString(packet.data))
        return msgs
예제 #10
0
 def do_interface(self, cmdLine):
     'Connect to a CAN interface: connect <device URI>'
     parser = ShellArgParser(prog='interface', description=__doc__)
     parser.add_argument('deviceURI', help="CAN device URI", default=None)
     args = parser.parse_args(shlex.split(cmdLine))
     self.interface = CANInterface.MakeInterface(args.deviceURI)
     self.connection = None
예제 #11
0
 def setBitrate(self, bitrate):
     print('Setting bitrate ' + str(bitrate))
     setBitrateResult = self._dll.icsneoSetBitRate(self._neoObject, bitrate,
                                                   self._icsNetId)
     if setBitrateResult != 1:
         raise CANInterface.Error('Setting bitrate failed')
     else:
         self._cfgdBitrate = bitrate
예제 #12
0
    def __init__(self, parsedURL):
        if not SocketCANSupported():
            raise CANInterface.InterfaceNotSupported(
                'Socket module does not support CAN')

        self._s = socket.socket(socket.AF_CAN, socket.SOCK_RAW, socket.CAN_RAW)
        self._slaveAddr = CANInterface.XCPSlaveCANAddr(0xFFFFFFFF, 0xFFFFFFFF)
        self._dumpTraffic = False
        if parsedURL.netloc == None or parsedURL.netloc == "":
            dev = 'can0'
        else:
            dev = parsedURL.netloc
        try:
            self._s.bind((dev, ))
        except socket.error:
            self._s.close()
            raise CANInterface.ConnectFailed()

        urlQueryDict = urllib.parse.parse_qs(parsedURL.query)

        if 'filterxcp' in urlQueryDict:
            self._filterXcp = (urlQueryDict['filterxcp'][0] != "0")
        else:
            self._filterXcp = True
예제 #13
0
 def disconnect(self):
     self._slaveAddr = CANInterface.XCPSlaveCANAddr(0xFFFFFFFF, 0xFFFFFFFF)
     self._dumpTraffic = False
     filt = struct.pack("=II", 0, 0)
     self._s.setsockopt(socket.SOL_CAN_RAW, socket.CAN_RAW_FILTER, filt)
예제 #14
0
 def _decodeFrame(self, frame):
     ident, dlc, data = struct.unpack("=IB3x8s", frame)
     return CANInterface.Packet(ident, data[0:dlc])
예제 #15
0
    def __init__(self, parsedURL):
        self._icsNetId = None
        self._cfgdBitrate = None
        self._dumpTraffic = False
        self._filter = 0x00000000
        self._mask = 0x00000000
        if not hasattr(ctypes, 'windll'):
            raise CANInterface.InterfaceNotSupported('Not a Windows system')

        try:
            self._dll = ctypes.windll.icsneo40
        except OSError:
            raise CANInterface.InterfaceNotSupported(
                'Loading icsneo40.dll failed')

        neoDevices = (_ICSNeoDevice * 64)()
        self._neoObject = None

        nNeoDevices = ctypes.c_int(64)
        findResult = self._dll.icsneoFindNeoDevices(0xFFFFFFFF, neoDevices,
                                                    ctypes.byref(nNeoDevices))
        if findResult != 1:
            raise CANInterface.ConnectFailed('Finding ICS devices failed')

        splitPath = parsedURL.path.split('/')
        if len(splitPath) != 3:
            raise CANInterface.ConnectFailed(
                'Invalid ICS device path \'' + parsedURL.path +
                '\'; path is ics:<devtype>/<dev-index>/<net-id>')
        try:
            devTypeMask = _ICS_TYPE_STRING_MASKS[splitPath[0]]
        except KeyError:
            raise CANInterface.ConnectFailed('Invalid ICS device type \'' +
                                             splitPath[0] + '\'')
        try:
            devIdx = int(splitPath[1])
        except ValueError:
            raise CANInterface.ConnectFailed('Invalid ICS device index \'' +
                                             splitPath[1] + '\'')
        try:
            self._icsNetId = _ICS_NET_IDS[splitPath[2]]
        except KeyError:
            raise CANInterface.ConnectFailed('Invalid ICS net id \'' +
                                             splitPath[2])

        devOfType = [
            dev for dev in neoDevices[0:nNeoDevices.value]
            if dev.DeviceType & devTypeMask
        ]
        if len(devOfType) < devIdx + 1:
            raise CANInterface.ConnectFailed('ICS device of type \'' +
                                             splitPath[0] + '\', index ' +
                                             str(devIdx) + ' not found')

        sys.stderr.write('Connecting to ' +
                         _ICSDevTypeStr(neoDevices[0].DeviceType) + ' #' +
                         str(devIdx) + '\n')

        netIDs = (ctypes.c_ubyte * 64)()
        for i in range(len(netIDs)):
            netIDs[i] = i
        tempNeoObject = ctypes.c_int()
        openResult = self._dll.icsneoOpenNeoDevice(
            ctypes.byref(devOfType[devIdx]), ctypes.byref(tempNeoObject),
            netIDs, 1, 0)
        if openResult != 1:
            raise CANInterface.ConnectFailed('Opening ICS device failed')
        self._neoObject = tempNeoObject.value

        self.setBitrate(CANInterface.URLBitrate(parsedURL))

        self._slaveAddr = CANInterface.XCPSlaveCANAddr(0xFFFFFFFF, 0xFFFFFFFF)
예제 #16
0
            if len(packets):
                self._s.setblocking(0)
            else:
                newTimeout = endTime - time.time()
                if newTimeout < 0:
                    self._s.setblocking(0)
                else:
                    self._s.settimeout(newTimeout)

            try:
                frame = self._s.recvfrom(16)[0]
            except (socket.timeout, BlockingIOError):
                break

            packet = self._decodeFrame(frame)
            if not self._filterXcp or packet.data[0] == 0xFF or packet.data[
                    0] == 0xFE:
                packets.append(packet)
                if self._dumpTraffic:
                    print('RX ' + CANInterface.ID(packet.ident).getString() +
                          ' ' + CANInterface.getDataHexString(packet.data))
        return packets

    def setFilter(self, filt):
        rfilter = struct.pack('LL', filt[0], filt[1])
        self._s.setsockopt(socket.SOL_CAN_RAW, socket.CAN_RAW_FILTER, rfilter)


if SocketCANSupported():
    CANInterface.addInterface("socketcan", SocketCANInterface)
예제 #17
0
            icsNErrors = ctypes.c_int()

            res = self._dll.icsneoGetMessages(self._neoObject, icsMsgs,
                                              ctypes.byref(icsNMsgs),
                                              ctypes.byref(icsNErrors))
            if res != 1:
                raise CANInterface.Error()

            for iMsg in range(icsNMsgs.value):
                if icsMsgs[iMsg].NetworkID == self._icsNetId:
                    ident, data = self._decode_frame(icsMsgs[iMsg])
                    if (ident &
                            self._mask) == self._filter and len(data) > 0 and (
                                data[0] == 0xFF or data[0] == 0xFE):
                        packets.append(CANInterface.Packet(ident, data))
                        if self._dumpTraffic:
                            print('RX ' + CANInterface.ID(ident).getString() +
                                  ' ' + CANInterface.getDataHexString(data))

            if len(packets) != 0:
                break
        return packets

    def setFilter(self, filt):
        self._filter = filt[0]
        self._mask = filt[1]


if ICSSupported():
    CANInterface.addInterface("ics", ICSCANInterface)
예제 #18
0
 def transmit(self, data):
     if self._dumpTraffic:
         print('TX ' + self._slaveAddr.cmdId.getString() + ' ' +
               CANInterface.getDataHexString(data))
     frame = self._buildFrame(data, self._slaveAddr.cmdId.raw)
     self._sendFrame(frame)
예제 #19
0
                    if newTimeout < 0:
                        packet = self._io.getReceived(timeout=0)
                    else:
                        packet = self._io.getReceived(timeout=newTimeout)
            except queue.Empty:
                break

            if len(packet.data) > 0 and (packet.data[0] == 0xFF
                                         or packet.data[0] == 0xFE):
                packets.append(packet)
                if self._dumpTraffic:
                    print('RX ' + CANInterface.ID(packet.ident).getString() +
                          ' ' + CANInterface.getDataHexString(packet.data))
        return packets


CANInterface.addInterface("elm327", ELM327CANInterface)

if __name__ == "__main__":
    parsedurl = urllib.parse.urlparse(
        'elm327:/dev/rfcomm0?debuglog=elm327.log')
    elm327 = ELM327CANInterface(parsedurl)
    elm327.setFilter((0x000, 0x80000000))
    elm327.transmitTo(b'1234', 0x9FFFFFFF)
    elm327.transmitTo(b'1234', 0x7FF)
    time.sleep(1)
    packets = elm327.receivePackets(1)
    for packet in packets:
        print(repr(packet))
    elm327.close()
예제 #20
0
 def disconnect(self):
     self._slaveAddr = CANInterface.XCPSlaveCANAddr(0xFFFFFFFF, 0xFFFFFFFF)
     self._doSetFilter(self._filter)
     self._dumpTraffic = False
예제 #21
0
    def __init__(self, parsedURL):
        self._slaveAddr = None
        self._port = None
        self._bitrate = None
        self._txAddrStd = False
        self._cfgdBitrate = None
        self._cfgdTxAddrStd = False
        self._baudDivisor = None
        self._baud87Mult = None
        self._hasSetCSM0 = False
        self._tcpTimeout = 1.0
        self._serialTimeout = 0.2
        self._dumpTraffic = False
        self._cfgdHeaderIdent = None
        self._filter = None
        self._cfgdFilter = None
        self._noCsmQuirk = False
        self._isSt = False

        self._io = None

        urlQueryDict = urllib.parse.parse_qs(parsedURL.query)

        debugLogfile = None
        if 'debuglog' in urlQueryDict:
            if urlQueryDict['debuglog'][0] == 'stdout':
                debugLogfile = sys.stdout
            else:
                debugLogfile = open(urlQueryDict['debuglog'][0], 'w')

        if len(parsedURL.netloc):
            # If netloc is present, we're using a TCP connection
            addr = parsedURL.netloc.split(':')
            if len(addr) == 1:
                addr.append(35000)  # use default port
            elif len(addr) != 2:
                raise CANInterface.Error('Interface address invalid')
            s = socket.socket()
            s.create_connection(addr, 0)
            self._port = SocketAsPort(s)
            self._intfcTimeout = self._tcpTimeout
        else:
            if debugLogfile != None:
                port = LoggingPort(debugLogfile)
            else:
                port = serial.Serial()
            port.port = parsedURL.path
            port.open()
            foundBaud = False
            for baudRate in self._POSSIBLE_BAUDRATES:
                if DEBUG:
                    print('Trying ' + str(baudRate))
                port.baudrate = baudRate
                port.interCharTimeout = min(10 / baudRate, 0.0001)
                port.timeout = 0.05

                # Try sending a CR, if we get a prompt then it's probably the right baudrate
                port.flushInput()
                port.write(b'\r')
                response = port.read(16384)
                if len(response) == 0 or response[-1:] != b'>':
                    port.write(b'\r')
                    response = port.read(16384)
                    if len(response) == 0 or response[-1:] != b'>':
                        continue

                # Turn off echo, this also serves as a test to make sure we didn't randomly get a > at the end of some gibberish
                port.flushInput()
                port.write(b'ATE0\r')
                response = port.read(16)
                if not b'OK' in response:
                    continue

                # If we made contact at baudrate 500k, we're done
                if baudRate == 500000:
                    foundBaud = True
                    break

                # Not at 500k, try to change ELM to that
                port.timeout = 1.28  # Maximum possible timeout for ELM327
                port.flushInput()
                port.write(b'ATBRD08\r')
                response = port.read(2)
                if response == b'?\r':
                    # Device does not allow baudrate change, but we found its operating baudrate
                    foundBaud = True
                    break
                elif response == b'OK':
                    # Device allows baudrate change, try to switch to 500k
                    port.baudrate = 500000
                    port.flushInput()
                    response = port.read(11)
                    if response[0:6] != b'ELM327':
                        # Baudrate switch unsuccessful, try to recover
                        port.baudrate = baudRate
                        port.write(b'\r')
                        port.flushInput()
                        response = port.read(1024)
                        if len(response) == 0 or response[-1:] != b'>':
                            raise UnexpectedResponse('switching baudrate')

                    # Baudrate switched, send a CR to confirm we're on board
                    port.flushInput()
                    port.write(b'\r')
                    response = port.read(2)
                    if response != b'OK':
                        raise UnexpectedResponse('switching baudrate')
                    foundBaud = True
                    if response == b'ELM327 v1.5':
                        self._noCsmQuirk = True
                    break

            if not foundBaud:
                raise SerialError('could not find baudrate')
            port.timeout = 0

            self._port = port
            self._intfcTimeout = self._serialTimeout

        self._port.flushInput()

        # Start the I/O thread, which takes over control of the port
        self._io = ELM327IO(port)

        self._runCmdWithCheck(b'ATWS', checkOK=False,
                              closeOnFail=True)  # Software reset
        self._runCmdWithCheck(b'ATE0', closeOnFail=True)  # Turn off echo
        self._runCmdWithCheck(b'ATL0', closeOnFail=True)  # Turn off newlines
        self._runCmdWithCheck(b'ATS0', closeOnFail=True)  # Turn off spaces
        self._runCmdWithCheck(b'ATH1', closeOnFail=True)  # Turn on headers
        self._runCmdWithCheck(b'ATAL',
                              closeOnFail=True)  # Allow full length messages
        try:
            self._runCmdWithCheck(
                b'STFCP', closeOnFail=False)  # See if this is an ST device
            self._isSt = True
        except UnexpectedResponse:
            pass

        self.setBitrate(CANInterface.URLBitrate(parsedURL))

        self._slaveAddr = CANInterface.XCPSlaveCANAddr(0xFFFFFFFF, 0xFFFFFFFF)
예제 #22
0
    def threadFunc(self):
        while 1:
            if self._terminate.is_set():
                if DEBUG:
                    print(str(time.time()) + ' ELM327IO(): terminate set')
                return

            setPipelineClear = (not self._pipelineClear.is_set())
            setPromptReady = False
            linesRead = self._port.read(4096).translate(
                None, b'\0').splitlines(keepends=True)
            if len(linesRead) > 0:
                if len(self._lines) > 0:
                    self._lines[-1] += linesRead[0]
                    del linesRead[0]
                for lineRead in linesRead:
                    self._lines.append(lineRead)

                if self._lines[-1] == self._PROMPT:
                    if DEBUG:
                        print(str(time.time()) + ' promptReady.set()')
                    # Manage the promptReady Event; it's set if and only if there is an incomplete line consisting of a prompt.
                    setPromptReady = True
                    del self._lines[-1]
                while self._lines:
                    rawLine = self._lines.popleft()
                    if self._EOL in rawLine:
                        line = rawLine.strip(self._EOL)
                        # Is it empty?
                        if len(line) == 0:
                            pass
                        # Does it contain non-hex characters?
                        elif any(x for x in line
                                 if x not in b'0123456789ABCDEF'):
                            # Command response or a packet received with errors
                            PutDiscard(self._cmdResp, line)
                        else:
                            # Must be a valid received frame
                            if len(line) % 2 == 1:
                                idLen = 3
                                mask = 0
                            else:
                                idLen = 8
                                mask = 0x80000000
                            if len(line) >= idLen:
                                ident = int(line[0:idLen], 16)
                                data = binascii.unhexlify(line[idLen:])
                                packet = CANInterface.Packet(
                                    ident | mask, data)
                                PutDiscard(self._receive, packet)
                            else:
                                # Too short to be valid
                                PutDiscard(self._cmdResp, line)
                    else:
                        if rawLine == self._PROMPT:
                            if DEBUG:
                                print(str(time.time()) + ' promptReady.set()')
                            # Manage the promptReady Event; it's set if and only if there is an incomplete line consisting of a prompt.
                            setPromptReady = True
                        else:
                            self._lines.appendleft(rawLine)
                            break

            if self._timeToSend < time.time() and not self._transmit.empty():
                self._port.write(self._transmit.get_nowait())
                self._promptReady.clear()
                self._timeToSend = time.time() + self._ELM_RECOVERY_TIME
                setPromptReady = False
                setPipelineClear = False

            if setPromptReady:
                self._promptReady.set()
            if setPipelineClear and self._transmit.empty():
                self._pipelineClear.set()
예제 #23
0
parser.add_argument('-w', help="Warn if slave returns out of range for any parameter", dest="warnNotFound", action="store_true", default=False)
args = parser.parse_args()

config.loadConfigs(args.configFiles)
BoardTypes.SetupBoardTypes()
try:
    boardType = BoardTypes.types[args.targetType]
except KeyError:
    print('Could not find board type ' + str(args.targetType))
    sys.exit(1)

paramSpec = json.loads(args.paramSpecFile.read())

maxAttempts = 10

with CANInterface.MakeInterface(args.deviceURI) as interface:
    targetSlaves = boardType.SlaveListFromIdxArg(args.targetID)
    # If needed, ask the user to pick a slave from the list
    if len(targetSlaves) == 0:
        slaves = boardType.GetSlaves(interface)
        for i in range(0, len(slaves)):
            print(str(i) + ': ' + slaves[i][0].description() + ', ID ' + str(slaves[i][1]))
        index = int(input('Slave: '))
        if index >= len(slaves):
            exit
        targetSlaves = [slaves[index]]
                
    for targetSlave in targetSlaves:
        outFile=OpenOutFile(args.outputFile, targetSlave[1])
        if targetSlave[1] != None:
            sys.stderr.write('Connecting to target addr ' + targetSlave[0].description() + ', ID ' + str(targetSlave[1]) + '\n')
예제 #24
0
parser.add_argument('size', help='word size', type=int, choices=[1, 2, 4])
parser.add_argument('words',
                    help='number of words to read',
                    type=hexInt,
                    default=1)
args = parser.parse_args()

if args.size == 1:
    uploadDelegate = UploadDelegate8()
elif args.size == 2:
    uploadDelegate = UploadDelegate16()
elif args.size == 4:
    uploadDelegate = UploadDelegate32()

try:
    with CANInterface.MakeInterface(args.deviceURI) as interface:
        slave = CANInterface.XCPSlaveCANAddr(args.commandId, args.responseId)
        interface.connect(slave)
        connection = XCPConnection.Connection(interface, readTimeout,
                                              writeTimeout)

        for address in range(args.address, args.address + args.words):
            pointer = XCPConnection.Pointer(address, args.extension)
            print(uploadDelegate.upload(connection, pointer))
        connection.close()

except (OSError, CANInterface.ConnectFailed):
    try:
        interface.close()
    except NameError:
        pass