def _getResponseLength(self, timeout: int): PN532_NACK = [0, 0, 0xFF, 0xFF, 0, 0] timer = 0 while (not self._isReady()): time.sleep(.001) # sleep 1 ms timer += 1 if ((0 != timeout) and (timer > timeout)): return -1 data = self._xfer_bytes([DATA_READ] + [0 for i in range(5)]) data = data[1:] # first byte is garbage DMSG('_getResponseLength length frame: {!r}'.format(data)) if data[:-2] != bytearray( [PN532_PREAMBLE, PN532_STARTCODE1, PN532_STARTCODE2]): DMSG('Invalid Response frame: {}'.format(data)) return PN532_INVALID_FRAME length = data[3] l_checksum = data[4] if (0 != (length + l_checksum) & 0xFF): DMSG('Invalid Length Checksum: len {:d} checksum {:d}'.format( length, l_checksum)) return PN532_INVALID_FRAME DMSG('_getResponseLength length is {:d}'.format(length)) # Not needed for SPI # request for last respond msg again # DMSG('_getResponseLength writing nack: {!r}'.format(PN532_NACK)) # self._send_bytes([DATA_WRITE] + PN532_NACK) return length
def _getResponseLength(self, timeout: int): PN532_NACK = [0, 0, 0xFF, 0xFF, 0, 0] timer = 0 while 1: responses = self._wire.transaction(reading(PN532_I2C_ADDRESS, 6)) data = bytearray(responses[0]) DMSG('_getResponseLength length frame: {!r}'.format(data)) if data[0] & 0x1: # check first byte --- status break # PN532 is ready time.sleep(.001) # sleep 1 ms timer += 1 if ((0 != timeout) and (timer > timeout)): return -1 if (PN532_PREAMBLE != data[1] or # PREAMBLE PN532_STARTCODE1 != data[2] or # STARTCODE1 PN532_STARTCODE2 != data[3] # STARTCODE2 ): DMSG('Invalid Length frame: {}'.format(data)) return PN532_INVALID_FRAME length = data[4] DMSG('_getResponseLength length is {:d}'.format(length)) # request for last respond msg again DMSG('_getResponseLength writing nack: {!r}'.format(PN532_NACK)) self._wire.transaction(writing(PN532_I2C_ADDRESS, PN532_NACK)) return length
def waitForConnection(self, timeout: int = LLCP_DEFAULT_TIMEOUT) -> int: type = 0 self.mode = 1 self.ns = 0 self.nr = 0 # Get CONNECT PDU DMSG("wait for a CONNECT PDU\n") while 1: status, data = self.link.read() if (2 > status): return -1 type = getPType(data) if (PDU_CONNECT == type): break elif (PDU_SYMM == type): if (not self.link.write(bytearray(self.SYMM_PDU))): return -2 else: return -3 # Put CC PDU DMSG("put a CC(Connection Complete) PDU to response the CONNECT PDU\n") ssap = getDSAP(data) dsap = getSSAP(data) header = buildHeader(dsap, PDU_CC, ssap) if (not self.link.write(header)): return -2 return 1
def writeCommand(self, header: bytearray, body: bytearray = bytearray()): self._command = header[0] data_out = [PN532_PREAMBLE, PN532_STARTCODE1, PN532_STARTCODE2] length = len(header) + len( body) + 1 # length of data field: TFI + DATA data_out.append(length) data_out.append((~length & 0xFF) + 1) # checksum of length data_out.append(PN532_HOSTTOPN532) dsum = PN532_HOSTTOPN532 + sum(header) + sum(body) # sum of TFI + DATA data_out += list(header) data_out += list(body) checksum = ((~dsum & 0xFF) + 1) & 0xFF # checksum of TFI + DATA data_out += [checksum, PN532_POSTAMBLE] DMSG("writeCommand: {} {} {}".format(header, body, data_out)) try: # send data self._wire.transaction(writing(PN532_I2C_ADDRESS, tuple(data_out))) except Exception as e: DMSG(e) DMSG( "\nToo many data to send, I2C doesn't support such a big packet\n" ) # I2C max packet: 32 bytes return PN532_INVALID_FRAME return self._readAckFrame()
def felica_Release(self) -> int: """ Release FeliCa card :returns: 1: Success, < 0: error """ # InRelease header = bytearray([ PN532_COMMAND_INRELEASE, 0x00, # All target ]) DMSG("Release all FeliCa target\n") if (self._interface.writeCommand(header)): DMSG("No ACK\n") return -1 # no ACK # Wait card response frameLength, response = self._interface.readResponse() if (frameLength < 0): DMSG("Could not receive response\n") return -2 # Check status (response[0]) if ((response[0] & 0x3F)!=0): DMSG("Status code indicates an error: ") DMSG_HEX(response[7]) DMSG("\n") return -3 return 1
def felica_RequestSystemCode(self) -> (int, List[int]): """ Sends FeliCa Request System Code command :returns: (status, systemCodeList) status 1: Success, < 0: error systemCodeList System Code list (Array length should longer than 16) """ cmd = bytearray([FELICA_CMD_REQUEST_SYSTEM_CODE]) + self._felicaIDm[:8] status, response = self.felica_SendCommand(cmd) responseLength = len(response) if (status != 1): DMSG("Request System Code command failed\n") return -1, [] numSystemCode = response[9] # length check if (responseLength < 10 + 2 * numSystemCode): DMSG("Request System Code command failed (wrong response length)\n") return -2, [] systemCodeList = [] for i in range(numSystemCode): systemCodeList.append((response[10 + i * 2] << 8) + response[10 + i * 2 + 1]) return 1, systemCodeList
def writeCommand(self, header: bytearray, body: bytearray = bytearray()) -> int: # dump serial buffer if (self._serial.inWaiting()): DMSG("Dump serial buffer: ") ret = self._serial.read() DMSG_HEX(ret) self.command = header[0] self._serial.write( PN532_WAKEUP ) # Extra long Preamble in case PN532 is in low VBat mode self._serial.write( bytearray([PN532_PREAMBLE, PN532_STARTCODE1, PN532_STARTCODE2])) length = len(header) + len( body) + 1 # length of data field: TFI + DATA self._serial.write( bytearray([length, (~length + 1) & 0xff, PN532_HOSTTOPN532])) # checksum of length dsum = PN532_HOSTTOPN532 + sum(header) + sum(body) DMSG("\nWrite: ") self._serial.write(header) self._serial.write(body) checksum = (~dsum + 1) & 0xff # checksum of TFI + DATA self._serial.write(bytearray([checksum, PN532_POSTAMBLE])) return self.readAckFrame()
def _writeFrame(self, header: bytearray, body: bytearray): data_out = [ DATA_WRITE, PN532_PREAMBLE, PN532_STARTCODE1, PN532_STARTCODE2 ] length = len(header) + len( body) + 1 # length of data field: TFI + DATA data_out.append(length) data_out.append((~length + 1) & 0xFF) data_out.append(PN532_HOSTTOPN532) dsum = PN532_HOSTTOPN532 + sum(header) + sum(body) # sum of TFI + DATA data_out += list(header) data_out += list(body) checksum = (~dsum + 1) & 0xFF # checksum of TFI + DATA data_out += [checksum, PN532_POSTAMBLE] DMSG("writeCommand: {} {} {}".format(header, body, data_out)) try: # send data self._send_bytes(data_out) except Exception as e: DMSG(e) DMSG("\nError writing frame\n") # I2C max packet: 32 bytes raise
def waitForDisconnection(self, timeout: int = LLCP_DEFAULT_TIMEOUT) -> int: type = 0 # Get DISC PDU DMSG("wait for a DISC PDU\n") while 1: status, data = self.link.read() if (2 > status): return -1 type = getPType(data) if (PDU_DISC == type): break elif (PDU_SYMM == type): if (not self.link.write(bytearray(self.SYMM_PDU))): return -2 else: return -3 # Put DM PDU DMSG("put a DM(Disconnect Mode) PDU to response the DISC PDU\n") # ssap = getDSAP(headerBuf) # dsap = getSSAP(headerBuf) header = buildHeader(self.dsap, PDU_DM, self.ssap) if (not self.link.write(header)): return -2 return 1
def readResponse(self, timeout: int = 1000) -> (int, bytearray): t = 0 length = self._getResponseLength(timeout) buf = bytearray() if length < 0: return length, buf # [RDY] 00 00 FF LEN LCS (TFI PD0 ... PDn) DCS 00 while 1: responses = self._wire.transaction( reading(PN532_I2C_ADDRESS, 6 + length + 2)) data = bytearray(responses[0]) if (data[0] & 1): # check first byte --- status break # PN532 is ready time.sleep(.001) # sleep 1 ms t += 1 if ((0 != timeout) and (t > timeout)): return -1, buf if (PN532_PREAMBLE != data[1] or # PREAMBLE PN532_STARTCODE1 != data[2] or # STARTCODE1 PN532_STARTCODE2 != data[3] # STARTCODE2 ): DMSG('Invalid Response frame: {}'.format(data)) return PN532_INVALID_FRAME, buf length = data[4] if (0 != (length + data[5] & 0xFF)): # checksum of length DMSG('Invalid Length Checksum: len {:d} checksum {:d}'.format( length, data[5])) return PN532_INVALID_FRAME, buf cmd = self._command + 1 # response command if (PN532_PN532TOHOST != data[6] or (cmd) != data[7]): return PN532_INVALID_FRAME, buf length -= 2 DMSG("readResponse read command: {:x}".format(cmd)) dsum = PN532_PN532TOHOST + cmd buf = data[8:-2] DMSG('readResponse response: {!r}\n'.format(buf)) dsum += sum(buf) checksum = data[-2] if (0 != (dsum + checksum) & 0xFF): DMSG("checksum is not ok: sum {:d} checksum {:d}\n".format( dsum, checksum)) return PN532_INVALID_FRAME, buf # POSTAMBLE data [-1] return length, buf
def readPassiveTargetID(self, cardbaudrate: int, timeout: int = 1000, inlist: bool = False) -> (bool, bytearray): """ Waits for an ISO14443A target to enter the field :param cardBaudRate: Baud rate of the card :param timeout: The number of tries before timing out :param inlist: If set to True, the card will be inlisted :returns: (True if successful, uid of the card) """ header = bytearray([ PN532_COMMAND_INLISTPASSIVETARGET, 1, # max 1 cards at once (we can set this to 2 later) cardbaudrate & 0xFF, ]) if (self._interface.writeCommand(header)) : return False, bytearray() # command failed # read data packet status, response = self._interface.readResponse(timeout) if (status < 0): return False, bytearray() # check some basic stuff # ISO14443A card response should be in the following format: # byte Description # ------------- ------------------------------------------ # b0 Tags Found # b1 Tag Number (only one used in this example) # b2..3 SENS_RES # b4 SEL_RES # b5 NFCID Length # b6..NFCIDLen NFCID if (response[0] != 1): return False, bytearray() sens_res = response[2] sens_res <<= 8 sens_res |= response[3] DMSG("ATQA: 0x") DMSG_HEX(sens_res) DMSG("SAK: 0x") DMSG_HEX(response[4]) DMSG("\n") # Card appears to be Mifare Classic uidLength = response[5] uid = bytearray(response[6:6 + uidLength]) if (inlist) : self.inListedTag = response[1] return True, uid
def _readAckFrame(self) -> int: PN532_ACK = [0, 0, 0xFF, 0, 0xFF, 0] DMSG("wait for ack at : ") DMSG(time.time()) DMSG('\n') t = 0 while 1: responses = self._wire.transaction( reading(PN532_I2C_ADDRESS, len(PN532_ACK) + 1)) data = bytearray(responses[0]) if (data[0] & 1): # check first byte --- status break # PN532 is ready time.sleep(.001) # sleep 1 ms t += 1 if (t > PN532_ACK_WAIT_TIME): DMSG("Time out when waiting for ACK\n") return PN532_TIMEOUT DMSG("ready at : ") DMSG(time.time()) DMSG('\n') ackBuf = list(data[1:]) if ackBuf != PN532_ACK: DMSG("Invalid ACK {}\n".format(ackBuf)) return PN532_INVALID_ACK return 0
def readAckFrame(self): PN532_ACK = bytearray([0, 0, 0xFF, 0, 0xFF, 0]) DMSG("\nAck: ") num, ackBuf = self.receive(len(PN532_ACK), PN532_ACK_WAIT_TIME) if (num <= 0): DMSG("Timeout\n") return PN532_TIMEOUT if (ackBuf != PN532_ACK): DMSG("Invalid\n") return PN532_INVALID_ACK return 0
def write(self, buf: bytearray, timeout: int = 0) -> int: """ Write a SNEP packet, the packet should be less than (255 - 2 - 3) bytes :param: buf the buffer to contain the packet :param: len length of the buffer :param: timeout max time to wait, 0 means no timeout :returns: >0 success =0 timeout <0 failed """ if (0 >= self.llcp.activate(timeout)): DMSG("failed to activate PN532 as a target\n") return -1 if (0 >= self.llcp.connect(timeout)): DMSG("failed to set up a connection\n") return -2 # response a success SNEP message header = bytearray([ SNEP_DEFAULT_VERSION, SNEP_REQUEST_PUT, 0, 0, 0, len(buf), ]) if (0 >= self.llcp.write(header, buf)): return -3 status, rbuf = self.llcp.read() if (6 > status): return -4 # check SNEP version if (SNEP_DEFAULT_VERSION != rbuf[0]): DMSG("The received SNEP message's major version is different\n") # Todo: send Unsupported Version response return -4 # expect a put request if (SNEP_RESPONSE_SUCCESS != rbuf[1]): DMSG("Expect a success response\n") return -4 self.llcp.disconnect(timeout) return 1
def disconnect(self, timeout: int = LLCP_DEFAULT_TIMEOUT) -> int: type = 0 # try to get a SYMM PDU status, data = self.link.read() if (2 > status): return -1 type = getPType(data) if (PDU_SYMM != type): return -1 # put a DISC PDU header = buildHeader(LLCP_DEFAULT_DSAP, PDU_DISC, LLCP_DEFAULT_SSAP) if (not self.link.write(header)): return -2 # wait for a DM PDU DMSG("wait for a DM PDU\n") while 1: status, data = self.link.read() if (2 > status): return -1 type = getPType(data) if (PDU_CC == type): break elif (PDU_DM == type): if (not self.link.write(bytearray(self.SYMM_PDU))): return -2 else: return -3 return 1
def inDataExchange(self, send: bytearray) -> (bool, bytearray): """ Exchanges an APDU with the currently inlisted peer :param send: Pointer to data to send :param response: Pointer to response data :param responseLength: Pointer to the response data length """ header = bytearray([ 0x40, # PN532_COMMAND_INDATAEXCHANGE self.inListedTag ]) if (self._interface.writeCommand(header, send)): return False, bytearray() status, response = self._interface.readResponse() if (status < 0): return False, bytearray() if ((response[0] & 0x3f) != 0): DMSG("Status code indicates an error\n") return False, bytearray() response = response[1:] return True, response
def setNdefFile(self, ndef: bytearray): ndefLength = len(ndef) if (ndefLength > (NDEF_MAX_LENGTH - 2)): DMSG("ndef file too large (> NDEF_MAX_LENGHT -2) - aborting") return self.ndef_file = bytearray([ndefLength >> 8, ndefLength & 0xFF]) + ndef
def writeCommand(self, header: bytearray, body: bytearray = bytearray()) -> int: self._command = header[0] self._writeFrame(header, body) timeout = PN532_ACK_WAIT_TIME while (not self._isReady()): time.sleep(.001) # sleep 1 ms timeout -= 1 if (0 >= timeout): DMSG("Time out when waiting for ACK\n") return PN532_TIMEOUT if (not self._readAckFrame()): DMSG("Invalid ACK\n") return PN532_INVALID_ACK return 0
def readResponse(self, timeout: int = 1000) -> (int, bytearray): DMSG("\nRead: ") # Frame Preamble and Start Code num, tmp = self.receive(3, timeout) if (num <= 0): return PN532_TIMEOUT, tmp if (0 != tmp[0] or 0 != tmp[1] or 0xFF != tmp[2]): DMSG("Preamble error") return PN532_INVALID_FRAME, bytearray() # receive length and check num, tmp = self.receive(2, timeout) if (num <= 0): return PN532_TIMEOUT, tmp length, lchksm = tmp[0], tmp[1] if (0 != (length + lchksm) & 0xff): DMSG("Length error") return PN532_INVALID_FRAME, bytearray() length -= 2 # receive self.command byte cmd = self.command + 1 # response self.command num, tmp = self.receive(2, timeout) if (num <= 0): return PN532_TIMEOUT, tmp if (PN532_PN532TOHOST != tmp[0] or cmd != tmp[1]): DMSG("Command error") return PN532_INVALID_FRAME, bytearray() num, buf = self.receive(length, timeout) if (num != length): return PN532_TIMEOUT, buf dsum = PN532_PN532TOHOST + cmd + sum(buf) # checksum and postamble num, tmp = self.receive(2, timeout) if (num <= 0): return PN532_TIMEOUT, tmp if (0 != (dsum + tmp[0]) & 0xff or 0 != tmp[1]): DMSG("Checksum error") return PN532_INVALID_FRAME, bytearray() return length, buf
def wakeup(self): self._serial.write(PN532_WAKEUP) # dump serial buffer if (self._serial.inWaiting()): DMSG("Dump serial buffer: ") ret = self._serial.read() DMSG_HEX(ret)
def _readAckFrame(self): """Returns true if ack was successfully read""" PN532_ACK = bytearray([0, 0, 0xFF, 0, 0xFF, 0]) ackBuf = self._xfer_bytes([DATA_READ] + [0 for i in range(len(PN532_ACK))]) DMSG("_readAckFrame: ack {}".format(ackBuf[1:])) return ackBuf[1:] == PN532_ACK
def mifareclassic_ReadDataBlock (self, blockNumber: int) -> (bool, bytearray): """ Tries to read an entire 16-bytes data block at the specified block address. :param blockNumber: The block number to authenticate. (0..63 for 1KB cards, and 0..255 for 4KB cards). :param data: Pointer to the byte array that will hold the retrieved data (if any) :returns: tuple (result, data) result: bool True if operation was successful, False if error data: bytearray data read """ DMSG("Trying to read 16 bytes from block ") DMSG(blockNumber) # Prepare the command header = bytearray([ PN532_COMMAND_INDATAEXCHANGE, 1, # Card number MIFARE_CMD_READ, # Mifare Read command = 0x30 blockNumber, # Block Number (0..63 for 1K, 0..255 for 4K) ]) # Send the command if (self._interface.writeCommand(header)): return False, bytearray() # Read the response packet status, response = self._interface.readResponse() # If byte 8 isn't 0x00 we probably have an error if (status < 0 or response[0] != 0x00): DMSG("Authentication failed\n") return False, bytearray() # Copy the 16 data bytes to the output buffer # Block content starts at byte 9 of a valid response return True, response[1:17]
def felica_ReadWithoutEncryption(self, serviceCodeList: List[int], blockList: List[int]) -> (int, List[bytearray]): """ Sends FeliCa Read Without Encryption command :param serviceCodeList: Service Code List (Big Endian) :param blockList: Block List (Big Endian, This API only accepts 2-byte block list element) :returns: (status, blockData) status 1: Success, < 0: error blockData Block Data """ no_data = [] numService = len(serviceCodeList) if (numService > FELICA_READ_MAX_SERVICE_NUM): DMSG("numService is too large\n") return -1, no_data numBlock = len(blockList) if (numBlock > FELICA_READ_MAX_BLOCK_NUM): DMSG("numBlock is too large\n") return -2, no_data cmd = bytearray([FELICA_CMD_READ_WITHOUT_ENCRYPTION]) + self._felicaIDm[:8] + bytearray([numService]) for i in range(numService): cmd.append(serviceCodeList[i] & 0xFF) cmd.append((serviceCodeList[i] >> 8) & 0xff) cmd.append(numBlock) for i in range(numBlock): cmd.append((blockList[i] >> 8) & 0xFF) cmd.append(blockList[i] & 0xff) status, response = self.felica_SendCommand(cmd) if (status != 1): DMSG("Read Without Encryption command failed\n") return -3, no_data # length check responseLength = len(response) if (responseLength != 12 + 16 * numBlock): DMSG("Read Without Encryption command failed (wrong response length)\n") return -4, no_data # status flag check if (response[9] != 0 or response[10] != 0): DMSG("Read Without Encryption command failed (Status Flag: ") DMSG_HEX(response[9]) DMSG_HEX(response[10]) DMSG(")\n") return -5, no_data k = 12 blockData = [] for i in range(numBlock): start = 12+ i * 16 blockData.append(response[start: start + 16]) return 1, blockData
def writeGPIO(self, pinstate: int) -> bool: """ Writes an 8-bit value that sets the state of the PN532's GPIO (P3) :warning: This function is provided exclusively for board testing and is dangerous since it will throw an error if any pin other than the ones marked "Can be used as GPIO" are modified! All pins that can not be used as GPIO should ALWAYS be left high (value = 1) or the system will become unstable and a HW reset will be required to recover the PN532. pinState[0] = P30 Can be used as GPIO pinState[1] = P31 Can be used as GPIO pinState[2] = P32 *** RESERVED (Must be 1!) *** pinState[3] = P33 Can be used as GPIO pinState[4] = P34 *** RESERVED (Must be 1!) *** pinState[5] = P35 Can be used as GPIO :returns 1 if everything executed properly, 0 for an error """ # Make sure pinstate does not try to toggle P32 or P34 pinstate |= (1 << PN532_GPIO_P32) | (1 << PN532_GPIO_P34) # Fill command buffer header = bytearray([PN532_COMMAND_WRITEGPIO, (PN532_GPIO_VALIDATIONBIT | pinstate), # P3 Pins 0x00]) # P7 GPIO Pins (not used ... taken by I2C) DMSG("Writing P3 GPIO: ") DMSG_HEX(header) DMSG("\n") # Send the WRITEGPIO command (0x0E) if (self._interface.writeCommand(header)): return False status, response = self._interface.readResponse() return status >= 0
def readGPIO(self) -> int: """ Reads the state of the PN532's GPIO pins (P3) :returns: An 8-bit value containing the pin state where: pinState[0] = P30 pinState[1] = P31 pinState[2] = P32 pinState[3] = P33 pinState[4] = P34 pinState[5] = P35 """ header = bytearray([PN532_COMMAND_READGPIO]) # Send the READGPIO command (0x0C) if (self._interface.writeCommand(header)): return 0x0 status, response = self._interface.readResponse() # READGPIO response without prefix and suffix should be in the following format: # # byte Description # ------------- ------------------------------------------ # b0 P3 GPIO Pins # b1 P7 GPIO Pins (not used ... taken by I2C) # b2 Interface Mode Pins (not used ... bus select pins) DMSG("P3 GPIO: ") DMSG_HEX(response[0]) DMSG("P7 GPIO: ") DMSG_HEX(response[1]) DMSG("I0I1 GPIO: ") DMSG_HEX(response[2]) DMSG("\n") return response[0]
def felica_RequestService(self, nodeCodeList: List[int]) -> (int, List[int]): """ Sends FeliCa Request Service command :param nodeCodeList: Node codes(Big Endian) :returns: (status, keyVersions) status 1: Success, < 0: error keyVersions Key Version of each Node (Big Endian) """ no_data = [] numNode = len(nodeCodeList) if (numNode > FELICA_REQ_SERVICE_MAX_NODE_NUM): DMSG("numNode is too large\n") return -1, no_data cmd = bytearray([FELICA_CMD_REQUEST_SERVICE]) + self._felicaIDm[:8] + bytearray([numNode]) for i in range(numNode): cmd.append(nodeCodeList[i] & 0xFF) cmd.append((nodeCodeList[i] >> 8) & 0xff) status, response = self.felica_SendCommand(cmd) if (status != 1): DMSG("Request Service command failed\n") return -2, no_data # length check responseLength = len(response) if (responseLength != 10 + 2 * numNode): DMSG("Request Service command failed (wrong response length)\n") return -3, no_data keyVersions = [] for i in range(numNode): keyVersions.append(response[10 + i * 2] + (response[10 + i * 2 + 1] << 8)) return 1, keyVersions
def felica_RequestResponse(self) -> (int, int): """ Sends FeliCa Request Response command :returns: (status, mode) status 1: Success, < 0: error mode Current Mode of the card """ cmd = bytearray([FELICA_CMD_REQUEST_RESPONSE]) + self._felicaIDm[:8] status, response = self.felica_SendCommand(cmd) responseLength = len(response) if (status != 1): DMSG("Request Response command failed\n") return -1, -1 # length check if (responseLength != 10): DMSG("Request Response command failed (wrong response length)\n") return -2, -1 mode = response[9] return 1, mode
def readResponse(self, timeout: int = 1000) -> (int, bytearray): timer = 0 buf = bytearray() result = 0 length = self._getResponseLength(timeout) if length < 0: return length, buf data = self._xfer_bytes( [DATA_READ] + [0 for i in range(length + 1) ]) # Total length - 1 for RW byte, SPI is full duplex cmd = self._command + 1 # response command if (PN532_PN532TOHOST != data[0] or (cmd) != data[1]): return PN532_INVALID_FRAME, buf length -= 2 DMSG("readResponse read command: {:x}".format(cmd)) dsum = PN532_PN532TOHOST + cmd buf = data[2:-2] DMSG('readResponse response: {!r}\n'.format(buf)) dsum += sum(buf) checksum = data[-2] if (0 != (dsum + checksum) & 0xFF): DMSG("checksum is not ok: sum {:d} checksum {:d}\n".format( dsum, checksum)) return PN532_INVALID_FRAME, buf # POSTAMBLE data [-1] return length, buf
def SAMConfig(self) -> bool: """ Configures the SAM (Secure Access Module) :returns: True if success, False if error """ header = bytearray([PN532_COMMAND_SAMCONFIGURATION, 0x01, # normal mode 0x14, # timeout 50ms * 20 = 1 second 0x01]) # use IRQ pin! DMSG("SAMConfig\n") if (self._interface.writeCommand(header)): return False status, response = self._interface.readResponse() return status >= 0
def felica_WriteWithoutEncryption(self, serviceCodeList: List[int], blockList: List[int], blockData: List[bytearray]) -> int: """ Sends FeliCa Write Without Encryption command :param serviceCodeList: Service Code List (Big Endian) :param blockList: Block List (Big Endian, This API only accepts 2-byte block list element) :returns: status 1: Success, < 0: error """ numService, numBlock = len(serviceCodeList), len(blockList) if (numService > FELICA_WRITE_MAX_SERVICE_NUM): DMSG("numService is too large\n") return -1 if (numBlock > FELICA_WRITE_MAX_BLOCK_NUM): DMSG("numBlock is too large\n") return -2 cmd = bytearray([FELICA_CMD_WRITE_WITHOUT_ENCRYPTION]) + self._felicaIDm[:8] + bytearray([numService]) for i in range(numService): cmd.append(serviceCodeList[i] & 0xFF) cmd.append((serviceCodeList[i] >> 8) & 0xff) cmd.append(numBlock) for i in range(numBlock): cmd.append((blockList[i] >> 8) & 0xFF) cmd.append(blockList[i] & 0xff) for i in range(numBlock): for k in range(16): cmd.append(blockData[i][k]) status, response = self.felica_SendCommand(cmd) responseLength = len(response) if (status != 1): DMSG("Write Without Encryption command failed\n") return -3 # length check if (responseLength != 11): DMSG("Write Without Encryption command failed (wrong response length)\n") return -4 # status flag check if (response[9] != 0 or response[10] != 0): DMSG("Write Without Encryption command failed (Status Flag: ") DMSG_HEX(response[9]) DMSG_HEX(response[10]) DMSG(")\n") return -5 return 1