#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;
} __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;
};
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;
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)
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);