mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-12 15:38:36 -07:00
218 lines
7.0 KiB
C
218 lines
7.0 KiB
C
#include "picopass_poller_i.h"
|
|
|
|
#include <nfc/helpers/iso14443_crc.h>
|
|
|
|
#define PICOPASS_POLLER_FWT_FC (100000)
|
|
|
|
#define TAG "Picopass"
|
|
|
|
static PicopassError picopass_poller_process_error(NfcError error) {
|
|
PicopassError ret = PicopassErrorNone;
|
|
|
|
switch(error) {
|
|
case NfcErrorNone:
|
|
ret = PicopassErrorNone;
|
|
break;
|
|
|
|
default:
|
|
ret = PicopassErrorTimeout;
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static PicopassError picopass_poller_send_frame(
|
|
PicopassPoller* instance,
|
|
BitBuffer* tx_buffer,
|
|
BitBuffer* rx_buffer,
|
|
uint32_t fwt_fc) {
|
|
PicopassError ret = PicopassErrorNone;
|
|
|
|
do {
|
|
NfcError error = nfc_poller_trx(instance->nfc, tx_buffer, rx_buffer, fwt_fc);
|
|
if(error != NfcErrorNone) {
|
|
ret = picopass_poller_process_error(error);
|
|
break;
|
|
}
|
|
if(!iso13239_crc_check(Iso13239CrcTypePicopass, rx_buffer)) {
|
|
ret = PicopassErrorIncorrectCrc;
|
|
break;
|
|
}
|
|
iso13239_crc_trim(instance->rx_buffer);
|
|
} while(false);
|
|
|
|
return ret;
|
|
}
|
|
|
|
PicopassError picopass_poller_actall(PicopassPoller* instance) {
|
|
PicopassError ret = PicopassErrorNone;
|
|
|
|
bit_buffer_reset(instance->tx_buffer);
|
|
bit_buffer_append_byte(instance->tx_buffer, RFAL_PICOPASS_CMD_ACTALL);
|
|
|
|
NfcError error = nfc_poller_trx(
|
|
instance->nfc, instance->tx_buffer, instance->rx_buffer, PICOPASS_POLLER_FWT_FC);
|
|
if(error != NfcErrorIncompleteFrame) {
|
|
ret = picopass_poller_process_error(error);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
PicopassError picopass_poller_identify(
|
|
PicopassPoller* instance,
|
|
PicopassColResSerialNum* col_res_serial_num) {
|
|
PicopassError ret = PicopassErrorNone;
|
|
|
|
do {
|
|
bit_buffer_reset(instance->tx_buffer);
|
|
bit_buffer_append_byte(instance->tx_buffer, RFAL_PICOPASS_CMD_READ_OR_IDENTIFY);
|
|
ret = picopass_poller_send_frame(
|
|
instance, instance->tx_buffer, instance->rx_buffer, PICOPASS_POLLER_FWT_FC);
|
|
if(ret != PicopassErrorNone) break;
|
|
if(bit_buffer_get_size_bytes(instance->rx_buffer) != sizeof(PicopassColResSerialNum)) {
|
|
ret = PicopassErrorProtocol;
|
|
break;
|
|
}
|
|
bit_buffer_write_bytes(
|
|
instance->rx_buffer, col_res_serial_num->data, sizeof(PicopassColResSerialNum));
|
|
} while(false);
|
|
|
|
return ret;
|
|
}
|
|
|
|
PicopassError picopass_poller_select(
|
|
PicopassPoller* instance,
|
|
PicopassColResSerialNum* col_res_serial_num,
|
|
PicopassSerialNum* serial_num) {
|
|
PicopassError ret = PicopassErrorNone;
|
|
|
|
do {
|
|
bit_buffer_reset(instance->tx_buffer);
|
|
bit_buffer_append_byte(instance->tx_buffer, RFAL_PICOPASS_CMD_SELECT);
|
|
bit_buffer_append_bytes(
|
|
instance->tx_buffer, col_res_serial_num->data, sizeof(PicopassColResSerialNum));
|
|
ret = picopass_poller_send_frame(
|
|
instance, instance->tx_buffer, instance->rx_buffer, PICOPASS_POLLER_FWT_FC);
|
|
if(ret != PicopassErrorNone) break;
|
|
if(bit_buffer_get_size_bytes(instance->rx_buffer) != sizeof(PicopassSerialNum)) {
|
|
ret = PicopassErrorProtocol;
|
|
break;
|
|
}
|
|
bit_buffer_write_bytes(instance->rx_buffer, serial_num->data, sizeof(PicopassSerialNum));
|
|
} while(false);
|
|
|
|
return ret;
|
|
}
|
|
|
|
PicopassError
|
|
picopass_poller_read_block(PicopassPoller* instance, uint8_t block_num, PicopassBlock* block) {
|
|
PicopassError ret = PicopassErrorNone;
|
|
|
|
do {
|
|
bit_buffer_reset(instance->tmp_buffer);
|
|
bit_buffer_append_byte(instance->tmp_buffer, block_num);
|
|
iso13239_crc_append(Iso13239CrcTypePicopass, instance->tmp_buffer);
|
|
bit_buffer_reset(instance->tx_buffer);
|
|
bit_buffer_append_byte(instance->tx_buffer, RFAL_PICOPASS_CMD_READ_OR_IDENTIFY);
|
|
bit_buffer_append(instance->tx_buffer, instance->tmp_buffer);
|
|
|
|
ret = picopass_poller_send_frame(
|
|
instance, instance->tx_buffer, instance->rx_buffer, PICOPASS_POLLER_FWT_FC);
|
|
if(ret != PicopassErrorNone) break;
|
|
|
|
if(bit_buffer_get_size_bytes(instance->rx_buffer) != sizeof(PicopassBlock)) {
|
|
ret = PicopassErrorProtocol;
|
|
break;
|
|
}
|
|
bit_buffer_write_bytes(instance->rx_buffer, block->data, sizeof(PicopassBlock));
|
|
} while(false);
|
|
|
|
return ret;
|
|
}
|
|
|
|
PicopassError
|
|
picopass_poller_read_check(PicopassPoller* instance, PicopassReadCheckResp* read_check_resp) {
|
|
PicopassError ret = PicopassErrorNone;
|
|
|
|
do {
|
|
bit_buffer_reset(instance->tx_buffer);
|
|
bit_buffer_append_byte(instance->tx_buffer, RFAL_PICOPASS_CMD_READCHECK_KD);
|
|
bit_buffer_append_byte(instance->tx_buffer, 0x02);
|
|
|
|
NfcError error = nfc_poller_trx(
|
|
instance->nfc, instance->tx_buffer, instance->rx_buffer, PICOPASS_POLLER_FWT_FC);
|
|
if(error != NfcErrorNone) {
|
|
ret = picopass_poller_process_error(error);
|
|
break;
|
|
}
|
|
|
|
if(bit_buffer_get_size_bytes(instance->rx_buffer) != sizeof(PicopassReadCheckResp)) {
|
|
ret = PicopassErrorProtocol;
|
|
break;
|
|
}
|
|
bit_buffer_write_bytes(
|
|
instance->rx_buffer, read_check_resp->data, sizeof(PicopassReadCheckResp));
|
|
} while(false);
|
|
|
|
return ret;
|
|
}
|
|
|
|
PicopassError picopass_poller_check(
|
|
PicopassPoller* instance,
|
|
PicopassMac* mac,
|
|
PicopassCheckResp* check_resp) {
|
|
PicopassError ret = PicopassErrorNone;
|
|
|
|
do {
|
|
bit_buffer_reset(instance->tx_buffer);
|
|
bit_buffer_append_byte(instance->tx_buffer, RFAL_PICOPASS_CMD_CHECK);
|
|
uint8_t null_arr[4] = {};
|
|
bit_buffer_append_bytes(instance->tx_buffer, null_arr, sizeof(null_arr));
|
|
bit_buffer_append_bytes(instance->tx_buffer, mac->data, sizeof(PicopassMac));
|
|
|
|
NfcError error = nfc_poller_trx(
|
|
instance->nfc, instance->tx_buffer, instance->rx_buffer, PICOPASS_POLLER_FWT_FC);
|
|
if(error != NfcErrorNone) {
|
|
ret = picopass_poller_process_error(error);
|
|
break;
|
|
}
|
|
|
|
if(bit_buffer_get_size_bytes(instance->rx_buffer) != sizeof(PicopassCheckResp)) {
|
|
ret = PicopassErrorProtocol;
|
|
break;
|
|
}
|
|
bit_buffer_write_bytes(instance->rx_buffer, check_resp->data, sizeof(PicopassCheckResp));
|
|
|
|
} while(false);
|
|
|
|
return ret;
|
|
}
|
|
|
|
PicopassError picopass_poller_write_block(
|
|
PicopassPoller* instance,
|
|
uint8_t block_num,
|
|
const PicopassBlock* block,
|
|
const PicopassMac* mac) {
|
|
PicopassError ret = PicopassErrorNone;
|
|
|
|
do {
|
|
bit_buffer_reset(instance->tx_buffer);
|
|
bit_buffer_append_byte(instance->tx_buffer, RFAL_PICOPASS_CMD_UPDATE);
|
|
bit_buffer_append_byte(instance->tx_buffer, block_num);
|
|
bit_buffer_append_bytes(instance->tx_buffer, block->data, sizeof(PicopassBlock));
|
|
bit_buffer_append_bytes(instance->tx_buffer, mac->data, sizeof(PicopassMac));
|
|
|
|
NfcError error = nfc_poller_trx(
|
|
instance->nfc, instance->tx_buffer, instance->rx_buffer, PICOPASS_POLLER_FWT_FC);
|
|
if(error != NfcErrorNone) {
|
|
ret = picopass_poller_process_error(error);
|
|
break;
|
|
}
|
|
|
|
} while(false);
|
|
|
|
return ret;
|
|
}
|