Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to write single byte #7

Open
Ricky1966 opened this issue Jul 17, 2023 · 11 comments
Open

How to write single byte #7

Ricky1966 opened this issue Jul 17, 2023 · 11 comments

Comments

@Ricky1966
Copy link

Hi, I put this post in the issuu, but actually it's not a real problem. I'm implementing a couple of new functions to your library the first one involves reading single, byte given the specific number of bytes to read. I need this because to read a multi-record tag, I need to know certain bytes. But now I find it difficult to write a certain byte.
The function :
def mifare_classic_read_block(self, block_number):
expects that you pass it the block and a 4-byte data array. I need to write the byte directly, is this possible?
I attach the lines of code that I wrote to be able to read the single byte
`

def ntag2xx_read_byte(self, byte_number):

    """Read a block of data from the card.  Block number should be the block
    to read.  If the block is successfully read a bytearray of length 16 with
    data starting at the specified block will be returned.  If the block is
    not read then None will be returned.
    position = (byte_number-4*(byte_number//4))-1
    block_number = byte_number//4
    """

    posiyion = (byte_number-4*(byte_number//4))
    block_number = (byte_number//4)+4
    return self.mifare_classic_read_block(block_number)[position:1+position]  # only 1 bytes per page``

`
As you can see, I pass the position of the byte and the function returns the value.
This feature allows me to read a single byte memory dump, which makes things easier for me when parsing the NDEF Message.
From my research, an NDEF Message begins with 0x03h (should be a byte indicating the ISO 14333-3A encoding) the second byte indicates the length of the message, the actual message starts from the third byte.
The message is divided into records and records have a header and a payload.
The header is made up of N bytes, it depends on 8 bits which act as flags.
I made a couple of functions to establish the value of the header and then its subsequent bytes, The payload starts with the byte of the UTF8 or UTF16 encoding type, I have always encountered UTF8 which is 0x02h which are then the next two bytes for the encoding , in most cases, "en" for english.
finally the real payload starts.
in my test, I manage to extrapolate all single records, which I load into a multiple array, where the first value is an array representing the first bytes, in order:

  • record header;
  • byte 0x01h should be the number of successive byte(s) for the real length of the payload;
  • payload length ;
  • payload type, example 0x54h (T = Text);
    -this byte 0x02h is the UTF8 encoding byte with two bytes for the language;
  • first byte language;
  • second byte language.
    After this list, I put the payload as the second value in the list, and so on until the end of the records.
    Now let's get to the point, if you help me write a function in NFC_PN532.py
    that allows me to directly write the single byte in the memory location that interests me, I would be able to change the value of the payload. always staying within its length. This can be done knowing that the value of the record header contains the length of the payload.
    Very important, the length of the payload starts from the UTF encoding byte, so a dump of a part of the NDEF message like this :
    03 ... 91 01 06 54 02 65 6e 61 61 61
    it means :
  • 03 ISO14333-3A
  • ... length of message ;
  • 91 that the records are more than 1;
  • 01 next byte is payload length;
  • 06 payload length 6 bytes;
  • 54 the payload is of text type;
  • UTF8 encoded (it's also the beginning of the payload);
  • e ;
  • n ;
  • a;
  • a;
  • a.

So, if I could write to the 10th byte, say 62, the payload would be UTF8 "en" baa instead of UTF8 "en" aaa
Thanks for your attention and I hope you can/want to help me

@Carglglz
Copy link
Owner

Carglglz commented Jul 17, 2023

@Ricky1966 I think you may want to check the develop branch at https://github.com/Carglglz/NFC_PN532_SPI/tree/develop,
nfctag/utag.py is what you may looking for 👀 or at least it can help . I'm not sure exactly what you are trying to do but I guess reading the NDEF record, modify the payload and rewrite it in the tag should be possible...

@Ricky1966
Copy link
Author

Hi, tks.
What I'm looking for is to write only 1 bytes for block and not all entire 4 bytes.
If you look inside Adafruit library, there are a couples of functions, called ntag2xx_write_block and ntag2xx_read_block.
I've create a second function called ntag2xx_read_byte, who return me a single byte I need. It work fine for my porpuse, but, for rewrite a single byte on EEPROM of the TAG, I have to ways, the first is to rewrite entire block (3 bytes remain the same, 1 byte changes) and this is the more easy way. Other way is to rewrite only one byte, but I don't know how...this is my problem!

@Carglglz
Copy link
Owner

I have to ways, the first is to rewrite entire block (3 bytes remain the same, 1 byte changes) and this is the more easy way. Other way is to rewrite only one byte, but I don't know how...this is my problem!

Well in that case I don't know if writing a single byte is possible, I think

rewrite entire block (3 bytes remain the same, 1 byte changes)

is the only way, but if you find out let me know 👍🏼

@Ricky1966
Copy link
Author

Rewrite the block is easy, for now I keep this way. But for change only one record in a NDEF Message with more than one record, is a little bit borring way. As you know the 5th block 0x04 have 4 bytes the first in my case is everytime 0x03, somewhere I've read this bytes meens start of NDEF Message and ISO 14443/3A, this is right? The second is the lenght of Message, without first and second bytes and the end 0xfe.Also this is right?

@Carglglz
Copy link
Owner

Carglglz commented Jul 17, 2023

somewhere I've read this bytes meens start of NDEF Message and ISO 14443/3A, this is right? The second is the lenght of Message, without first and second bytes and the end 0xfe.Also this is right?

I've just followed https://learn.adafruit.com/adafruit-pn532-rfid-nfc/ndef which I guess is what you're looking for

@Ricky1966
Copy link
Author

I've already read that link, but is not explained how are setting the first bytes of ndef message.

@Ricky1966
Copy link
Author

In the Adafruit link you gave me, some things I found on the net are not explained.
For example sector 03 OTP0-3 is the sector where you find what kind of tag you are reading. E1 10 3E 00 is an NTag215. I found these data on the net. if instead of 3E you have another value, which I can't remember now, it's NTag213 or 216. They are constants E1 10.
I would like to attach a zip file in which I have put some images. in one there are the two tags that I used to test, the one with the paper is TagA, as you can see they are different.
The other images are the dump of the memories of TagA, that of paper, of TagB in one image it is formatted, sector 4 is 03 00 FE and in the last two I wrote two records (hello world with spaces).
If you notice, they always start with 03, this byte should be the one that identifies that the next message is an ISO 14443/3A NDEF. Then the next byte is the total length of the message excluding 03 and the length byte. Furthermore, the byte FE closing the message is excluded.
I haven't tried using the ntag2xx_write_block function directly, but from what I understand it works, it overwrites 4 bytes in the indicated block. This isn't very practical, because if you notice, the records can be across multiple blocks.
This is why, through the analysis of the records, I understood, like you, that an NDEF message is made in the following structure:

  • after 4 unwritable sectors, there are 2 bytes for ISO coding and Message length;
  • 4/7 bytes for the header of the record (in accord with 1 or 4 bytes for record length);
  • 3 bytes are 02 should be UTF8 65 and 6E "en" for English;
  • the remaining bytes are the payload.
    The byte that includes the length of the payload, the third of the header, also including the 3 bytes of UTF8 and 'en'.
    In your work I saw that you deal with the byte header, so you can know how many bytes are header and how many payloads.
    As you can see in my function to work on single byte reading, the thing is quite simple. If ai were able to write a function for writing a single byte then modifying the payload would be easier, provided that the length is unchanged, but at that point it is enough to insert spaces.
    We could also create a function to completely rewrite the message. It's not complicated. In my work, which I can send you if you want, I create a list, containing a list for the header + the 3 bytes of the UTF encoding, and then a string with the real payload, for example "hello ".
    I'm not that expert in Python, so I offer you my code and suggestions, so as to make a very complete library.
    I thought of doing it like this, if you modify a record, in length and in string value, you have to modify:
  • the second byte of the 5th block because the message may be longer or shorter than before;
  • the byte which indicates the length of the record;
  • the part of the string representing the text value of the record.
    All of this, of course, only applies to text records 0x54h because I haven't investigated yet for URLs 0x55 or Sp 0x56.
    P.S.: I don't know how to send the zip and my files, this is my email address, if you write me here, I'll send you the files riccardo.bramati@gmail.com

@Ricky1966
Copy link
Author

TagB_2
TagB_1
Tag_Empty
TagA_2
TagA_1
TagA_TagB

@Carglglz
Copy link
Owner

I haven't tried using the ntag2xx_write_block function directly, but from what I understand it works, it overwrites 4 bytes in the indicated block. This isn't very practical, because if you notice, the records can be across multiple blocks.

The thing is it doesn't look like writing less than a block is possible, i.e. 4. bytes (in case of ntags) is the minimum amount but if you find out that you can write a single byte (maybe in pn532 data sheet?) you could send a pull request and I may be able to test it 👍🏼

@Ricky1966
Copy link
Author

I'll try to write to NXP directly. Maybe they could help me for understand if is possible, if I don't wrong the PN532 chip comes from they.

@Ricky1966
Copy link
Author

If you want my code, I'll gladly give it to you, write me at the email I put above and I'll send it to you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants