libfreefare/libfreefare/felica.c
Romain Tartière 94bf7059b4 Remove copyright comments.
The COPYRIGHT file is already here and is more complete, while the VCS
hold accurate information about contributors and conibution date.
2017-06-29 09:29:15 +02:00

170 lines
3.6 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* This implementation was written based on information provided by the
* following documents:
*
* FeliCa Lite User's Manual
* Version 1.2
* No. M624-E01-20
*/
#if defined(HAVE_CONFIG_H)
# include "config.h"
#endif
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#ifdef WITH_DEBUG
# include <libutil.h>
#endif
#include <freefare.h>
#include "freefare_internal.h"
#define MAX_BLOCK_COUNT 8
inline static
ssize_t felica_transceive(FreefareTag tag, uint8_t *data_in, uint8_t *data_out, size_t data_out_length)
{
DEBUG_XFER(data_in, data_in[0], "===> ");
ssize_t res = nfc_initiator_transceive_bytes(tag->device, data_in, data_in[0], data_out, data_out_length, 0);
DEBUG_XFER(data_out, res, "<=== ");
return res;
}
bool
felica_taste(nfc_device *device, nfc_target target)
{
(void) device;
return target.nm.nmt == NMT_FELICA;
}
FreefareTag
felica_tag_new(nfc_device *device, nfc_target target)
{
FreefareTag tag;
if ((tag = malloc(sizeof(struct felica_tag)))) {
tag->type = FELICA;
tag->free_tag = felica_tag_free;
tag->device = device;
tag->info = target;
tag->active = 0;
}
return tag;
}
void
felica_tag_free(FreefareTag tag)
{
free(tag);
}
ssize_t
felica_read_ex(FreefareTag tag, uint16_t service, uint8_t block_count, uint8_t blocks[], uint8_t *data, size_t length)
{
assert(block_count <= MAX_BLOCK_COUNT);
assert(length == 16 * block_count);
DEBUG_FUNCTION();
uint8_t cmd[1 + 1 + 8 + 1 + 2 + 1 + 2 * MAX_BLOCK_COUNT] = {
0x00, /* Length */
0x06,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01,
0x00, 0x00, /* Service */
0x00,
/* Block ... */
};
uint8_t res[100];
cmd[0] = 14 + 2 * block_count;
memcpy(cmd + 2, tag->info.nti.nfi.abtId, 8);
cmd[11] = service;
cmd[12] = service >> 8;
cmd[13] = block_count;
for (int i = 0; i < block_count; i++) {
cmd[14 + 2 * i] = 0x80;
cmd[14 + 2 * i + 1] = blocks[i];
}
int cnt = felica_transceive(tag, cmd, res, sizeof(res));
if (cnt != 1 + 1 + 8 + 1 + 1 + 1 + 16 * block_count) {
return -1;
}
size_t len = MIN(res[12] * 16, length);
memcpy(data, res + 13, len);
return len;
}
ssize_t
felica_read(FreefareTag tag, uint16_t service, uint8_t block, uint8_t *data, size_t length)
{
uint8_t blocks[] = {
block
};
return felica_read_ex(tag, service, 1, blocks, data, length);
}
ssize_t
felica_write_ex(FreefareTag tag, uint16_t service, uint8_t block_count, uint8_t blocks[], uint8_t *data, size_t length)
{
DEBUG_FUNCTION();
assert(block_count <= MAX_BLOCK_COUNT);
assert(length == 16 * block_count);
uint8_t cmd[1 + 1 + 8 + 1 + 2 + 1 + 2 + 16 * MAX_BLOCK_COUNT] = {
0x00, /* Length */
0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01,
0x00, 0x00, /* Service */
0x00,
/* Block ... */
/* n * 16 */
};
uint8_t res[12];
cmd[0] = 1 + 1 + 8 + 1 + 2 * 1 + 1 + 2 * 1 + 16 * block_count;
memcpy(cmd + 2, tag->info.nti.nfi.abtId, 8);
cmd[11] = service;
cmd[12] = service >> 8;
cmd[13] = block_count;
for (int i = 0; i < block_count; i++) {
cmd[14 + 2 * i] = 0x80;
cmd[14 + 2 * i + 1] = blocks[i];
}
memcpy(cmd + 14 + 2 * block_count, data, length);
ssize_t cnt = felica_transceive(tag, cmd, res, sizeof(res));
if (cnt != sizeof(res))
return -1;
return res[10] == 0 ? 0 : -1;
}
ssize_t
felica_write(FreefareTag tag, uint16_t service, uint8_t block, uint8_t *data, size_t length)
{
uint8_t blocks[] = {
block
};
return felica_write_ex(tag, service, 1, blocks, data, length);
}