Van Duoc
Van Duoc

Reputation: 65

Get mifare card serial number is incorrect

With the card reader I'm using, the protocol to retrieve the serial number of a MIFARE card is as follows:

Mifare anticollision, 0x0202:
Function card anticollision
Format       aa bb 05 00 00 00 02 02 00
Response  aa bb 0a 00 52 51 02 02 00 46 ff a6 b8 a4

Where 46 ff a6 b8 is the card serial number in the above response.

I implement this protocol in C# as follows:

private SerialPort _serialPort = new SerialPort();
private string _receivedData = null;

public MifareCardReader(string comPort, int baudRate)
{
    _serialPort = new SerialPort();
    _serialPort.PortName = comPort;
    _serialPort.BaudRate = baudRate;
    _serialPort.DataBits = 8;
    _serialPort.Parity = Parity.None;
    _serialPort.StopBits = StopBits.One;
    _serialPort.Handshake = Handshake.None;
    _serialPort.Open();   

    // Add event
    _serialPort.DataReceived += SerialPort_DataReceived;     
}

public string MifareAnticollision()
{
    if (_serialPort != null && _serialPort.IsOpen)
    {
        string message = "AABB050000000202000D";
        byte[] data = StringToByteArray(message);
        _serialPort.Write(data, 0, data.Length);
    }
}

private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    _receivedData += _serialPort.ReadExisting();
    byte[] data = Encoding.ASCII.GetBytes(receivedData);
    if (data.Length >= 9)
    {
        if (data[8] == 0) // OK
        {
            // Response data is complete
            if (data.Length == 14)
            {
                StringBuilder hex = new StringBuilder(8);
                hex.AppendFormat("{0:X2}", data[9]);
                hex.AppendFormat("{0:X2}", data[10]);
                hex.AppendFormat("{0:X2}", data[11]);
                hex.AppendFormat("{0:X2}", data[12]);

                string cardID = hex.ToString();
                _receivedData = string.Empty;
            }
        }
        else // fail
        {
            _receivedData = string.Empty;
        }
    }
}

I tested this with 3 different MIFARE cards, however, the output is not what I expected:

What do I need to change to get the correct output?

Upvotes: 0

Views: 1738

Answers (1)

Michael Roland
Michael Roland

Reputation: 40831

The problem that you are experiencing seems to be that bytes with a value above 0x7F replaced with 0x3F (the question mark ("?") character). I.e. only 7-bit values show correctly and values with the 8th bit set are turned into "?" (0x3F). E.g. for card 1, 974682D6 is "received" as 3F463F3F, because 0x97, 0x82, and 0xD6 have their 8th bit set.

The source for this problem is that you are using the ReadExisting() method to read a string value from the serial port. By default, the ReadExisting() reads bytes from the serial port, translates them using the ASCII encoding (System.Text.ASCIIEncoding), and returns the resulting string. You then take that string and convert it back to a byte array (again using the ASCII encoding).

The problematic steps are the conversions using System.Text.ASCIIEncoding/Encoding.ASCII. The documentation says:

Because ASCII is a 7-bit encoding, ASCII characters are limited to the lowest 128 Unicode characters, from U+0000 to U+007F. [...] characters outside that range are replaced with a question mark (?) before the encoding operation is performed.

Consequently, you should read the bytes directly into a byte array using the Read() or ReadByte() methods. E.g. with

byte[] buffer = new byte[_serialPort.ReadBufferSize];
int bytesRead = _serialPort.Read(buffer, 0, buffer.Length);

Upvotes: 1

Related Questions