Don't mind this i basically removed everything woops
This commit is contained in:
parent
358e4633ae
commit
6143187f3b
258
aimeio/aimeio.c
258
aimeio/aimeio.c
@ -1,3 +1,5 @@
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <assert.h>
|
||||
@ -8,83 +10,218 @@
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "aimeio/aimeio.h"
|
||||
#include "aimepcsc/aimepcsc.h"
|
||||
#include "aimeio.h"
|
||||
|
||||
static struct aimepcsc_context *ctx;
|
||||
static struct aime_data data;
|
||||
#define REPORTID_LIGHT_OUTPUT_AIME 0x0A
|
||||
#define REPORTID_INPUT_OLD 0x01
|
||||
#define REPORTID_INPUT_FELICA 0x02
|
||||
#define ITF_NUM_LIGHT 0x01
|
||||
#define ITF_NUM_CARDIO 0x02
|
||||
|
||||
uint16_t aime_io_get_api_version(void)
|
||||
struct aime_io_config
|
||||
{
|
||||
wchar_t aime_path[MAX_PATH];
|
||||
wchar_t felica_path[MAX_PATH];
|
||||
uint8_t vk_scan;
|
||||
};
|
||||
|
||||
static struct aime_io_config aime_io_cfg;
|
||||
static uint8_t aime_io_aime_id[10];
|
||||
static uint8_t aime_io_felica_id[8];
|
||||
static bool aime_io_aime_id_present;
|
||||
static bool aime_io_felica_id_present;
|
||||
|
||||
static void aime_io_config_read(
|
||||
struct aime_io_config *cfg,
|
||||
const wchar_t *filename);
|
||||
|
||||
static void aime_io_config_read(
|
||||
struct aime_io_config *cfg,
|
||||
const wchar_t *filename)
|
||||
{
|
||||
// VERBOSE_DEBUG("aime_io_config_read\n");
|
||||
assert(cfg != NULL);
|
||||
assert(filename != NULL);
|
||||
|
||||
GetPrivateProfileStringW(
|
||||
L"aime",
|
||||
L"aimePath",
|
||||
L"DEVICE\\aime.txt",
|
||||
cfg->aime_path,
|
||||
_countof(cfg->aime_path),
|
||||
filename);
|
||||
|
||||
GetPrivateProfileStringW(
|
||||
L"aime",
|
||||
L"felicaPath",
|
||||
L"DEVICE\\felica.txt",
|
||||
cfg->felica_path,
|
||||
_countof(cfg->felica_path),
|
||||
filename);
|
||||
|
||||
cfg->vk_scan = GetPrivateProfileIntW(
|
||||
L"aime",
|
||||
L"scan",
|
||||
VK_RETURN,
|
||||
filename);
|
||||
}
|
||||
|
||||
static HANDLE aime_io_poll_thread;
|
||||
static bool aime_io_poll_stop_flag;
|
||||
|
||||
typedef struct aime_report_s
|
||||
{
|
||||
uint8_t report_id; // 1 for old, 2 for felica, 0 to rearm poll
|
||||
uint8_t uid[8];
|
||||
} aime_report_t;
|
||||
|
||||
aime_report_t g_aime_report = {0};
|
||||
|
||||
static unsigned int __stdcall aime_io_poll_thread_proc(void *ctx)
|
||||
{
|
||||
while (!aime_io_poll_stop_flag)
|
||||
{
|
||||
if (g_aime_report.report_id != 0)
|
||||
continue;
|
||||
|
||||
// (void)hid_get_report(g_device_handle, (uint8_t *)&g_aime_report, REPORTID_INPUT_OLD, 9);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t __cdecl aime_io_get_api_version(void)
|
||||
{
|
||||
return 0x0100;
|
||||
}
|
||||
|
||||
HRESULT aime_io_init(void)
|
||||
{
|
||||
int ret;
|
||||
FILE* fp;
|
||||
// VERBOSE_DEBUG("aime_io_init\n");
|
||||
aime_io_config_read(&aime_io_cfg, L".\\segatools.ini");
|
||||
|
||||
ret = AllocConsole();
|
||||
// VERBOSE_DEBUG("config read, opening USB device\n");
|
||||
// if (hid_open_device(&g_device_handle, 0x0f0d, 0x00fb, ITF_NUM_CARDIO) != 0)
|
||||
// {
|
||||
// VERBOSE_DEBUG("USB Device not found\n");
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
// someone might already allocated a console - seeing this on fufubot's segatools
|
||||
if (ret != 0) {
|
||||
// only when we allocate a console, we need to redirect stdout
|
||||
freopen_s(&fp, "CONOUT$", "w", stdout);
|
||||
// VERBOSE_DEBUG("Cardio found\n");
|
||||
/* try to open the HID lights interface (will fail for Hori official, no biggie) */
|
||||
// if (hid_open_device(&g_lights_handle, 0x0f0d, 0x00fb, ITF_NUM_LIGHT) != 0)
|
||||
// {
|
||||
// VERBOSE_DEBUG("no lights handle\n");
|
||||
// g_lights_handle = NULL;
|
||||
// }
|
||||
|
||||
/* start poll thread */
|
||||
if (aime_io_poll_thread != NULL)
|
||||
{
|
||||
// VERBOSE_DEBUG("poll thread already init\n");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
ctx = aimepcsc_create();
|
||||
if (!ctx) {
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
ret = aimepcsc_init(ctx);
|
||||
|
||||
if (ret != 0) {
|
||||
printf("aimeio-pcsc: failed to initialize: %s\n", aimepcsc_error(ctx));
|
||||
aimepcsc_destroy(ctx);
|
||||
ctx = NULL;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
printf("aimeio-pcsc: initialized with reader: %s\n", aimepcsc_reader_name(ctx));
|
||||
aime_io_poll_thread = (HANDLE)_beginthreadex(
|
||||
NULL,
|
||||
0,
|
||||
aime_io_poll_thread_proc,
|
||||
NULL,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
// VERBOSE_DEBUG("init ok\n");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT aime_io_nfc_poll(uint8_t unit_no)
|
||||
{
|
||||
int ret;
|
||||
HRESULT hr;
|
||||
// VERBOSE_DEBUG("aime_io_nfc_poll\n");
|
||||
// bool sense;
|
||||
// HRESULT hr;
|
||||
|
||||
if (unit_no != 0) {
|
||||
return S_OK;
|
||||
}
|
||||
// if (unit_no != 0)
|
||||
// {
|
||||
// return S_OK;
|
||||
// }
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
// if (!sense)
|
||||
// {
|
||||
// aime_io_aime_id_present = false;
|
||||
// aime_io_felica_id_present = false;
|
||||
// return S_OK;
|
||||
// }
|
||||
|
||||
ret = aimepcsc_poll(ctx, &data);
|
||||
/* Try AiMe IC */
|
||||
|
||||
if (ret < 0) {
|
||||
printf("aimeio-pcsc: poll failed: %s\n", aimepcsc_error(ctx));
|
||||
}
|
||||
// hr = aime_io_read_id_file(
|
||||
// aime_io_cfg.aime_path,
|
||||
// aime_io_aime_id,
|
||||
// sizeof(aime_io_aime_id));
|
||||
|
||||
// if (SUCCEEDED(hr) && hr != S_FALSE)
|
||||
// {
|
||||
// aime_io_aime_id_present = true;
|
||||
|
||||
// return S_OK;
|
||||
// }
|
||||
|
||||
/* Try FeliCa IC */
|
||||
|
||||
// hr = aime_io_read_id_file(
|
||||
// aime_io_cfg.felica_path,
|
||||
// aime_io_felica_id,
|
||||
// sizeof(aime_io_felica_id));
|
||||
|
||||
// if (SUCCEEDED(hr) && hr != S_FALSE)
|
||||
// {
|
||||
// aime_io_felica_id_present = true;
|
||||
|
||||
// return S_OK;
|
||||
// }
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT aime_io_nfc_get_aime_id(
|
||||
uint8_t unit_no,
|
||||
uint8_t *luid,
|
||||
size_t luid_size)
|
||||
HRESULT aime_io_nfc_get_aime_id(uint8_t unit_no, uint8_t *luid, size_t luid_size)
|
||||
{
|
||||
assert(luid != NULL);
|
||||
assert(luid_size == sizeof(aime_io_aime_id));
|
||||
|
||||
if (unit_no != 0 || data.card_type != Mifare || luid_size != data.card_id_len) {
|
||||
// VERBOSE_DEBUG("aime_io_nfc_get_aime_id\n");
|
||||
if (unit_no != 0)
|
||||
return S_FALSE;
|
||||
|
||||
if (aime_io_aime_id_present)
|
||||
{
|
||||
// VERBOSE_DEBUG("Found OLD present from conf\n");
|
||||
memcpy(luid, aime_io_aime_id, luid_size);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
memcpy(luid, data.card_id, luid_size);
|
||||
if (g_aime_report.report_id == 1)
|
||||
{
|
||||
// VERBOSE_DEBUG("Found OLD present from NFC\n");
|
||||
uint64_t val = 0;
|
||||
|
||||
for (int i = 4; i < 8; i++)
|
||||
{
|
||||
val = (val << 8) | g_aime_report.uid[i];
|
||||
}
|
||||
// VERBOSE_DEBUG("uid %02x %02x %02x %02x -> %lld\nluid: ", g_aime_report.uid[4], g_aime_report.uid[5], g_aime_report.uid[6], g_aime_report.uid[7], val);
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
luid[9 - i] = val % 10;
|
||||
val /= 10;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
g_aime_report.report_id = 0; // rearm poll in thread
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT aime_io_nfc_get_felica_id(uint8_t unit_no, uint64_t *IDm)
|
||||
@ -93,21 +230,42 @@ HRESULT aime_io_nfc_get_felica_id(uint8_t unit_no, uint64_t *IDm)
|
||||
size_t i;
|
||||
|
||||
assert(IDm != NULL);
|
||||
// VERBOSE_DEBUG("aime_io_nfc_get_felica_id\n");
|
||||
|
||||
if (unit_no != 0 || data.card_type != FeliCa || data.card_id_len != 8) {
|
||||
if (unit_no != 0)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
if (aime_io_felica_id_present)
|
||||
{
|
||||
// VERBOSE_DEBUG("Found FeliCa present from conf\n");
|
||||
val = 0;
|
||||
|
||||
for (i = 0 ; i < 8 ; i++) {
|
||||
val = (val << 8) | data.card_id[i];
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
val = (val << 8) | aime_io_felica_id[i];
|
||||
}
|
||||
|
||||
*IDm = val;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
unsigned char ID[10];
|
||||
if (g_aime_report.report_id == 2)
|
||||
{
|
||||
// VERBOSE_DEBUG("Found FeliCa present from NFC\n");
|
||||
val = 0;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
val = (val << 8) | g_aime_report.uid[i];
|
||||
}
|
||||
|
||||
*IDm = val;
|
||||
g_aime_report.report_id = 0; // rearm poll in thread
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
void aime_io_led_set_color(uint8_t unit_no, uint8_t r, uint8_t g, uint8_t b)
|
||||
{}
|
||||
void aime_io_led_set_color(uint8_t unit_no, uint8_t r, uint8_t g, uint8_t b) {}
|
@ -4,6 +4,6 @@ EXPORTS
|
||||
aime_io_get_api_version
|
||||
aime_io_init
|
||||
aime_io_led_set_color
|
||||
aime_io_nfc_poll
|
||||
aime_io_nfc_get_aime_id
|
||||
aime_io_nfc_get_felica_id
|
||||
aime_io_nfc_poll
|
||||
|
162
aimeio/aimeio.h
162
aimeio/aimeio.h
@ -5,83 +5,103 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
Get the version of the Aime IO API that this DLL supports. This function
|
||||
should return a positive 16-bit integer, where the high byte is the major
|
||||
version and the low byte is the minor version (as defined by the Semantic
|
||||
Versioning standard).
|
||||
/* THIS API IS UNSTABLE. Please do not build alternative implementations of
|
||||
this DLL just yet unless you are prepared to deal with API breakages. */
|
||||
|
||||
The latest API version as of this writing is 0x0100.
|
||||
*/
|
||||
uint16_t aime_io_get_api_version(void);
|
||||
|
||||
/*
|
||||
Initialize Aime IO provider DLL. Only called once, before any other
|
||||
functions exported from this DLL are called (except for
|
||||
aime_io_get_api_version).
|
||||
|
||||
Minimum API version: 0x0100
|
||||
*/
|
||||
HRESULT aime_io_init(void);
|
||||
|
||||
/*
|
||||
Poll for IC cards in the vicinity.
|
||||
|
||||
- unit_no: Always 0 as of the current API version
|
||||
|
||||
Minimum API version: 0x0100
|
||||
*/
|
||||
void aime_io_fini(void);
|
||||
HRESULT aime_io_nfc_poll(uint8_t unit_no);
|
||||
|
||||
/*
|
||||
Attempt to read out a classic Aime card ID
|
||||
|
||||
- unit_no: Always 0 as of the current API version
|
||||
- luid: Pointer to a ten-byte buffer that will receive the ID
|
||||
- luid_size: Size of the buffer at *luid. Always 10.
|
||||
|
||||
Returns:
|
||||
|
||||
- S_OK if a classic Aime is present and was read successfully
|
||||
- S_FALSE if no classic Aime card is present (*luid will be ignored)
|
||||
- Any HRESULT error if an error occured.
|
||||
|
||||
Minimum API version: 0x0100
|
||||
*/
|
||||
HRESULT aime_io_nfc_get_aime_id(
|
||||
uint8_t unit_no,
|
||||
uint8_t *luid,
|
||||
size_t luid_size);
|
||||
|
||||
/*
|
||||
Attempt to read out a FeliCa card ID ("IDm"). The following are examples
|
||||
of FeliCa cards:
|
||||
|
||||
- Amuse IC (which includes new-style Aime-branded cards, among others)
|
||||
- Smartphones with FeliCa NFC capability (uncommon outside Japan)
|
||||
- Various Japanese e-cash cards and train passes
|
||||
|
||||
Parameters:
|
||||
|
||||
- unit_no: Always 0 as of the current API version
|
||||
- IDm: Output parameter that will receive the card ID
|
||||
|
||||
Returns:
|
||||
|
||||
- S_OK if a FeliCa device is present and was read successfully
|
||||
- S_FALSE if no FeliCa device is present (*IDm will be ignored)
|
||||
- Any HRESULT error if an error occured.
|
||||
|
||||
Minimum API version: 0x0100
|
||||
*/
|
||||
HRESULT aime_io_nfc_get_felica_id(uint8_t unit_no, uint64_t *IDm);
|
||||
|
||||
/*
|
||||
Change the color and brightness of the card reader's RGB lighting
|
||||
|
||||
- unit_no: Always 0 as of the current API version
|
||||
- r, g, b: Primary color intensity, from 0 to 255 inclusive.
|
||||
|
||||
Minimum API version: 0x0100
|
||||
*/
|
||||
void aime_io_led_set_color(uint8_t unit_no, uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
// #pragma once
|
||||
|
||||
// #include <windows.h>
|
||||
|
||||
// #include <stddef.h>
|
||||
// #include <stdint.h>
|
||||
|
||||
// /*
|
||||
// Get the version of the Aime IO API that this DLL supports. This function
|
||||
// should return a positive 16-bit integer, where the high byte is the major
|
||||
// version and the low byte is the minor version (as defined by the Semantic
|
||||
// Versioning standard).
|
||||
|
||||
// The latest API version as of this writing is 0x0100.
|
||||
// */
|
||||
// uint16_t aime_io_get_api_version(void);
|
||||
|
||||
// /*
|
||||
// Initialize Aime IO provider DLL. Only called once, before any other
|
||||
// functions exported from this DLL are called (except for
|
||||
// aime_io_get_api_version).
|
||||
|
||||
// Minimum API version: 0x0100
|
||||
// */
|
||||
// HRESULT aime_io_init(void);
|
||||
|
||||
// /*
|
||||
// Poll for IC cards in the vicinity.
|
||||
|
||||
// - unit_no: Always 0 as of the current API version
|
||||
|
||||
// Minimum API version: 0x0100
|
||||
// */
|
||||
// HRESULT aime_io_nfc_poll(uint8_t unit_no);
|
||||
|
||||
// /*
|
||||
// Attempt to read out a classic Aime card ID
|
||||
|
||||
// - unit_no: Always 0 as of the current API version
|
||||
// - luid: Pointer to a ten-byte buffer that will receive the ID
|
||||
// - luid_size: Size of the buffer at *luid. Always 10.
|
||||
|
||||
// Returns:
|
||||
|
||||
// - S_OK if a classic Aime is present and was read successfully
|
||||
// - S_FALSE if no classic Aime card is present (*luid will be ignored)
|
||||
// - Any HRESULT error if an error occured.
|
||||
|
||||
// Minimum API version: 0x0100
|
||||
// */
|
||||
// HRESULT aime_io_nfc_get_aime_id(
|
||||
// uint8_t unit_no,
|
||||
// uint8_t *luid,
|
||||
// size_t luid_size);
|
||||
|
||||
// /*
|
||||
// Attempt to read out a FeliCa card ID ("IDm"). The following are examples
|
||||
// of FeliCa cards:
|
||||
|
||||
// - Amuse IC (which includes new-style Aime-branded cards, among others)
|
||||
// - Smartphones with FeliCa NFC capability (uncommon outside Japan)
|
||||
// - Various Japanese e-cash cards and train passes
|
||||
|
||||
// Parameters:
|
||||
|
||||
// - unit_no: Always 0 as of the current API version
|
||||
// - IDm: Output parameter that will receive the card ID
|
||||
|
||||
// Returns:
|
||||
|
||||
// - S_OK if a FeliCa device is present and was read successfully
|
||||
// - S_FALSE if no FeliCa device is present (*IDm will be ignored)
|
||||
// - Any HRESULT error if an error occured.
|
||||
|
||||
// Minimum API version: 0x0100
|
||||
// */
|
||||
// HRESULT aime_io_nfc_get_felica_id(uint8_t unit_no, uint64_t *IDm);
|
||||
|
||||
// /*
|
||||
// Change the color and brightness of the card reader's RGB lighting
|
||||
|
||||
// - unit_no: Always 0 as of the current API version
|
||||
// - r, g, b: Primary color intensity, from 0 to 255 inclusive.
|
||||
|
||||
// Minimum API version: 0x0100
|
||||
// */
|
||||
// void aime_io_led_set_color(uint8_t unit_no, uint8_t r, uint8_t g, uint8_t b);
|
||||
|
@ -1,11 +1,16 @@
|
||||
aimeio_lib = shared_library(
|
||||
compiler = meson.get_compiler('c')
|
||||
winscard_lib = compiler.find_library('winscard')
|
||||
|
||||
deps = [
|
||||
winscard_lib,
|
||||
]
|
||||
|
||||
shared_library(
|
||||
'aimeio',
|
||||
name_prefix : '',
|
||||
include_directories: inc,
|
||||
implicit_include_directories : false,
|
||||
vs_module_defs : 'aimeio.def',
|
||||
link_with: [aimepcsc_lib],
|
||||
sources : [
|
||||
'aimeio.c',
|
||||
sources: [
|
||||
'aimeio.c'
|
||||
],
|
||||
dependencies: deps,
|
||||
)
|
@ -1,222 +0,0 @@
|
||||
#include "aimepcsc.h"
|
||||
#include <stdio.h>
|
||||
|
||||
static const uint8_t atr_ios14443_common[] = {0x3B, 0x8F, 0x80, 0x01, 0x80, 0x4F, 0x0C, 0xA0, 0x00, 0x00, 0x03, 0x06};
|
||||
static const uint8_t cardtype_m1k[] = {0x03, 0x00, 0x01};
|
||||
static const uint8_t cardtype_felica[] = {0x11, 0x00, 0x3B};
|
||||
|
||||
static const uint8_t felica_cmd_readidm[] = {0xFF, 0xCA, 0x00, 0x00, 0x00};
|
||||
|
||||
static const uint8_t m1k_cmd_loadkey[] = {0xFF, 0x82, 0x00, 0x00, 0x06, 0x57, 0x43, 0x43, 0x46, 0x76, 0x32};
|
||||
static const uint8_t m1k_cmd_auth_block2[] = {0xFF, 0x86, 0x00, 0x00, 0x05, 0x01, 0x00, 0x02, 0x61, 0x00};
|
||||
static const uint8_t m1k_cmd_read_block2[] = {0xFF, 0xB0, 0x00, 0x02, 0x10};
|
||||
|
||||
struct aimepcsc_context {
|
||||
SCARDCONTEXT hContext;
|
||||
LPSTR mszReaders;
|
||||
DWORD pcchReaders;
|
||||
|
||||
CHAR last_error[256];
|
||||
};
|
||||
|
||||
#define APDU_SEND(card, cmd, expected_res_len) \
|
||||
do { \
|
||||
len = sizeof(buf); \
|
||||
ret = SCardTransmit(*card, SCARD_PCI_T1, cmd, sizeof(cmd), NULL, buf, &len); \
|
||||
if (ret != SCARD_S_SUCCESS) { \
|
||||
snprintf(ctx->last_error, sizeof(ctx->last_error), "SCardTransmit failed during " #cmd ": %08lX", (ULONG) ret); \
|
||||
return -1; \
|
||||
} \
|
||||
if (len != expected_res_len || buf[expected_res_len - 2] != 0x90 || buf[expected_res_len - 1] != 0x00) { \
|
||||
snprintf(ctx->last_error, sizeof(ctx->last_error), #cmd " failed; res_len=%lu, res_code=%02x%02x", len, buf[2], buf[3]); \
|
||||
return 1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int read_felica_aime(struct aimepcsc_context *ctx, LPSCARDHANDLE card, struct aime_data *data) {
|
||||
uint8_t buf[32];
|
||||
DWORD len;
|
||||
LONG ret;
|
||||
|
||||
/* read card ID */
|
||||
APDU_SEND(card, felica_cmd_readidm, 10);
|
||||
|
||||
data->card_id_len = 8;
|
||||
memcpy(data->card_id, buf, 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_m1k_aime(struct aimepcsc_context *ctx, LPSCARDHANDLE card, struct aime_data *data) {
|
||||
uint8_t buf[32];
|
||||
DWORD len;
|
||||
LONG ret;
|
||||
|
||||
/* load key onto reader */
|
||||
APDU_SEND(card, m1k_cmd_loadkey, 2);
|
||||
|
||||
/* authenticate block 2 */
|
||||
APDU_SEND(card, m1k_cmd_auth_block2, 2);
|
||||
|
||||
/* read block 2 */
|
||||
APDU_SEND(card, m1k_cmd_read_block2, 18);
|
||||
|
||||
data->card_id_len = 10;
|
||||
memcpy(data->card_id, buf + 6, 10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct aimepcsc_context* aimepcsc_create(void) {
|
||||
struct aimepcsc_context* ctx;
|
||||
|
||||
ctx = (struct aimepcsc_context*) malloc(sizeof(struct aimepcsc_context));
|
||||
if (!ctx) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(ctx, 0, sizeof(struct aimepcsc_context));
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void aimepcsc_destroy(struct aimepcsc_context *ctx) {
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
int aimepcsc_init(struct aimepcsc_context *ctx) {
|
||||
LONG ret;
|
||||
|
||||
ret = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &ctx->hContext);
|
||||
|
||||
if (ret != SCARD_S_SUCCESS) {
|
||||
snprintf(ctx->last_error, sizeof(ctx->last_error), "SCardEstablishContext failed: %08lX", (ULONG) ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->pcchReaders = SCARD_AUTOALLOCATE;
|
||||
|
||||
ret = SCardListReaders(ctx->hContext, NULL, (LPSTR) &ctx->mszReaders, &ctx->pcchReaders);
|
||||
|
||||
if (ret != SCARD_S_SUCCESS) {
|
||||
snprintf(ctx->last_error, sizeof(ctx->last_error), "SCardListReaders failed: %08lX", (ULONG) ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
SCardReleaseContext(ctx->hContext);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void aimepcsc_shutdown(struct aimepcsc_context *ctx) {
|
||||
if (ctx->mszReaders != NULL) {
|
||||
SCardFreeMemory(ctx->hContext, ctx->mszReaders);
|
||||
}
|
||||
|
||||
SCardReleaseContext(ctx->hContext);
|
||||
}
|
||||
|
||||
int aimepcsc_poll(struct aimepcsc_context *ctx, struct aime_data *data) {
|
||||
SCARDHANDLE hCard;
|
||||
SCARD_READERSTATE rs;
|
||||
LONG ret;
|
||||
LPBYTE pbAttr = NULL;
|
||||
DWORD cByte = SCARD_AUTOALLOCATE;
|
||||
int retval;
|
||||
|
||||
retval = 1;
|
||||
|
||||
memset(&rs, 0, sizeof(SCARD_READERSTATE));
|
||||
|
||||
rs.szReader = ctx->mszReaders;
|
||||
rs.dwCurrentState = SCARD_STATE_UNAWARE;
|
||||
|
||||
/* check if a card is present */
|
||||
ret = SCardGetStatusChange(ctx->hContext, 0, &rs, 1);
|
||||
|
||||
if (ret == SCARD_E_TIMEOUT) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ret != SCARD_S_SUCCESS) {
|
||||
snprintf(ctx->last_error, sizeof(ctx->last_error), "SCardGetStatusChange failed: %08lX", (ULONG) ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rs.dwEventState & SCARD_STATE_EMPTY) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(rs.dwEventState & SCARD_STATE_PRESENT)) {
|
||||
sprintf(ctx->last_error, "unknown dwCurrentState: %08lX", rs.dwCurrentState);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* connect to card */
|
||||
ret = SCardConnect(ctx->hContext, rs.szReader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, NULL);
|
||||
|
||||
if (ret != SCARD_S_SUCCESS) {
|
||||
snprintf(ctx->last_error, sizeof(ctx->last_error), "SCardConnect failed: %08lX", (ULONG) ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* get ATR string */
|
||||
ret = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, (LPBYTE) &pbAttr, &cByte);
|
||||
|
||||
if (ret != SCARD_S_SUCCESS) {
|
||||
snprintf(ctx->last_error, sizeof(ctx->last_error), "SCardGetAttrib failed: %08lX", (ULONG) ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cByte != 20) {
|
||||
snprintf(ctx->last_error, sizeof(ctx->last_error), "invalid ATR length: %lu", cByte);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* check ATR */
|
||||
if (memcmp(pbAttr, atr_ios14443_common, sizeof(atr_ios14443_common)) != 0) {
|
||||
snprintf(ctx->last_error, sizeof(ctx->last_error), "invalid card type.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* check card type */
|
||||
if (memcmp(pbAttr + sizeof(atr_ios14443_common), cardtype_m1k, sizeof(cardtype_m1k)) == 0) {
|
||||
data->card_type = Mifare;
|
||||
ret = read_m1k_aime(ctx, &hCard, data);
|
||||
if (ret < 0) {
|
||||
retval = -1;
|
||||
goto out;
|
||||
} else if (ret > 0) {
|
||||
goto out;
|
||||
}
|
||||
} else if (memcmp(pbAttr + sizeof(atr_ios14443_common), cardtype_felica, sizeof(cardtype_felica)) == 0) {
|
||||
data->card_type = FeliCa;
|
||||
ret = read_felica_aime(ctx, &hCard, data);
|
||||
if (ret < 0) {
|
||||
retval = -1;
|
||||
goto out;
|
||||
} else if (ret > 0) {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
snprintf(ctx->last_error, sizeof(ctx->last_error), "invalid card type.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
|
||||
out:
|
||||
SCardFreeMemory(ctx->hContext, pbAttr);
|
||||
SCardDisconnect(hCard, SCARD_LEAVE_CARD);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
const char* aimepcsc_error(struct aimepcsc_context *ctx) {
|
||||
return ctx->last_error;
|
||||
}
|
||||
|
||||
const char* aimepcsc_reader_name(struct aimepcsc_context *ctx) {
|
||||
return ctx->mszReaders;
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <winioctl.h>
|
||||
#include <winscard.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* opaque context */
|
||||
struct aimepcsc_context;
|
||||
|
||||
/* aime card types */
|
||||
enum AIME_CARDTYPE {
|
||||
Mifare = 0x01,
|
||||
FeliCa = 0x02,
|
||||
};
|
||||
|
||||
/* aime card data */
|
||||
struct aime_data {
|
||||
/* AIME_CARDTYPE */
|
||||
uint8_t card_type;
|
||||
|
||||
/* Card ID */
|
||||
uint8_t card_id[32];
|
||||
|
||||
/* Card ID length */
|
||||
uint8_t card_id_len;
|
||||
};
|
||||
|
||||
/* create new context for aimepcsc
|
||||
* @return context on success, NULL on failure
|
||||
*/
|
||||
struct aimepcsc_context* aimepcsc_create(void);
|
||||
|
||||
/* destroy context for aimepcsc */
|
||||
void aimepcsc_destroy(struct aimepcsc_context *ctx);
|
||||
|
||||
/* setup reader (first detected reader will be used)
|
||||
* @param ctx context
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int aimepcsc_init(struct aimepcsc_context *ctx);
|
||||
|
||||
/* shutdown reader */
|
||||
void aimepcsc_shutdown(struct aimepcsc_context *ctx);
|
||||
|
||||
/* poll for card
|
||||
* @param ctx context
|
||||
* @param data data to be filled
|
||||
* @return 0 on success, -1 on failure, 1 on no card
|
||||
*/
|
||||
int aimepcsc_poll(struct aimepcsc_context *ctx, struct aime_data *data);
|
||||
|
||||
/* get last error
|
||||
* @param ctx context
|
||||
* @return error string
|
||||
*/
|
||||
const char* aimepcsc_error(struct aimepcsc_context *ctx);
|
||||
|
||||
/* get reader name
|
||||
* @param ctx context
|
||||
* @return reader name
|
||||
*/
|
||||
const char* aimepcsc_reader_name(struct aimepcsc_context *ctx);
|
@ -1,44 +0,0 @@
|
||||
#include "aimepcsc.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
struct aimepcsc_context* ctx;
|
||||
int ret;
|
||||
|
||||
ctx = aimepcsc_create();
|
||||
if (!ctx) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = aimepcsc_init(ctx);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "aimepcsc_init failed: %s\n", aimepcsc_error(ctx));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "connected to reader: %s; waiting for cards...\n", aimepcsc_reader_name(ctx));
|
||||
|
||||
while (1) {
|
||||
struct aime_data data;
|
||||
|
||||
ret = aimepcsc_poll(ctx, &data);
|
||||
if (ret == 0) {
|
||||
printf("card detected: ");
|
||||
printf("type=%s, id=", data.card_type == Mifare ? "Mifare (old Aime)" : "FeliCa (AIC-Aime)");
|
||||
for (int i = 0; i < data.card_id_len; i++) {
|
||||
printf("%02X", data.card_id[i]);
|
||||
}
|
||||
printf("\n");
|
||||
} else if (ret == -1) {
|
||||
fprintf(stderr, "aimepcsc_poll failed: %s\n", aimepcsc_error(ctx));
|
||||
break;
|
||||
}
|
||||
|
||||
Sleep(500);
|
||||
}
|
||||
|
||||
aimepcsc_shutdown(ctx);
|
||||
aimepcsc_destroy(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
winscard_lib = cc.find_library('winscard')
|
||||
|
||||
aimepcsc_lib = static_library(
|
||||
'aimepcsc',
|
||||
name_prefix : '',
|
||||
include_directories: inc,
|
||||
implicit_include_directories : false,
|
||||
dependencies: [winscard_lib],
|
||||
sources : [
|
||||
'aimepcsc.c',
|
||||
],
|
||||
)
|
||||
|
||||
aimereader = executable(
|
||||
'aimereader',
|
||||
name_prefix : '',
|
||||
include_directories : [inc],
|
||||
implicit_include_directories : false,
|
||||
link_with: [aimepcsc_lib],
|
||||
sources : [
|
||||
'aimereader.c'
|
||||
]
|
||||
)
|
9
build64.bat
Normal file
9
build64.bat
Normal file
@ -0,0 +1,9 @@
|
||||
cd /d %~dp0
|
||||
|
||||
REM Edit this with the right path to vcvarsall.bat.
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
|
||||
meson setup build64 --buildtype=release
|
||||
meson configure build64
|
||||
ninja -C build64
|
||||
|
||||
pause
|
34
meson.build
34
meson.build
@ -7,38 +7,4 @@ project(
|
||||
],
|
||||
)
|
||||
|
||||
add_project_arguments(
|
||||
'-DCOBJMACROS',
|
||||
'-DDIRECTINPUT_VERSION=0x0800',
|
||||
'-DWIN32_LEAN_AND_MEAN',
|
||||
'-D_WIN32_WINNT=_WIN32_WINNT_WIN7',
|
||||
'-DMINGW_HAS_SECURE_API=1',
|
||||
'-Wno-unused',
|
||||
language: 'c',
|
||||
)
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
if cc.get_id() != 'msvc'
|
||||
add_project_arguments(
|
||||
'-ffunction-sections',
|
||||
'-fdata-sections',
|
||||
'-flto', # Enable Link-Time Optimization
|
||||
language: 'c',
|
||||
)
|
||||
|
||||
add_project_link_arguments(
|
||||
'-Wl,--enable-stdcall-fixup',
|
||||
'-Wl,--exclude-all-symbols',
|
||||
'-Wl,--gc-sections',
|
||||
'-static-libgcc',
|
||||
'-flto', # Enable Link-Time Optimization
|
||||
'-Wl,-s', # Strip debug symbols
|
||||
language: 'c',
|
||||
)
|
||||
endif
|
||||
|
||||
inc = include_directories('.')
|
||||
|
||||
subdir('aimepcsc')
|
||||
subdir('aimeio')
|
||||
|
Loading…
Reference in New Issue
Block a user