1
0
mirror of https://github.com/djhackersdev/bemanitools.git synced 2025-02-26 14:41:53 +01:00

Stopgap: Modified eamio-icca for wavepass working with mag and slotted readers

The implementation emulates parts of the slotted and magnetic reader
command flow to ensure that this implementation is working with games
that only operate on slotted or magnetic card readers, e.g. iidx 9-18
This commit is contained in:
icex2 2020-11-06 23:43:17 +01:00
parent f5c8ab6d77
commit bdb11bb60c
3 changed files with 83 additions and 25 deletions

View File

@ -46,6 +46,13 @@ enum ac_io_icca_keypad_mask {
AC_IO_ICCA_KEYPAD_MASK_8 = (1 << 15),
};
enum ac_io_icca_status_code {
AC_IO_ICCA_STATUS_FAULT = 0x00,
AC_IO_ICCA_STATUS_IDLE = 0x01,
AC_IO_ICCA_STATUS_GOT_UID = 0x02,
AC_IO_ICCA_STATUS_IDLE_NEW = 0x04
};
#pragma pack(push, 1)
struct ac_io_icca_misc {

View File

@ -29,13 +29,6 @@ enum ac_io_icca_flag {
AC_IO_ICCA_FLAG_SOLENOID = 0x40
};
enum ac_io_icca_status_code {
AC_IO_ICCA_STATUS_FAULT = 0x00,
AC_IO_ICCA_STATUS_IDLE = 0x01,
AC_IO_ICCA_STATUS_GOT_UID = 0x02,
AC_IO_ICCA_STATUS_IDLE_NEW = 0x04
};
static void ac_io_emu_icca_cmd_send_version(
struct ac_io_emu_icca *icca, const struct ac_io_message *req);

View File

@ -8,6 +8,8 @@
#include <stdint.h>
#include <stdio.h>
#include "acio/icca.h"
#include "aciodrv/device.h"
#include "aciodrv/icca.h"
@ -32,7 +34,20 @@ static const uint8_t eam_io_keypad_mappings[16] = {EAM_IO_KEYPAD_DECIMAL,
EAM_IO_KEYPAD_5,
EAM_IO_KEYPAD_8};
// States to map slotted state machine to a slightly simplified
// one that fits the states of the wavepass reader. Probably
// the most important part is correct emulation of the slot
// sensores to ensure the calling backend's states are set
// correctly
enum eam_io_icca_card_state {
EAM_IO_ICCA_CARD_STATE_IDLE = 0,
EAM_IO_ICCA_CARD_STATE_PROBE = 1,
};
static struct ac_io_icca_state eam_io_icca_state[2];
static enum eam_io_icca_card_state eam_io_icca_card_state[2];
static bool eam_io_icca_card_data_avail[2];
static uint8_t eam_io_icca_card_uid_buffer[2][8];
void eam_io_set_loggers(
log_formatter_t misc,
@ -56,8 +71,13 @@ bool eam_io_init(
log_warning("Initializing icca %d failed", i);
return false;
}
eam_io_icca_card_state[i] = EAM_IO_ICCA_CARD_STATE_IDLE;
eam_io_icca_card_data_avail[i] = false;
}
log_info("Initialized icca wavepass");
return true;
}
@ -85,12 +105,10 @@ uint8_t eam_io_get_sensor_state(uint8_t unit_no)
{
uint8_t sensors = 0;
if ((eam_io_icca_state[unit_no].sensor_state &
AC_IO_ICCA_SENSOR_MASK_BACK_ON) > 0) {
// when card data is available, signal this by telling the backend "card fully inserted"
// also, keep card "inserted" as long as reading is in progress
if (eam_io_icca_card_data_avail[unit_no]) {
sensors |= (1 << EAM_IO_SENSOR_BACK);
}
if ((eam_io_icca_state[unit_no].sensor_state &
AC_IO_ICCA_SENSOR_MASK_FRONT_ON) > 0) {
sensors |= (1 << EAM_IO_SENSOR_FRONT);
}
@ -99,32 +117,44 @@ uint8_t eam_io_get_sensor_state(uint8_t unit_no)
uint8_t eam_io_read_card(uint8_t unit_no, uint8_t *card_id, uint8_t nbytes)
{
memcpy(card_id, eam_io_icca_state[unit_no].uid, nbytes);
// report back with actual data read from card only if card read command
// status reports back there is data
if (eam_io_icca_card_data_avail[unit_no]) {
memcpy(card_id, eam_io_icca_card_uid_buffer[unit_no], nbytes);
if (card_id[0] == 0xe0 && card_id[1] == 0x04) {
return EAM_IO_CARD_ISO15696;
} else {
return EAM_IO_CARD_FELICA;
}
} else {
// Avoids garbage data reads for wavepass readers since these need to be
// polled continuously for data
memset(card_id, 0, nbytes);
return EAM_IO_CARD_NONE;
}
}
bool eam_io_card_slot_cmd(uint8_t unit_no, uint8_t cmd)
{
switch (cmd) {
case EAM_IO_CARD_SLOT_CMD_CLOSE:
return aciodrv_icca_set_state(
unit_no, AC_IO_ICCA_SLOT_STATE_CLOSE, NULL);
eam_io_icca_card_state[unit_no] = EAM_IO_ICCA_CARD_STATE_IDLE;
return true;
case EAM_IO_CARD_SLOT_CMD_OPEN:
return aciodrv_icca_set_state(
unit_no, AC_IO_ICCA_SLOT_STATE_OPEN, NULL);
eam_io_icca_card_state[unit_no] = EAM_IO_ICCA_CARD_STATE_PROBE;
return true;
case EAM_IO_CARD_SLOT_CMD_EJECT:
return aciodrv_icca_set_state(
unit_no, AC_IO_ICCA_SLOT_STATE_EJECT, NULL);
eam_io_icca_card_data_avail[unit_no] = false;
eam_io_icca_card_state[unit_no] = EAM_IO_ICCA_CARD_STATE_IDLE;
return true;
case EAM_IO_CARD_SLOT_CMD_READ:
return aciodrv_icca_read_card(unit_no, NULL) &&
aciodrv_icca_get_state(unit_no, &eam_io_icca_state[unit_no]);
return true;
default:
break;
@ -135,7 +165,35 @@ bool eam_io_card_slot_cmd(uint8_t unit_no, uint8_t cmd)
bool eam_io_poll(uint8_t unit_no)
{
// On idle, i.e. the game does not signal any interest in reading cards,
// just to a standard poll to get the latest status of the readers
if (eam_io_icca_card_state[unit_no] == EAM_IO_ICCA_CARD_STATE_IDLE) {
return aciodrv_icca_get_state(unit_no, &eam_io_icca_state[unit_no]);
} else {
// When either probing or reading the card, do actual reading by
// continuously issueing the read command to either keep probing
// for potential cards nearby or actually getting data from
// detected cards back.
if (aciodrv_icca_read_card(unit_no, NULL) &&
aciodrv_icca_get_state(unit_no, &eam_io_icca_state[unit_no])) {
if (!eam_io_icca_card_data_avail[unit_no] &&
eam_io_icca_state[unit_no].status_code == AC_IO_ICCA_STATUS_GOT_UID) {
eam_io_icca_card_data_avail[unit_no] = true;
// tmp store read card id because stupid mag readers are sending open and close
// commands all the time which makes creating a sane state machine impossible
memcpy(
eam_io_icca_card_uid_buffer[unit_no],
eam_io_icca_state[unit_no].uid,
sizeof(eam_io_icca_card_uid_buffer[unit_no]));
}
return true;
}
}
return false;
}
const struct eam_io_config_api *eam_io_get_config_api(void)