Enhance simulation of ISO15693 devices.

This adds the following things:
- support for reading multiple blocks,
- configurable block size,
- ability to provide a memory image.
This commit is contained in:
Markus Walter 2022-08-26 09:29:15 +02:00
commit eef1ce9c33
5 changed files with 113 additions and 22 deletions

View file

@ -2100,7 +2100,7 @@ void Iso15693InitTag(void) {
// Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands
// all demodulation performed in arm rather than host. - greg
void SimTagIso15693(uint8_t *uid) {
void SimTagIso15693(uint8_t *uid, uint8_t block_size, int image_length, uint8_t *image) {
// free eventually allocated BigBuf memory
BigBuf_free_keep_EM();
@ -2109,12 +2109,14 @@ void SimTagIso15693(uint8_t *uid) {
LED_A_ON();
Dbprintf("ISO-15963 Simulating uid: %02X%02X%02X%02X%02X%02X%02X%02X", uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7]);
if (image_length == -1) {
Dbprintf("ISO-15963 Simulating uid: %02X%02X%02X%02X%02X%02X%02X%02X block size %d with no image", uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7], block_size);
} else {
Dbprintf("ISO-15963 Simulating uid: %02X%02X%02X%02X%02X%02X%02X%02X block size %d with 0x%X bytes image", uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7], block_size, image_length);
}
LED_C_ON();
enum { NO_FIELD, IDLE, ACTIVATED, SELECTED, HALTED } chip_state = NO_FIELD;
bool button_pressed = false;
@ -2207,8 +2209,14 @@ void SimTagIso15693(uint8_t *uid) {
resp_sysinfo[10] = 0; // DSFID
resp_sysinfo[11] = 0; // AFI
resp_sysinfo[12] = 0x1B; // Memory size.
resp_sysinfo[13] = 0x03; // Memory size.
// Memory size.
if (image_length == -1) {
// use sensible default value if no image is provided
resp_sysinfo[12] = 0x1F;
} else {
resp_sysinfo[12] = image_length / block_size;
}
resp_sysinfo[13] = block_size - 1; // Memory size.
resp_sysinfo[14] = 0x01; // IC reference.
// CRC
@ -2221,28 +2229,71 @@ void SimTagIso15693(uint8_t *uid) {
LogTrace_ISO15693(resp_sysinfo, CMD_SYSINFO_RESP, response_time * 32, (response_time * 32) + (ts->max * 32 * 64), NULL, false);
}
// READ_BLOCK
if ((cmd[1] == ISO15693_READBLOCK)) {
// READ_BLOCK and READ_MULTI_BLOCK
if ((cmd[1] == ISO15693_READBLOCK) || (cmd[1] == ISO15693_READ_MULTI_BLOCK)) {
bool slow = !(cmd[0] & ISO15_REQ_DATARATE_HIGH);
bool option = cmd[0] & ISO15_REQ_OPTION;
uint32_t response_time = reader_eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM;
// Build READ_BLOCK response
uint8_t resp_readblock[CMD_READBLOCK_RESP] = {0};
uint8_t block_idx = 0;
uint8_t block_count = 1;
if (cmd[1] == ISO15693_READBLOCK) {
if (cmd_len == 13) {
// addressed mode
block_idx= cmd[10];
} else if (cmd_len == 5) {
// non-addressed mode
block_idx = cmd[2];
}
} else if (cmd[1] == ISO15693_READ_MULTI_BLOCK) {
if (cmd_len == 14) {
// addressed mode
block_idx= cmd[10];
block_count= cmd[11] + 1;
} else if (cmd_len == 6) {
// non-addressed mode
block_idx = cmd[2];
block_count = cmd[3] + 1;
}
}
resp_readblock[0] = 0; // Response flags.
resp_readblock[1] = 0; // Block data.
resp_readblock[2] = 0; // Block data.
resp_readblock[3] = 0; // Block data.
resp_readblock[4] = 0; // Block data.
// Build READ_(MULTI_)BLOCK response
int response_length = 3 + block_size * block_count;
int security_offset = 0;
if (option) {
response_length += block_count;
security_offset = 1;
}
uint8_t resp_readblock[response_length];
for (int i = 0; i < response_length; i++) {
resp_readblock[i] = 0;
}
resp_readblock[0] = 0; // Response flags
for (int j = 0; j < block_count; j++) {
// where to put the data of the current block
int work_offset = 1 + j * (block_size + security_offset);
if (option) {
resp_readblock[work_offset] = 0; // Security status
}
for (int i = 0; i < block_size; i++) {
// Block data
if (block_size * (block_idx + j + 1) <= image_length) {
resp_readblock[work_offset + security_offset + i] = image[block_size * (block_idx + j) + i];
} else {
resp_readblock[work_offset + security_offset + i] = 0;
}
}
}
// CRC
AddCrc15(resp_readblock, 5);
CodeIso15693AsTag(resp_readblock, CMD_READBLOCK_RESP);
AddCrc15(resp_readblock, response_length - 2);
CodeIso15693AsTag(resp_readblock, response_length);
tosend_t *ts = get_tosend();
TransmitTo15693Reader(ts->buf, ts->max, &response_time, 0, slow);
LogTrace_ISO15693(resp_readblock, CMD_READBLOCK_RESP, response_time * 32, (response_time * 32) + (ts->max * 32 * 64), NULL, false);
LogTrace_ISO15693(resp_readblock, response_length, response_time * 32, (response_time * 32) + (ts->max * 32 * 64), NULL, false);
}
}