Esempio n. 1
0
class MFRC522:
    # RST Pin number,default 22
    NRSTPD = 22
    MAX_LEN = 16

    # RC522命令字
    PCD_IDLE = 0x00
    PCD_AUTHENT = 0x0E
    PCD_RECEIVE = 0x08
    PCD_TRANSMIT = 0x04
    PCD_TRANSCEIVE = 0x0C
    PCD_RESETPHASE = 0x0F
    PCD_CALCCRC = 0x03

    # PICC命令字
    PICC_REQIDL = 0x26
    PICC_REQALL = 0x52
    PICC_ANTICOLL = 0x93
    PICC_SElECTTAG = 0x93
    PICC_AUTHENT1A = 0x60
    PICC_AUTHENT1B = 0x61
    PICC_READ = 0x30
    PICC_WRITE = 0xA0
    PICC_DECREMENT = 0xC0
    PICC_INCREMENT = 0xC1
    PICC_RESTORE = 0xC2
    PICC_TRANSFER = 0xB0
    PICC_HALT = 0x50

    # 返回状态
    MI_OK = 0
    MI_NO_TAG_ERR = 1
    MI_ERR = 2

    # RC522寄存器地址
    Reserved00 = 0x00
    CommandReg = 0x01
    CommIEnReg = 0x02
    DivlEnReg = 0x03
    CommIrqReg = 0x04
    DivIrqReg = 0x05
    ErrorReg = 0x06
    Status1Reg = 0x07
    Status2Reg = 0x08
    FIFODataReg = 0x09
    FIFOLevelReg = 0x0A
    WaterLevelReg = 0x0B
    ControlReg = 0x0C
    BitFramingReg = 0x0D
    CollReg = 0x0E
    Reserved01 = 0x0F

    Reserved10 = 0x10
    ModeReg = 0x11
    TxModeReg = 0x12
    RxModeReg = 0x13
    TxControlReg = 0x14
    TxAutoReg = 0x15
    TxSelReg = 0x16
    RxSelReg = 0x17
    RxThresholdReg = 0x18
    DemodReg = 0x19
    Reserved11 = 0x1A
    Reserved12 = 0x1B
    MifareReg = 0x1C
    Reserved13 = 0x1D
    Reserved14 = 0x1E
    SerialSpeedReg = 0x1F

    Reserved20 = 0x20
    CRCResultRegM = 0x21
    CRCResultRegL = 0x22
    Reserved21 = 0x23
    ModWidthReg = 0x24
    Reserved22 = 0x25
    RFCfgReg = 0x26
    GsNReg = 0x27
    CWGsPReg = 0x28
    ModGsPReg = 0x29
    TModeReg = 0x2A
    TPrescalerReg = 0x2B
    TReloadRegH = 0x2C
    TReloadRegL = 0x2D
    TCounterValueRegH = 0x2E
    TCounterValueRegL = 0x2F

    Reserved30 = 0x30
    TestSel1Reg = 0x31
    TestSel2Reg = 0x32
    TestPinEnReg = 0x33
    TestPinValueReg = 0x34
    TestBusReg = 0x35
    AutoTestReg = 0x36
    VersionReg = 0x37
    AnalogTestReg = 0x38
    TestDAC1Reg = 0x39
    TestDAC2Reg = 0x3A
    TestADCReg = 0x3B
    Reserved31 = 0x3C
    Reserved32 = 0x3D
    Reserved33 = 0x3E
    Reserved34 = 0x3F

    def __init__(self, dev='/dev/spidev0.0', speed=1000000):
        self.__spiDev = SPI(device=dev, speed=speed)
        self.MFRC522_Init()

    def __debug(self, s):
        # print (s)
        pass

    # 复位读卡器
    def MFRC522_Reset(self):
        self.Write_MFRC522(self.CommandReg, self.PCD_RESETPHASE)

    # 向读卡器中写数据
    def Write_MFRC522(self, addr, val):
        self.__spiDev.transfer(((addr << 1) & 0x7E, val))

    # 读取读卡器中的数据
    def Read_MFRC522(self, addr):
        val = self.__spiDev.transfer((((addr << 1) & 0x7E) | 0x80, 0))
        return val[1]

    # 设置位掩码
    def SetBitMask(self, reg, mask):
        tmp = self.Read_MFRC522(reg)
        self.Write_MFRC522(reg, tmp | mask)

    # 清除位掩码
    def ClearBitMask(self, reg, mask):
        tmp = self.Read_MFRC522(reg)
        self.Write_MFRC522(reg, tmp & (~mask))

    # 打开天线
    def AntennaOn(self):
        temp = self.Read_MFRC522(self.TxControlReg)
        if ~(temp & 0x03):
            self.SetBitMask(self.TxControlReg, 0x03)

    # 关闭天线
    def AntennaOff(self):
        self.ClearBitMask(self.TxControlReg, 0x03)

    def MFRC522_ToCard(self, command, sendData):
        backData = []
        backLen = 0
        status = self.MI_ERR
        irqEn = 0x00
        waitIRq = 0x00
        n = 0
        i = 0

        if command == self.PCD_AUTHENT:
            irqEn = 0x12
            waitIRq = 0x10
        if command == self.PCD_TRANSCEIVE:
            irqEn = 0x77
            waitIRq = 0x30

        self.Write_MFRC522(self.CommIEnReg, irqEn | 0x80)
        self.ClearBitMask(self.CommIrqReg, 0x80)
        self.SetBitMask(self.FIFOLevelReg, 0x80)

        self.Write_MFRC522(self.CommandReg, self.PCD_IDLE)

        while i < len(sendData):
            self.Write_MFRC522(self.FIFODataReg, sendData[i])
            i += 1

        self.Write_MFRC522(self.CommandReg, command)

        if command == self.PCD_TRANSCEIVE:
            self.SetBitMask(self.BitFramingReg, 0x80)

        i = 2000
        while True:
            n = self.Read_MFRC522(self.CommIrqReg)
            i -= 1
            if ~((i != 0) and ~(n & 0x01) and ~(n & waitIRq)):
                break

        self.ClearBitMask(self.BitFramingReg, 0x80)

        if i != 0:
            if (self.Read_MFRC522(self.ErrorReg) & 0x1B) == 0x00:
                status = self.MI_OK
                if n & irqEn & 0x01:
                    status = self.MI_NO_TAG_ERR
                if command == self.PCD_TRANSCEIVE:
                    n = self.Read_MFRC522(self.FIFOLevelReg)
                    lastBits = self.Read_MFRC522(self.ControlReg) & 0x07
                    if lastBits != 0:
                        backLen = (n - 1) * 8 + lastBits
                    else:
                        backLen = n * 8
                    if n == 0:
                        n = 1
                    if n > self.MAX_LEN:
                        n = self.MAX_LEN
                    i = 0
                    while i < n:
                        backData.append(self.Read_MFRC522(self.FIFODataReg))
                        i += 1
            else:
                status = self.MI_ERR

        return status, backData, backLen

    def MFRC522_Request(self, reqMode):
        TagType = []
        self.Write_MFRC522(self.BitFramingReg, 0x07)
        TagType.append(reqMode)
        (status, backData, backBits) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, TagType)
        if (status != self.MI_OK) | (backBits != 0x10):
            status = self.MI_ERR
        return status, backBits

    def MFRC522_Anticoll(self):
        serNumCheck = 0
        serNum = []
        self.Write_MFRC522(self.BitFramingReg, 0x00)
        serNum.append(self.PICC_ANTICOLL)
        serNum.append(0x20)
        (status, backData, backBits) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, serNum)
        if status == self.MI_OK:
            i = 0
            if len(backData) == 5:
                while i < 4:
                    serNumCheck = serNumCheck ^ backData[i]
                    i += 1
                if serNumCheck != backData[i]:
                    status = self.MI_ERR
            else:
                status = self.MI_ERR

        return status, backData

    # 计算 CRC 值
    def CalulateCRC(self, pIndata):
        self.ClearBitMask(self.DivIrqReg, 0x04)
        self.SetBitMask(self.FIFOLevelReg, 0x80)
        i = 0
        while i < len(pIndata):
            self.Write_MFRC522(self.FIFODataReg, pIndata[i])
            i += 1
        self.Write_MFRC522(self.CommandReg, self.PCD_CALCCRC)
        i = 0xFF
        while True:
            n = self.Read_MFRC522(self.DivIrqReg)
            i -= 1
            if not ((i != 0) and not (n & 0x04)):
                break
        pOutData = [self.Read_MFRC522(self.CRCResultRegL), self.Read_MFRC522(self.CRCResultRegM)]
        return pOutData

    # 选择标签
    def MFRC522_SelectTag(self, serNum):
        buf = [self.PICC_SElECTTAG, 0x70]
        i = 0
        while i < 5:
            buf.append(serNum[i])
            i += 1
        pOut = self.CalulateCRC(buf)
        buf.append(pOut[0])
        buf.append(pOut[1])
        (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buf)
        if (status == self.MI_OK) and (backLen == 0x18):
            self.__debug("Size: " + str(backData[0]))
            return backData[0]
        else:
            return 0

    def MFRC522_Auth(self, authMode, BlockAddr, Sectorkey, serNum):
        # First byte should be the authMode (A or B)
        # Second byte is the trailerBlock (usually 7)
        buff = [authMode, BlockAddr]
        # Now we need to append the authKey which usually is 6 bytes of 0xFF
        i = 0
        while i < len(Sectorkey):
            buff.append(Sectorkey[i])
            i += 1
        i = 0
        # Next we append the first 4 bytes of the UID
        while i < 4:
            buff.append(serNum[i])
            i += 1
        # Now we start the authentication itself
        (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_AUTHENT, buff)
        # 检查是否发生错误
        if not (status == self.MI_OK):
            self.__debug("AUTH ERROR!!")
        if not (self.Read_MFRC522(self.Status2Reg) & 0x08) != 0:
            self.__debug("AUTH ERROR(status2reg & 0x08) != 0")

        # 返回状态码
        return status

    def MFRC522_StopCrypto1(self):
        self.ClearBitMask(self.Status2Reg, 0x08)

    # 读卡
    def MFRC522_Read(self, blockAddr):
        recvData = [self.PICC_READ, blockAddr]
        pOut = self.CalulateCRC(recvData)
        recvData.append(pOut[0])
        recvData.append(pOut[1])
        status, backData, backLen = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, recvData)
        return status, backData, backLen

    # 写卡
    def MFRC522_Write(self, blockAddr, writeData):
        buff = [self.PICC_WRITE, blockAddr]
        crc = self.CalulateCRC(buff)
        buff.append(crc[0])
        buff.append(crc[1])
        status, backData, backLen = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buff)
        if status == self.MI_OK and backLen != 4 and (backData[0] & 0x0F) != 0x0A:
            status = self.MI_ERR
        self.__debug(str(backLen) + " backdata &0x0F == 0x0A " + str(backData[0] & 0x0F))
        if status == self.MI_OK:
            i = 0
            buf = []
            while i < 16:
                buf.append(writeData[i])
                i += 1
            crc = self.CalulateCRC(buf)
            buf.append(crc[0])
            buf.append(crc[1])
            status, backData, backLen = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buf)
            if status == self.MI_OK and backLen != 4 and (backData[0] & 0x0F) != 0x0A:
                self.__debug("Error while writing")
            if status == self.MI_OK:
                self.__debug("Data written")

    # 导出1K字节, 64个扇区
    def MFRC522_DumpClassic1K(self, key, uid):
        i = 0
        while i < 64:
            status = self.MFRC522_Auth(self.PICC_AUTHENT1A, i, key, uid)
            # 检查是否认证成功
            if status == self.MI_OK:
                self.MFRC522_Read(i)
            else:
                self.__debug("Authentication error")
            i += 1

    def MFRC522_Init(self):
        self.MFRC522_Reset()
        self.Write_MFRC522(self.TModeReg, 0x8D)
        self.Write_MFRC522(self.TPrescalerReg, 0x3E)
        self.Write_MFRC522(self.TReloadRegL, 30)
        self.Write_MFRC522(self.TReloadRegH, 0)
        self.Write_MFRC522(self.TxAutoReg, 0x40)
        self.Write_MFRC522(self.ModeReg, 0x3D)
        self.AntennaOn()