summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcbdev <cb@cbcdn.com>2023-07-09 01:16:37 +0200
committercbdev <cb@cbcdn.com>2023-07-09 01:16:37 +0200
commit2712c7bee486ec889434d30889364ce5e89958ad (patch)
tree4640961e9957a4f1715ce2f15df7a2a37c134dd0
parent24c97f5b1fe1b666a3c53e8d36b0bea0ede307e0 (diff)
downloadnfcommander-2712c7bee486ec889434d30889364ce5e89958ad.tar.gz
nfcommander-2712c7bee486ec889434d30889364ce5e89958ad.tar.bz2
nfcommander-2712c7bee486ec889434d30889364ce5e89958ad.zip
Implement NTAG writing for YHY
-rw-r--r--command.c18
-rw-r--r--nfcommander.h10
-rw-r--r--reader.c43
-rw-r--r--reader.h1
-rw-r--r--reader_yhy.c56
5 files changed, 117 insertions, 11 deletions
diff --git a/command.c b/command.c
index b222997..3dc07e6 100644
--- a/command.c
+++ b/command.c
@@ -11,6 +11,7 @@
#include "nfcommander.h"
#include "command.h"
#include "config.h"
+#include "reader.h"
#define COMMAND_ALIVE 1
#define COMMAND_STOPPED 2
@@ -43,7 +44,15 @@ static int command_scan_input(command_t* cmd, size_t bytes){
cmd->input[cmd->input_head + n] = 0;
//handle line
if(!strncmp((char*) cmd->input, "UPDATE ", strlen("UPDATE "))){
- printf("Update: %s\n", cmd->input + 7);
+ if(cmd->tag && strlen((char*) (cmd->input + 7)) < cmd->tag->dynamic_max){
+ free(cmd->tag->dynamic_data);
+ cmd->tag->dynamic_data = (uint8_t*) strdup((char*) (cmd->input + 7));
+ cmd->tag->dynamic_length = strlen((char*) cmd->tag->dynamic_data);
+ reader_write(cmd->tag, TAG_WRITE_DYNAMIC);
+ }
+ else{
+ printf("Failed to update tag dynamic data\n");
+ }
}
//find beginning of next line
@@ -63,6 +72,9 @@ static int command_scan_input(command_t* cmd, size_t bytes){
//try to find another sentence
return command_scan_input(cmd, bytes - n);
}
+ else if(!isprint(cmd->input[cmd->input_head + n])){
+ cmd->input[cmd->input_head + n] = ' ';
+ }
}
if(cmd->input_head + bytes > INPUT_BUFFER_MAX - 10){
@@ -146,6 +158,7 @@ static int command_spawn(command_t* cmd, char* command_name, char* command_stati
char* handler = config_get("command", "handler");
size_t bytes;
char tag_uid[12] = "";
+ char dynsize[10] = "";
printf("Starting command %s, static %s\n", command_name, command_static);
if(pipe(cmd->iopipe)){
@@ -186,8 +199,9 @@ static int command_spawn(command_t* cmd, char* command_name, char* command_stati
cmd->tag->uid[4], cmd->tag->uid[5],
cmd->tag->uid[6]);
}
+ snprintf(dynsize, sizeof(dynsize), "%ld", cmd->tag->dynamic_max);
setenv("TAG_UID", tag_uid, 1);
- //DYNAMIC_SIZE
+ setenv("MAX_DATA_LENGTH", dynsize, 1);
//run actual command
if(handler){
diff --git a/nfcommander.h b/nfcommander.h
index d380f78..4693a42 100644
--- a/nfcommander.h
+++ b/nfcommander.h
@@ -57,9 +57,13 @@ int core_manage_fd(int fd, int manage, notification_target_t system);
* If this API returns TAG_READ_REQUESTED, a full read is requested and the
* nfc_tag_info_t should be submitted again with the data fully read.
*
- * If this API returns TAG_WRITE_REQUESTED, the nfc_tag_into_t has been filled
- * with valid data pointers and sizes to be writen to the tag
+ * If this API returns TAG_WRITE_FULL, the nfc_tag_into_t has been filled
+ * with valid data pointers and sizes for both the static and dynamic parts
+ * to be written to the tag
+ * In the same fashion, if this API returns TAG_WRITE_DYNAMIC, a write for
+ * only the dynamic section of the tag is requested.
*/
#define TAG_READ_REQUESTED 1
-#define TAG_WRITE_REQUESTED 2
+#define TAG_WRITE_FULL 2
+#define TAG_WRITE_DYNAMIC 4
int reader_tag_present(uint8_t flags, nfc_tag_info_t* tag);
diff --git a/reader.c b/reader.c
index 7bc20e3..2c3a06b 100644
--- a/reader.c
+++ b/reader.c
@@ -12,10 +12,21 @@
#define MAX_PLUGIN_PATH NAME_MAX
#define DEFAULT_POLL_TIMEOUT 1000
+
+/*
+ * Pointers into the tags array are used as stable identifiers
+ * across the different NFCommander modules, so this array should
+ * never be reallocated dynamically.
+ *
+ * As most readers have a limited number of tags they can power in
+ * the field, this should not pose a practical limitation.
+ */
#define MAX_TAGS 5
#define FLAG_PRESENT 16
#define FLAG_ACTIVE 32
+#define FLAG_WRITE_FULL 64
+#define FLAG_WRITE_DYNAMIC 128
static void* reader_module = NULL;
static reader_plugin_handle reader_backend_handle = NULL;
@@ -195,6 +206,15 @@ int reader_tag_present(uint8_t flags, nfc_tag_info_t* tag){
//if data has not yet been fully read, request a full read
return TAG_READ_REQUESTED;
}
+
+ if(tags[n].flags & (FLAG_WRITE_FULL | FLAG_WRITE_DYNAMIC)){
+ flags = tags[n].flags;
+ tags[n].flags &= ~(FLAG_WRITE_FULL | FLAG_WRITE_DYNAMIC);
+ //this is kinda dangerous as we hand the reader backend our pointers
+ memcpy(tag, &(tags[n].info), sizeof(nfc_tag_info_t));
+
+ return (flags & FLAG_WRITE_FULL) ? TAG_WRITE_FULL : TAG_WRITE_DYNAMIC;
+ }
return 0;
}
}
@@ -214,6 +234,23 @@ int reader_tag_present(uint8_t flags, nfc_tag_info_t* tag){
return 0;
}
+int reader_write(nfc_tag_info_t* tag, uint8_t flags){
+ size_t n = 0;
+
+ for(n = 0; n < MAX_TAGS; n++){
+ if(tag == &(tags[n].info)){
+ if(flags & TAG_WRITE_FULL){
+ tags[n].flags |= FLAG_WRITE_FULL;
+ }
+
+ if(flags & TAG_WRITE_DYNAMIC){
+ tags[n].flags |= FLAG_WRITE_DYNAMIC;
+ }
+ }
+ }
+ return 0;
+}
+
int reader_handle(int fd){
uint8_t buffer[1024];
@@ -240,6 +277,8 @@ int reader_handle(int fd){
}
void reader_free(){
+ size_t n = 0;
+
if(reader_module){
dlclose(reader_module);
reader_backend_handle = NULL;
@@ -247,6 +286,10 @@ void reader_free(){
reader_module = NULL;
}
+ for(n = 0; n < MAX_TAGS; n++){
+ tag_info_free(&(tags[n].info));
+ }
+
core_manage_fd(timer_fd, 0, system_reader);
close(timer_fd);
timer_fd = -1;
diff --git a/reader.h b/reader.h
index c1136bb..869b8f3 100644
--- a/reader.h
+++ b/reader.h
@@ -1,3 +1,4 @@
int reader_init();
int reader_handle(int fd);
+int reader_write(nfc_tag_info_t* tag, uint8_t flags);
void reader_free();
diff --git a/reader_yhy.c b/reader_yhy.c
index 5174ef9..192e235 100644
--- a/reader_yhy.c
+++ b/reader_yhy.c
@@ -116,6 +116,7 @@ uint8_t read_ntag(nfc_tag_info_t* tag){
} while(n <= data[13] / 2);
//read dynamic data if present
+ tag->dynamic_max = tag->bytes_available - 8 /*4 byte magic, 4 byte length*/ - tag->static_length;
tag->dynamic_length = data[15] * tag->granularity;
if(tag->dynamic_length){
tag->dynamic_data = calloc(tag->dynamic_length, sizeof(uint8_t));
@@ -142,8 +143,47 @@ uint8_t read_ntag(nfc_tag_info_t* tag){
return FLAG_TAG_DATA_VALID;
}
-void write_ntag(nfc_tag_info_t* tag){
- //TODO
+void write_ntag(nfc_tag_info_t* tag, uint8_t flags){
+ size_t n = 0;
+ size_t static_offset = 6;
+ size_t static_blocks = (tag->static_length / tag->granularity) + ((tag->static_length % tag->granularity) ? 1 : 0);
+ size_t dynamic_offset = static_offset + static_blocks;
+ size_t dynamic_blocks = (tag->dynamic_length / tag->granularity) + ((tag->dynamic_length % tag->granularity) ? 1 : 0);
+ uint8_t data[16] = { 0 };
+
+ if(!static_blocks){
+ printf("Invalid tag data requested for write (static length is %ld), aborting\n", tag->static_length);
+ return;
+ }
+
+ //write directory
+ data[0] = static_offset;
+ data[1] = static_blocks;
+ data[2] = dynamic_offset;
+ data[3] = dynamic_blocks;
+ yhy_sync_write(reader_fd, 5, data);
+
+ if(flags & TAG_WRITE_FULL){
+ //write signature
+ data[0] = 0xCB;
+ data[1] = 'N';
+ data[2] = 'F';
+ data[3] = 'C';
+ yhy_sync_write(reader_fd, 4, data);
+
+ for(n = 0; n < static_blocks; n++){
+ memset(data, 0, sizeof(data));
+ memcpy(data, tag->static_data + n * tag->granularity, MIN(tag->static_length - n * tag->granularity, 4));
+ yhy_sync_write(reader_fd, static_offset + n, data);
+ }
+ }
+
+ //write dynamic data
+ for(n = 0; n < dynamic_blocks; n++){
+ memset(data, 0, sizeof(data));
+ memcpy(data, tag->dynamic_data + n * tag->granularity, MIN(tag->dynamic_length - n * tag->granularity, 4));
+ yhy_sync_write(reader_fd, dynamic_offset + n, data);
+ }
}
uint8_t read_mifare(nfc_tag_info_t* tag){
@@ -151,7 +191,7 @@ uint8_t read_mifare(nfc_tag_info_t* tag){
return FLAG_TAG_LOCKED;
}
-void write_mifare(nfc_tag_info_t* tag){
+void write_mifare(nfc_tag_info_t* tag, uint8_t flags){
//TODO
}
@@ -197,6 +237,7 @@ int scan(){
}
}
+ flags = TAG_WRITE_FULL;
switch(reader_tag_present(0, &card)){
case TAG_READ_REQUESTED:
//read card data
@@ -208,13 +249,16 @@ int scan(){
}
reader_tag_present(flags, &card);
break;
- case TAG_WRITE_REQUESTED:
+ case TAG_WRITE_DYNAMIC:
+ flags = TAG_WRITE_DYNAMIC;
+ //fall through
+ case TAG_WRITE_FULL:
//write card data
if(card.type == tag_ntag){
- write_ntag(&card);
+ write_ntag(&card, flags);
}
else if(card.type == tag_mifare1){
- write_mifare(&card);
+ write_mifare(&card, flags);
}
break;
}