diff options
-rw-r--r-- | command.c | 18 | ||||
-rw-r--r-- | nfcommander.h | 10 | ||||
-rw-r--r-- | reader.c | 43 | ||||
-rw-r--r-- | reader.h | 1 | ||||
-rw-r--r-- | reader_yhy.c | 56 |
5 files changed, 117 insertions, 11 deletions
@@ -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); @@ -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; @@ -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; } |