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 <windows.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@ -8,106 +10,262 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include "aimeio/aimeio.h"
|
#include "aimeio.h"
|
||||||
#include "aimepcsc/aimepcsc.h"
|
|
||||||
|
|
||||||
static struct aimepcsc_context *ctx;
|
#define REPORTID_LIGHT_OUTPUT_AIME 0x0A
|
||||||
static struct aime_data data;
|
#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;
|
return 0x0100;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT aime_io_init(void)
|
HRESULT aime_io_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
// VERBOSE_DEBUG("aime_io_init\n");
|
||||||
FILE* fp;
|
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
|
// VERBOSE_DEBUG("Cardio found\n");
|
||||||
if (ret != 0) {
|
/* try to open the HID lights interface (will fail for Hori official, no biggie) */
|
||||||
// only when we allocate a console, we need to redirect stdout
|
// if (hid_open_device(&g_lights_handle, 0x0f0d, 0x00fb, ITF_NUM_LIGHT) != 0)
|
||||||
freopen_s(&fp, "CONOUT$", "w", stdout);
|
// {
|
||||||
|
// 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();
|
aime_io_poll_thread = (HANDLE)_beginthreadex(
|
||||||
if (!ctx) {
|
NULL,
|
||||||
return E_OUTOFMEMORY;
|
0,
|
||||||
}
|
aime_io_poll_thread_proc,
|
||||||
|
NULL,
|
||||||
ret = aimepcsc_init(ctx);
|
0,
|
||||||
|
NULL);
|
||||||
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));
|
|
||||||
|
|
||||||
|
// VERBOSE_DEBUG("init ok\n");
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT aime_io_nfc_poll(uint8_t unit_no)
|
HRESULT aime_io_nfc_poll(uint8_t unit_no)
|
||||||
{
|
{
|
||||||
int ret;
|
// VERBOSE_DEBUG("aime_io_nfc_poll\n");
|
||||||
HRESULT hr;
|
// bool sense;
|
||||||
|
// HRESULT hr;
|
||||||
|
|
||||||
if (unit_no != 0) {
|
// if (unit_no != 0)
|
||||||
return S_OK;
|
// {
|
||||||
}
|
// 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) {
|
// hr = aime_io_read_id_file(
|
||||||
printf("aimeio-pcsc: poll failed: %s\n", aimepcsc_error(ctx));
|
// 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;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT aime_io_nfc_get_aime_id(
|
HRESULT aime_io_nfc_get_aime_id(uint8_t unit_no, uint8_t *luid, size_t luid_size)
|
||||||
uint8_t unit_no,
|
|
||||||
uint8_t *luid,
|
|
||||||
size_t luid_size)
|
|
||||||
{
|
{
|
||||||
assert(luid != NULL);
|
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;
|
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_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT aime_io_nfc_get_felica_id(uint8_t unit_no, uint64_t *IDm)
|
HRESULT aime_io_nfc_get_felica_id(uint8_t unit_no, uint64_t *IDm)
|
||||||
{
|
{
|
||||||
uint64_t val;
|
uint64_t val;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
assert(IDm != NULL);
|
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;
|
return S_FALSE;
|
||||||
}
|
|
||||||
|
|
||||||
|
if (aime_io_felica_id_present)
|
||||||
|
{
|
||||||
|
// VERBOSE_DEBUG("Found FeliCa present from conf\n");
|
||||||
val = 0;
|
val = 0;
|
||||||
|
|
||||||
for (i = 0 ; i < 8 ; i++) {
|
for (i = 0; i < 8; i++)
|
||||||
val = (val << 8) | data.card_id[i];
|
{
|
||||||
|
val = (val << 8) | aime_io_felica_id[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
*IDm = val;
|
*IDm = val;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void aime_io_led_set_color(uint8_t unit_no, uint8_t r, uint8_t g, uint8_t b)
|
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) {}
|
@ -4,6 +4,6 @@ EXPORTS
|
|||||||
aime_io_get_api_version
|
aime_io_get_api_version
|
||||||
aime_io_init
|
aime_io_init
|
||||||
aime_io_led_set_color
|
aime_io_led_set_color
|
||||||
|
aime_io_nfc_poll
|
||||||
aime_io_nfc_get_aime_id
|
aime_io_nfc_get_aime_id
|
||||||
aime_io_nfc_get_felica_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 <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/*
|
/* THIS API IS UNSTABLE. Please do not build alternative implementations of
|
||||||
Get the version of the Aime IO API that this DLL supports. This function
|
this DLL just yet unless you are prepared to deal with API breakages. */
|
||||||
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);
|
HRESULT aime_io_init(void);
|
||||||
|
void aime_io_fini(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);
|
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(
|
HRESULT aime_io_nfc_get_aime_id(
|
||||||
uint8_t unit_no,
|
uint8_t unit_no,
|
||||||
uint8_t *luid,
|
uint8_t *luid,
|
||||||
size_t luid_size);
|
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);
|
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);
|
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',
|
'aimeio',
|
||||||
name_prefix : '',
|
|
||||||
include_directories: inc,
|
|
||||||
implicit_include_directories : false,
|
implicit_include_directories : false,
|
||||||
vs_module_defs : 'aimeio.def',
|
vs_module_defs : 'aimeio.def',
|
||||||
link_with: [aimepcsc_lib],
|
|
||||||
sources: [
|
sources: [
|
||||||
'aimeio.c',
|
'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')
|
subdir('aimeio')
|
||||||
|
Loading…
Reference in New Issue
Block a user