From a0e7f9c64ba888d391d059bf8acd41c07360d8d5 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Thu, 12 May 2011 16:41:24 +0200 Subject: [PATCH] nfctype2: Tag data blocks read Compile tested only, due to missing formatted type 2 tags. --- plugins/nfctype2.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/plugins/nfctype2.c b/plugins/nfctype2.c index a58853a..d989a7a 100644 --- a/plugins/nfctype2.c +++ b/plugins/nfctype2.c @@ -40,8 +40,16 @@ #define CMD_READ 0x30 #define CMD_WRITE 0xA2 + +#define READ_SIZE 16 +#define BLOCK_SIZE 4 + #define META_BLOCK_START 0 #define DATA_BLOCK_START 4 +#define TYPE2_MAGIC 0xe1 + +#define TAG_DATA_LENGTH(cc) ((cc)[2] * 8) +#define TAG_DATA_NFC(cc) ((cc)[0] & TYPE2_MAGIC) static GHashTable *tag_hash; @@ -52,10 +60,12 @@ struct type2_cmd { } __attribute__((packed)); struct type2_tag { + uint32_t adapter_idx; uint32_t target_idx; uint8_t uid[8]; uint8_t lock[4]; uint8_t cc[4]; + uint16_t current_block; uint16_t data_length; uint8_t *data; }; @@ -68,6 +78,67 @@ static void free_tag(gpointer data) g_free(tag); } +static int data_recv(uint8_t *resp, int length, void *data) +{ + struct type2_tag *tag = data; + struct type2_cmd cmd; + uint16_t current_length, length_read; + int read_blocks; + + DBG("%d", length); + + if (length < 0) + return length; + + length_read = length; + current_length = tag->current_block * BLOCK_SIZE; + if (current_length + length > tag->data_length) + length_read = tag->data_length - current_length; + + memcpy(data + current_length, resp, length_read); + + if (current_length + length_read == tag->data_length) { + /* TODO parse tag->data for NDEFS, and notify target.c */ + near_adapter_disconnect(tag->adapter_idx); + tag->current_block = 0; + return 0; + } + + read_blocks = length / BLOCK_SIZE; + tag->current_block += read_blocks; + + cmd.cmd = CMD_READ; + cmd.block = DATA_BLOCK_START + tag->current_block; + + return near_adapter_send(tag->adapter_idx, + (uint8_t *)&cmd, sizeof(cmd), + data_recv, tag); +} + +static int data_read(struct type2_tag *tag) +{ + uint32_t adapter_idx; + struct type2_cmd cmd; + + if (tag->data == NULL) { + g_hash_table_remove(tag_hash, GINT_TO_POINTER(tag->target_idx)); + + return -ENOMEM; + } + + DBG("%d", tag->data_length); + + adapter_idx = tag->adapter_idx; + tag->current_block = 0; + + cmd.cmd = CMD_READ; + cmd.block = DATA_BLOCK_START; + + return near_adapter_send(adapter_idx, + (uint8_t *)&cmd, sizeof(cmd), + data_recv, tag); +} + static int meta_recv(uint8_t *resp, int length, void *data) { int i; @@ -88,7 +159,13 @@ static int meta_recv(uint8_t *resp, int length, void *data) DBG("0x%x 0x%x 0x%x 0x%x", tag->cc[0], tag->cc[1], tag->cc[2], tag->cc[3]); - return 0; + if (tag->data != NULL) + g_free(tag->data); + + tag->data_length = TAG_DATA_LENGTH(tag->cc); + tag->data = g_try_malloc0(tag->data_length); + + return data_read(tag); } static int nfctype2_read_meta(uint32_t adapter_idx, uint32_t target_idx, struct type2_tag *tag) @@ -115,6 +192,7 @@ static int nfctype2_read_tag(uint32_t adapter_idx, if (tag == NULL) return -ENOMEM; + tag->adapter_idx = adapter_idx; tag->target_idx = target_idx; g_hash_table_insert(tag_hash, GINT_TO_POINTER(target_idx), tag); -- 2.7.4