Files
djhackersdev_bemanitools/src/main/aciodrv/icca.c
T

182 lines
4.3 KiB
C

#define LOG_MODULE "aciodrv-icca"
#include <string.h>
#include "aciodrv/device.h"
#include "aciodrv/icca.h"
#include "util/log.h"
static bool aciodrv_icca_queue_loop_start(
struct aciodrv_device_ctx *device, uint8_t node_id)
{
struct ac_io_message msg;
log_assert(device);
msg.addr = node_id;
msg.cmd.code = ac_io_u16(AC_IO_ICCA_CMD_QUEUE_LOOP_START);
msg.cmd.nbytes = 1;
msg.cmd.status = 0;
if (!aciodrv_send_and_recv(
device, &msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
log_warning("Starting queue loop failed");
return false;
}
log_info(
"Started queue loop of node %d, status: %d", node_id, msg.cmd.status);
return true;
}
bool aciodrv_icca_init(struct aciodrv_device_ctx *device, uint8_t node_id)
{
log_assert(device);
if (!aciodrv_icca_queue_loop_start(device, node_id + 1)) {
return false;
}
return true;
}
bool aciodrv_icca_set_state(
struct aciodrv_device_ctx *device,
uint8_t node_id,
int slot_state,
struct ac_io_icca_state *state)
{
struct ac_io_message msg;
log_assert(device);
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_ICCA_CMD_SET_SLOT_STATE);
msg.cmd.nbytes = 2;
/* buffer size of data we expect */
msg.cmd.raw[0] = sizeof(struct ac_io_icca_state);
msg.cmd.raw[1] = slot_state;
if (!aciodrv_send_and_recv(
device,
&msg,
offsetof(struct ac_io_message, cmd.raw) + msg.cmd.raw[0])) {
log_warning("Setting state of node %d failed", node_id + 1);
return false;
}
if (state != NULL) {
memcpy(state, msg.cmd.raw, sizeof(struct ac_io_icca_state));
}
return true;
}
bool aciodrv_icca_get_state(
struct aciodrv_device_ctx *device,
uint8_t node_id,
struct ac_io_icca_state *state)
{
struct ac_io_message msg;
log_assert(device);
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_ICCA_CMD_POLL);
msg.cmd.nbytes = 1;
/* buffer size of data we expect */
msg.cmd.count = sizeof(struct ac_io_icca_state);
if (!aciodrv_send_and_recv(
device,
&msg,
offsetof(struct ac_io_message, cmd.raw) + msg.cmd.count)) {
log_warning("Getting state of node %d failed", node_id + 1);
return false;
}
if (state != NULL) {
memcpy(state, msg.cmd.raw, sizeof(struct ac_io_icca_state));
}
return true;
}
bool aciodrv_icca_read_card(
struct aciodrv_device_ctx *device,
uint8_t node_id,
struct ac_io_icca_state *state)
{
struct ac_io_message msg;
log_assert(device);
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_ICCA_CMD_ENGAGE);
msg.cmd.nbytes = 1;
/* buffer size of data we expect */
msg.cmd.count = sizeof(struct ac_io_icca_state);
if (!aciodrv_send_and_recv(
device,
&msg,
offsetof(struct ac_io_message, cmd.raw) + msg.cmd.count)) {
log_warning("Reading card of node %d failed", node_id + 1);
return false;
}
if (state != NULL) {
memcpy(state, msg.cmd.raw, sizeof(struct ac_io_icca_state));
}
return true;
}
bool aciodrv_icca_is_slotted(struct aciodrv_device_ctx *device, uint8_t node_id)
{
const struct aciodrv_device_node_version *version;
version = aciodrv_device_get_node_product_version(device, node_id);
// current heuristic is to check if version >= 1.5
if (version) {
if (version->major == 1) {
if (version->minor >= 5) {
return false;
}
}
}
return true;
}
bool aciodrv_icca_poll_felica(
struct aciodrv_device_ctx *device, uint8_t node_id)
{
struct ac_io_message msg;
log_assert(device);
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_ICCA_CMD_POLL_FELICA);
msg.cmd.nbytes = 4;
/* buffer size of data we expect */
msg.cmd.count = 1;
// additional data, not sure
msg.cmd.raw[1] = 0x03;
msg.cmd.raw[2] = 0xFF;
msg.cmd.raw[3] = 0xFF;
if (!aciodrv_send_and_recv(
device,
&msg,
offsetof(struct ac_io_message, cmd.raw) + msg.cmd.count)) {
log_warning("Reading card of node %d failed", node_id + 1);
return false;
}
return true;
}