Esempio n. 1
0
    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
Esempio n. 2
0
    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
Esempio n. 3
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
Esempio n. 4
0
    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()
Esempio n. 5
0
    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
Esempio n. 6
0
    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)
Esempio n. 7
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]
Esempio n. 8
0
    def felica_SendCommand(self, command: bytearray) -> (int, bytearray):
        """
            Sends FeliCa command to the currently inlisted peer

            :param  command:         FeliCa command packet. (e.g. 00 FF FF 00 00  for Polling command)
            :returns:  (status, response)
                        status 1: Success, < 0: error
                        response: FeliCa response packet. (e.g. 01 NFCID2(8 bytes) PAD(8 bytes)  for Polling response)
        """
        commandlength = len(command)
        no_data = bytearray()

        if (commandlength > 0xFE):
            DMSG("Command length too long\n")
            return -1, no_data

        header = bytearray([
            PN532_COMMAND_INDATAEXCHANGE,
            self.inListedTag,
            commandlength + 1,
        ])
        if (self._interface.writeCommand(header, command)):
            DMSG("Could not send FeliCa command\n")
            return -2, no_data

        # Wait card response
        status, response = self._interface.readResponse()
        if (status < 0):
            DMSG("Could not receive response\n")
            return -3, no_data

        # Check status (response[0])
        if ((response[0] & 0x3F) != 0):
            DMSG("Status code indicates an error: ")
            DMSG_HEX(response[0])
            DMSG("\n")
            return -4, no_data

        # length check
        responseLength = response[1] - 1
        if ((status - 2) !=  responseLength):
            DMSG("Wrong response length\n")
            return -5, no_data

        response_data = response[2: 2 + responseLength]
        

        return 1, response_data
Esempio n. 9
0
    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
Esempio n. 10
0
    def felica_Polling(self, systemCode: int, requestCode: int, timeout: int = 1000) -> (int, bytearray, bytearray, int):
        """
            Poll FeliCa card. PN532 acting as reader/initiator,
            peer acting as card/responder.
            :param timeout:
            :param  systemCode:             Designation of System Code. When sending FFFFh as System Code,
                                               all FeliCa cards can return response.
            :param  requestCode:            Designation of Request Data as follows:
                                                 00h: No Request
                                                 01h: System Code request (to acquire System Code of the card)
                                                 02h: Communication performance request
            :returns: (status, idm, pwm, systemCodeResponse)
                        status                 0 = no card, 1 = FeliCa card detected, <0 = error
                        idm                    IDm of the card (8 bytes)
                        pmm                    PMm of the card (8 bytes)
                        systemCodeResponse     System Code of the card (Optional, 2bytes)
        """
        header = bytearray([
        PN532_COMMAND_INLISTPASSIVETARGET,
        1,
        1,
        FELICA_CMD_POLLING,
        (systemCode >> 8) & 0xFF,
        systemCode & 0xFF,
        requestCode & 0xFF,
        0,
        ])
        no_data = bytearray()

        if (self._interface.writeCommand(header)):
            DMSG("Could not send Polling command\n")
            return -1, no_data, no_data, 0

        status, response = self._interface.readResponse(timeout)
        if (status < 0):
            DMSG("Could not receive response\n")
            return -2, no_data, no_data, 0

        # Check NbTg (response[7])
        if (response[0] == 0):
            DMSG("No card had detected\n")
            return 0, no_data, no_data, 0
        elif (response[0] != 1):
            DMSG("Unhandled number of targets inlisted. NbTg: ")
            DMSG_HEX(response[7])
            DMSG("\n")
            return -3, no_data, no_data, 0

        self.inListedTag = response[1]
        DMSG("Tag number: ")
        DMSG_HEX(response[1])
        DMSG("\n")

        # length check
        responseLength = response[2]
        if (responseLength != 18 and responseLength != 20):
            DMSG("Wrong response length\n")
            return -4, no_data, no_data, 0

        idm = response[4:12]
        pwm = response[12:24]
        self._felicaIDm = idm
        self._felicaPMm = pwm

        if (responseLength == 20):
            systemCodeResponse = (response[20] << 8) + response[21]
        else:
            systemCodeResponse = 0

        return 1, idm, pwm, systemCodeResponse