mirror of
https://github.com/djhackersdev/bemanitools.git
synced 2026-09-07 16:05:09 -05:00
Merge e1e47ee7c4 into 5ae0b17517
This commit is contained in:
@@ -116,12 +116,17 @@ FONT 8, "Ms Shell Dlg"
|
||||
{
|
||||
LTEXT "Keyboard device", IDC_STATIC, 15, 20, 54, 8, SS_LEFT
|
||||
COMBOBOX IDC_KBD_DEVICE, 15, 30, 135, 12, WS_GROUP | WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS
|
||||
LTEXT "Card ID file", IDC_STATIC, 15, 50, 36, 8, SS_LEFT
|
||||
EDITTEXT IDC_CARD_PATH, 15, 60, 135, 14, ES_AUTOHSCROLL
|
||||
PUSHBUTTON "&Browse...", IDC_BROWSE, 155, 60, 50, 14
|
||||
AUTOCHECKBOX "Use top keyboard row for PIN pad input", IDC_ALT_10K, 15, 47, 136, 8
|
||||
LTEXT "Card ID file", IDC_CARD_TEXT, 15, 60, 36, 8, SS_LEFT
|
||||
EDITTEXT IDC_CARD_PATH, 15, 70, 135, 14, ES_AUTOHSCROLL
|
||||
PUSHBUTTON "&Browse...", IDC_BROWSE, 155, 70, 50, 14
|
||||
LTEXT "Smartcard reader", IDC_SCARD_TEXT, 15, 60, 80, 8, SS_LEFT
|
||||
LTEXT "", IDC_SCARD_READER_NAME, 15, 72, 135, 14, SS_LEFT
|
||||
GROUPBOX "", IDC_GROUP, 5, 5, 210, 80
|
||||
LTEXT "Keypad status", IDC_STATIC, 155, 20, 46, 8, SS_LEFT
|
||||
LTEXT "", IDC_KEYPAD_STATE, 160, 30, 45, 12, SS_LEFT | SS_CENTERIMAGE
|
||||
LTEXT "Card present", IDC_SCARD_CARD_TEXT, 155, 60, 46, 8, SS_LEFT
|
||||
LTEXT "", IDC_SCARD_IS_PRESENT, 160, 70, 45, 12, SS_LEFT | SS_CENTERIMAGE
|
||||
}
|
||||
|
||||
|
||||
@@ -170,14 +175,15 @@ FONT 8, "Ms Shell Dlg"
|
||||
|
||||
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
IDD_TAB_NETWORK DIALOG 0, 0, 220, 215
|
||||
IDD_TAB_NETWORK DIALOG 0, 0, 220, 240
|
||||
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
|
||||
CAPTION "Network"
|
||||
FONT 8, "Ms Shell Dlg"
|
||||
{
|
||||
LTEXT "", IDC_STATIC, 0, 0, 8, 8, SS_LEFT
|
||||
AUTOCHECKBOX "Generate card ID files on insertion if they do not already exist", IDC_AUTOGEN, 5, 200, 206, 8
|
||||
AUTOCHECKBOX "Use top keyboard row for PIN pad input", IDC_ALT_10K, 5, 185, 141, 8
|
||||
AUTOCHECKBOX "Use smartcard readers instead of card ID files", IDC_SCARD, 5, 5, 200, 8
|
||||
AUTOCHECKBOX "Use NUMLOCK to deconflict overlapping keypads (ON = P2)", IDC_MUX_KEYPAD, 5, 200, 265, 8
|
||||
AUTOCHECKBOX "Use NUMLOCK to share one smartcard reader (ON = P2)", IDC_MUX_SCARD, 5, 212, 265, 8
|
||||
AUTOCHECKBOX "Generate card ID files on insertion if they do not already exist", IDC_AUTOGEN, 5, 224, 265, 8
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -56,9 +56,14 @@ static INT_PTR eam_ui_handle_init(HWND hwnd, const PROPSHEETPAGE *psp);
|
||||
static INT_PTR eam_ui_handle_activate(HWND hwnd);
|
||||
static INT_PTR eam_ui_handle_passivate(HWND hwnd);
|
||||
static INT_PTR eam_ui_handle_tick(HWND hwnd);
|
||||
static INT_PTR eam_ui_handle_change_alt_10k(HWND hwnd);
|
||||
static INT_PTR eam_ui_handle_change_scard(HWND hwnd);
|
||||
static INT_PTR eam_ui_handle_change_mux_keypad(HWND hwnd);
|
||||
static INT_PTR eam_ui_handle_change_mux_scard(HWND hwnd);
|
||||
static INT_PTR eam_ui_handle_change_autogen(HWND hwnd);
|
||||
static INT_PTR eam_ui_handle_fini(HWND hwnd);
|
||||
static HWND eam_mux_keypad_dlg;
|
||||
static HWND *eam_unit_dlgs;
|
||||
static uint8_t eam_num_units;
|
||||
|
||||
static INT_PTR CALLBACK
|
||||
eam_unit_ui_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
@@ -66,8 +71,10 @@ static INT_PTR
|
||||
eam_unit_ui_handle_init(HWND hwnd, const struct eam_unit_def *def);
|
||||
static void eam_unit_ui_handle_init_devs(HWND hwnd);
|
||||
static void eam_unit_ui_handle_init_path(HWND hwnd);
|
||||
static void eam_unit_ui_handle_init_alt_10k(HWND hwnd);
|
||||
static INT_PTR eam_unit_ui_handle_browse(HWND hwnd);
|
||||
static INT_PTR eam_unit_ui_handle_change_device(HWND hwnd);
|
||||
static INT_PTR eam_unit_ui_handle_change_alt_10k(HWND hwnd);
|
||||
static INT_PTR eam_unit_ui_handle_tick(HWND hwnd);
|
||||
static INT_PTR eam_unit_ui_handle_fini(HWND hwnd);
|
||||
|
||||
@@ -110,12 +117,18 @@ eam_ui_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
switch (HIWORD(wparam)) {
|
||||
case BN_CLICKED:
|
||||
switch (LOWORD(wparam)) {
|
||||
case IDC_SCARD:
|
||||
return eam_ui_handle_change_scard(hwnd);
|
||||
|
||||
case IDC_MUX_KEYPAD:
|
||||
return eam_ui_handle_change_mux_keypad(hwnd);
|
||||
|
||||
case IDC_MUX_SCARD:
|
||||
return eam_ui_handle_change_mux_scard(hwnd);
|
||||
|
||||
case IDC_AUTOGEN:
|
||||
return eam_ui_handle_change_autogen(hwnd);
|
||||
|
||||
case IDC_ALT_10K:
|
||||
return eam_ui_handle_change_alt_10k(hwnd);
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
@@ -163,8 +176,16 @@ static INT_PTR eam_ui_handle_init(HWND hwnd, const PROPSHEETPAGE *psp)
|
||||
inst = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
|
||||
schema = (struct schema *) psp->lParam;
|
||||
|
||||
ypos = 0;
|
||||
eam_unit_dlgs = xmalloc(sizeof(HWND) * schema->nunits);
|
||||
eam_num_units = schema->nunits;
|
||||
|
||||
GetWindowRect(GetDlgItem(hwnd, IDC_SCARD), &r);
|
||||
if (eam_io_config_api->get_scard()) {
|
||||
SendMessage(GetDlgItem(hwnd, IDC_SCARD), BM_SETCHECK, BST_CHECKED, 0);
|
||||
}
|
||||
|
||||
ypos = r.bottom - r.top + 8; // todo the +8 is hacky bc the bottom is hella big
|
||||
|
||||
for (i = 0; i < schema->nunits; i++) {
|
||||
child = CreateDialogParam(
|
||||
inst,
|
||||
@@ -172,6 +193,7 @@ static INT_PTR eam_ui_handle_init(HWND hwnd, const PROPSHEETPAGE *psp)
|
||||
hwnd,
|
||||
eam_unit_ui_dlg_proc,
|
||||
(LPARAM) &schema->units[i]);
|
||||
eam_unit_dlgs[i] = child;
|
||||
|
||||
GetWindowRect(child, &r);
|
||||
SetWindowPos(
|
||||
@@ -182,14 +204,30 @@ static INT_PTR eam_ui_handle_init(HWND hwnd, const PROPSHEETPAGE *psp)
|
||||
*array_append(HWND, &ui->children) = child;
|
||||
}
|
||||
|
||||
eam_mux_keypad_dlg = GetDlgItem(hwnd, IDC_MUX_KEYPAD);
|
||||
if (eam_io_config_api->get_mux_keypad()) {
|
||||
SendMessage(eam_mux_keypad_dlg, BM_SETCHECK, BST_CHECKED, 0);
|
||||
}
|
||||
|
||||
if (eam_io_config_api->get_mux_scard()) {
|
||||
SendMessage(GetDlgItem(hwnd, IDC_MUX_SCARD), BM_SETCHECK, BST_CHECKED, 0);
|
||||
}
|
||||
|
||||
if (eam_io_config_api->get_autogen()) {
|
||||
SendMessage(GetDlgItem(hwnd, IDC_AUTOGEN), BM_SETCHECK, BST_CHECKED, 0);
|
||||
}
|
||||
|
||||
if (eam_io_config_api->get_alt_10k()) {
|
||||
SendMessage(GetDlgItem(hwnd, IDC_ALT_10K), BM_SETCHECK, BST_CHECKED, 0);
|
||||
}
|
||||
// invoke scard change handler so we can toggle card file / smartcard stuff
|
||||
eam_ui_handle_change_scard(hwnd);
|
||||
// invoke a keypad-related change handler so the keypad mux option updates
|
||||
eam_unit_ui_handle_change_alt_10k(eam_unit_dlgs[0]);
|
||||
|
||||
// if only one reader is present, disablo mux options
|
||||
if (schema->nunits == 1) {
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_MUX_KEYPAD), false);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_MUX_SCARD), false);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -225,15 +263,68 @@ static INT_PTR eam_ui_handle_tick(HWND hwnd)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR eam_ui_handle_change_alt_10k(HWND hwnd)
|
||||
static INT_PTR eam_ui_handle_change_scard(HWND hwnd)
|
||||
{
|
||||
HWND btn;
|
||||
bool alt_10k;
|
||||
bool scard;
|
||||
size_t i;
|
||||
|
||||
btn = GetDlgItem(hwnd, IDC_ALT_10K);
|
||||
alt_10k = SendMessage(btn, BM_GETCHECK, 0, 0) == BST_CHECKED;
|
||||
btn = GetDlgItem(hwnd, IDC_SCARD);
|
||||
scard = SendMessage(btn, BM_GETCHECK, 0, 0) == BST_CHECKED;
|
||||
|
||||
eam_io_config_api->set_alt_10k(alt_10k);
|
||||
eam_io_config_api->set_scard(scard);
|
||||
|
||||
// toggle state of card file vs scard components
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_AUTOGEN), !scard);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_MUX_SCARD), scard);
|
||||
for (i = 0; i < eam_num_units; i++) {
|
||||
ShowWindow(GetDlgItem(eam_unit_dlgs[i], IDC_CARD_TEXT), !scard);
|
||||
ShowWindow(GetDlgItem(eam_unit_dlgs[i], IDC_CARD_PATH), !scard);
|
||||
ShowWindow(GetDlgItem(eam_unit_dlgs[i], IDC_BROWSE), !scard);
|
||||
ShowWindow(GetDlgItem(eam_unit_dlgs[i], IDC_SCARD_TEXT), scard);
|
||||
ShowWindow(GetDlgItem(eam_unit_dlgs[i], IDC_SCARD_READER_NAME), scard);
|
||||
ShowWindow(GetDlgItem(eam_unit_dlgs[i], IDC_SCARD_CARD_TEXT), scard);
|
||||
ShowWindow(GetDlgItem(eam_unit_dlgs[i], IDC_SCARD_IS_PRESENT), scard);
|
||||
|
||||
if (scard) {
|
||||
SetWindowTextA(
|
||||
GetDlgItem(eam_unit_dlgs[i], IDC_SCARD_READER_NAME),
|
||||
eam_io_config_api->get_scard_reader_name(i));
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR eam_ui_handle_change_mux_keypad(HWND hwnd)
|
||||
{
|
||||
HWND btn;
|
||||
bool mux_keypad;
|
||||
|
||||
btn = GetDlgItem(hwnd, IDC_MUX_KEYPAD);
|
||||
mux_keypad = SendMessage(btn, BM_GETCHECK, 0, 0) == BST_CHECKED;
|
||||
|
||||
eam_io_config_api->set_mux_keypad(mux_keypad);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR eam_ui_handle_change_mux_scard(HWND hwnd)
|
||||
{
|
||||
HWND btn;
|
||||
bool mux_scard;
|
||||
size_t i;
|
||||
|
||||
btn = GetDlgItem(hwnd, IDC_MUX_SCARD);
|
||||
mux_scard = SendMessage(btn, BM_GETCHECK, 0, 0) == BST_CHECKED;
|
||||
|
||||
eam_io_config_api->set_mux_scard(mux_scard);
|
||||
|
||||
for (i = 0; i < eam_num_units; i++) {
|
||||
SetWindowTextA(
|
||||
GetDlgItem(eam_unit_dlgs[i], IDC_SCARD_READER_NAME),
|
||||
eam_io_config_api->get_scard_reader_name(i));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -294,6 +385,15 @@ eam_unit_ui_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
case IDC_ALT_10K:
|
||||
switch (HIWORD(wparam)) {
|
||||
case BN_CLICKED:
|
||||
return eam_unit_ui_handle_change_alt_10k(hwnd);
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
@@ -326,6 +426,7 @@ eam_unit_ui_handle_init(HWND hwnd, const struct eam_unit_def *def)
|
||||
|
||||
eam_unit_ui_handle_init_devs(hwnd);
|
||||
eam_unit_ui_handle_init_path(hwnd);
|
||||
eam_unit_ui_handle_init_alt_10k(hwnd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -401,6 +502,17 @@ static void eam_unit_ui_handle_init_path(HWND hwnd)
|
||||
}
|
||||
}
|
||||
|
||||
static void eam_unit_ui_handle_init_alt_10k(HWND hwnd)
|
||||
{
|
||||
struct eam_unit_ui *ui;
|
||||
|
||||
ui = (struct eam_unit_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
if (eam_io_config_api->get_alt_10k(ui->def->unit_no)) {
|
||||
SendMessage(GetDlgItem(hwnd, IDC_ALT_10K), BM_SETCHECK, BST_CHECKED, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static INT_PTR eam_unit_ui_handle_browse(HWND hwnd)
|
||||
{
|
||||
struct eam_unit_ui *ui;
|
||||
@@ -451,6 +563,28 @@ static INT_PTR eam_unit_ui_handle_change_device(HWND hwnd)
|
||||
eam_io_config_api->set_keypad_device(ui->def->unit_no, hid);
|
||||
}
|
||||
|
||||
// enable the keypad mux option if the devices/keys conflict
|
||||
EnableWindow(eam_mux_keypad_dlg, eam_io_config_api->do_keypads_conflict());
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR eam_unit_ui_handle_change_alt_10k(HWND hwnd)
|
||||
{
|
||||
struct eam_unit_ui *ui;
|
||||
HWND btn;
|
||||
bool alt_10k;
|
||||
|
||||
ui = (struct eam_unit_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
btn = GetDlgItem(hwnd, IDC_ALT_10K);
|
||||
alt_10k = SendMessage(btn, BM_GETCHECK, 0, 0) == BST_CHECKED;
|
||||
|
||||
eam_io_config_api->set_alt_10k(ui->def->unit_no, alt_10k);
|
||||
|
||||
// enable the keypad mux option if the devices/keys conflict
|
||||
EnableWindow(eam_mux_keypad_dlg, eam_io_config_api->do_keypads_conflict());
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -459,14 +593,28 @@ static INT_PTR eam_unit_ui_handle_tick(HWND hwnd)
|
||||
struct eam_unit_ui *ui;
|
||||
uint16_t state;
|
||||
wchar_t state_str[9];
|
||||
bool card_present;
|
||||
|
||||
// keypad state
|
||||
ui = (struct eam_unit_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
state = eam_io_get_keypad_state(ui->def->unit_no);
|
||||
|
||||
wstr_format(state_str, lengthof(state_str), L"%04x", state);
|
||||
|
||||
SetWindowText(GetDlgItem(hwnd, IDC_KEYPAD_STATE), state_str);
|
||||
|
||||
// smartcard state
|
||||
if (eam_io_config_api->get_scard()) {
|
||||
|
||||
eam_io_poll(ui->def->unit_no);
|
||||
|
||||
card_present = eam_io_get_sensor_state(ui->def->unit_no);
|
||||
|
||||
SetWindowText(
|
||||
GetDlgItem(hwnd, IDC_SCARD_IS_PRESENT),
|
||||
(card_present ? L"YES" : L"NO"));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#define IDC_LIGHT 1001
|
||||
#define IDC_SENSITIVITY 1001
|
||||
#define IDC_ACTION_NAME 1002
|
||||
#define IDC_ALT_10K 1002
|
||||
#define IDC_KEYPAD_STATE 1002
|
||||
#define IDC_GAME_TYPE 1003
|
||||
#define IDC_GROUP 1003
|
||||
@@ -39,6 +38,15 @@
|
||||
#define IDC_BINDING_MAX 1010
|
||||
#define IDC_LIMIT_MAX 1011
|
||||
#define IDC_CURRENT 1013
|
||||
#define IDC_SCARD 1014
|
||||
#define IDC_ALT_10K 1015
|
||||
#define IDC_MUX_KEYPAD 1016
|
||||
#define IDC_MUX_SCARD 1017
|
||||
#define IDC_CARD_TEXT 1018
|
||||
#define IDC_SCARD_TEXT 1019
|
||||
#define IDC_SCARD_READER_NAME 1020
|
||||
#define IDC_SCARD_CARD_TEXT 1021
|
||||
#define IDC_SCARD_IS_PRESENT 1022
|
||||
#define IDC_BINDING_EDIT_MANY 40000
|
||||
#define IDS_APPNAME 40000
|
||||
#define IDS_BAD_GAME_TYPE 40001
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
dlls += eamio
|
||||
libs_eamio := geninput util
|
||||
ldflags_eamio := -lwinscard
|
||||
src_eamio := \
|
||||
eam-api.c \
|
||||
eam-impl.c \
|
||||
eam-s11n.c \
|
||||
eam-scard.c
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "eamio/eam-config.h"
|
||||
#include "eamio/eam-impl.h"
|
||||
#include "eamio/eam-s11n.h"
|
||||
#include "eamio/eam-scard.h"
|
||||
|
||||
#include "util/fs.h"
|
||||
#include "util/log.h"
|
||||
@@ -24,10 +25,17 @@ static void eam_handle_hotplug_msg(WPARAM wparam, const DEV_BROADCAST_HDR *hdr);
|
||||
static FILE *eam_io_config_open(const char *mode);
|
||||
static void eam_io_config_load(void);
|
||||
static void eam_io_config_save(void);
|
||||
static bool eam_io_get_scard(void);
|
||||
static void eam_io_set_scard(bool scard);
|
||||
static bool eam_io_get_mux_keypad(void);
|
||||
static void eam_io_set_mux_keypad(bool mux_keypad);
|
||||
static bool eam_io_get_mux_scard(void);
|
||||
static void eam_io_set_mux_scard(bool mux_scard);
|
||||
static bool eam_io_get_autogen(void);
|
||||
static void eam_io_set_autogen(bool autogen);
|
||||
static bool eam_io_get_alt_10k(void);
|
||||
static void eam_io_set_alt_10k(bool alt_10k);
|
||||
static bool eam_io_do_keypads_conflict(void);
|
||||
static bool eam_io_get_alt_10k(uint8_t unit_no);
|
||||
static void eam_io_set_alt_10k(uint8_t unit_no, bool alt_10k);
|
||||
static struct hid_stub *eam_io_get_keypad_device(uint8_t unit_no);
|
||||
static void eam_io_set_keypad_device(uint8_t unit_no, struct hid_stub *hid);
|
||||
static const char *eam_io_get_card_path(uint8_t unit_no);
|
||||
@@ -46,6 +54,14 @@ static const struct eam_io_config_api eam_io_config_api = {
|
||||
.set_keypad_device = eam_io_set_keypad_device,
|
||||
.get_card_path = eam_io_get_card_path,
|
||||
.set_card_path = eam_io_set_card_path,
|
||||
.get_scard = eam_io_get_scard,
|
||||
.set_scard = eam_io_set_scard,
|
||||
.get_mux_keypad = eam_io_get_mux_keypad,
|
||||
.set_mux_keypad = eam_io_set_mux_keypad,
|
||||
.get_mux_scard = eam_io_get_mux_scard,
|
||||
.set_mux_scard = eam_io_set_mux_scard,
|
||||
.do_keypads_conflict = eam_io_do_keypads_conflict,
|
||||
.get_scard_reader_name = eam_scard_get_reader_name,
|
||||
};
|
||||
|
||||
void msg_window_setup(HWND hwnd)
|
||||
@@ -99,7 +115,7 @@ void msg_window_teardown(HWND hwnd)
|
||||
|
||||
static FILE *eam_io_config_open(const char *mode)
|
||||
{
|
||||
return fopen_appdata("DJHACKERS", "eam_v4_22.bin", mode);
|
||||
return fopen_appdata("DJHACKERS", "eam_v5_49a.bin", mode);
|
||||
}
|
||||
|
||||
void eam_io_set_loggers(
|
||||
@@ -161,6 +177,7 @@ void eam_io_fini(void)
|
||||
msg_thread_fini();
|
||||
eam_impl_destroy(eam_inst);
|
||||
input_fini();
|
||||
eam_scard_fini();
|
||||
}
|
||||
|
||||
const struct eam_io_config_api *eam_io_get_config_api(void)
|
||||
@@ -182,6 +199,36 @@ static void eam_io_config_save(void)
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
static bool eam_io_get_scard(void)
|
||||
{
|
||||
return eam_impl_get_scard(eam_inst);
|
||||
}
|
||||
|
||||
static void eam_io_set_scard(bool scard)
|
||||
{
|
||||
eam_impl_set_scard(eam_inst, scard);
|
||||
}
|
||||
|
||||
static bool eam_io_get_mux_keypad(void)
|
||||
{
|
||||
return eam_impl_get_mux_keypad(eam_inst);
|
||||
}
|
||||
|
||||
static void eam_io_set_mux_keypad(bool mux_keypad)
|
||||
{
|
||||
eam_impl_set_mux_keypad(eam_inst, mux_keypad);
|
||||
}
|
||||
|
||||
static bool eam_io_get_mux_scard(void)
|
||||
{
|
||||
return eam_impl_get_mux_scard(eam_inst);
|
||||
}
|
||||
|
||||
static void eam_io_set_mux_scard(bool mux_scard)
|
||||
{
|
||||
eam_impl_set_mux_scard(eam_inst, mux_scard);
|
||||
}
|
||||
|
||||
static bool eam_io_get_autogen(void)
|
||||
{
|
||||
return eam_impl_get_autogen(eam_inst);
|
||||
@@ -192,14 +239,19 @@ static void eam_io_set_autogen(bool autogen)
|
||||
eam_impl_set_autogen(eam_inst, autogen);
|
||||
}
|
||||
|
||||
static bool eam_io_get_alt_10k(void)
|
||||
static bool eam_io_do_keypads_conflict(void)
|
||||
{
|
||||
return eam_impl_get_alt_10k(eam_inst);
|
||||
return eam_impl_do_keypads_conflict(eam_inst);
|
||||
}
|
||||
|
||||
static void eam_io_set_alt_10k(bool alt_10k)
|
||||
static bool eam_io_get_alt_10k(uint8_t unit_no)
|
||||
{
|
||||
eam_impl_set_alt_10k(eam_inst, alt_10k);
|
||||
return eam_impl_get_alt_10k(eam_inst, unit_no);
|
||||
}
|
||||
|
||||
static void eam_io_set_alt_10k(uint8_t unit_no, bool alt_10k)
|
||||
{
|
||||
eam_impl_set_alt_10k(eam_inst, unit_no, alt_10k);
|
||||
}
|
||||
|
||||
static struct hid_stub *eam_io_get_keypad_device(uint8_t unit_no)
|
||||
@@ -229,16 +281,28 @@ uint16_t eam_io_get_keypad_state(uint8_t unit_no)
|
||||
|
||||
uint8_t eam_io_get_sensor_state(uint8_t unit_no)
|
||||
{
|
||||
if (eam_impl_get_sensor_state(eam_inst, unit_no)) {
|
||||
bool has_card;
|
||||
|
||||
if (eam_io_get_scard()) {
|
||||
has_card = eam_scard_is_present(unit_no);
|
||||
} else {
|
||||
has_card = eam_impl_get_sensor_state(eam_inst, unit_no);
|
||||
}
|
||||
|
||||
if (has_card) {
|
||||
return (1 << EAM_IO_SENSOR_FRONT) | (1 << EAM_IO_SENSOR_BACK);
|
||||
} else {
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t eam_io_read_card(uint8_t unit_no, uint8_t *card_id, uint8_t nbytes)
|
||||
{
|
||||
return eam_impl_read_card(eam_inst, unit_no, card_id, nbytes);
|
||||
if (eam_io_get_scard()) {
|
||||
return eam_scard_read(unit_no, card_id, nbytes);
|
||||
} else {
|
||||
return eam_impl_read_card(eam_inst, unit_no, card_id, nbytes);
|
||||
}
|
||||
}
|
||||
|
||||
bool eam_io_card_slot_cmd(uint8_t unit_no, uint8_t cmd)
|
||||
@@ -249,11 +313,14 @@ bool eam_io_card_slot_cmd(uint8_t unit_no, uint8_t cmd)
|
||||
|
||||
bool eam_io_poll(uint8_t unit_no)
|
||||
{
|
||||
// ignored
|
||||
if (eam_io_get_scard()) {
|
||||
eam_scard_poll(unit_no);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *ctx)
|
||||
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *scard)
|
||||
{
|
||||
if (reason == DLL_PROCESS_ATTACH) {
|
||||
eam_hinst = hinst;
|
||||
|
||||
@@ -7,12 +7,21 @@ struct eam_io_config_api {
|
||||
void (*config_save)(void);
|
||||
bool (*get_autogen)(void);
|
||||
void (*set_autogen)(bool autogen);
|
||||
bool (*get_alt_10k)(void);
|
||||
void (*set_alt_10k)(bool alt_10k);
|
||||
bool (*get_alt_10k)(uint8_t unit_no);
|
||||
void (*set_alt_10k)(uint8_t unit_no, bool alt_10k);
|
||||
struct hid_stub *(*get_keypad_device)(uint8_t unit_no);
|
||||
void (*set_keypad_device)(uint8_t unit_no, struct hid_stub *hid);
|
||||
const char *(*get_card_path)(uint8_t unit_no);
|
||||
void (*set_card_path)(uint8_t unit_no, const char *path);
|
||||
bool (*get_scard)(void);
|
||||
void (*set_scard)(bool scard);
|
||||
bool (*get_mux_keypad)(void);
|
||||
void (*set_mux_keypad)(bool mux_keypad);
|
||||
bool (*get_mux_scard)(void);
|
||||
void (*set_mux_scard)(bool mux_scard);
|
||||
|
||||
bool (*do_keypads_conflict)(void);
|
||||
LPSTR (*get_scard_reader_name)(uint8_t unit_no);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,8 +10,10 @@
|
||||
#include "bemanitools/eamio.h"
|
||||
|
||||
#include "eamio/eam-impl.h"
|
||||
#include "eamio/eam-scard.h"
|
||||
|
||||
#include "geninput/hid-mgr.h"
|
||||
#include "geninput/kbd-naive.h"
|
||||
|
||||
#include "util/defs.h"
|
||||
#include "util/fs.h"
|
||||
@@ -31,6 +33,7 @@ struct eam_unit {
|
||||
uint8_t drive_no;
|
||||
uint32_t sensor_time;
|
||||
bool sensor_hot;
|
||||
bool alt_10k;
|
||||
};
|
||||
|
||||
struct eam {
|
||||
@@ -41,8 +44,9 @@ struct eam {
|
||||
CRITICAL_SECTION lock;
|
||||
struct eam_unit units[EAM_UNIT_COUNT];
|
||||
bool autogen;
|
||||
bool alt_10k;
|
||||
bool mux;
|
||||
bool scard;
|
||||
bool mux_keypad;
|
||||
bool mux_scard;
|
||||
};
|
||||
|
||||
static const uint32_t eam_keypad_usages[EAM_IO_KEYPAD_COUNT + 1] = {
|
||||
@@ -76,7 +80,7 @@ static const uint32_t eam_keypad_usages_alt[EAM_IO_KEYPAD_COUNT + 1] = {
|
||||
/* Sensor = */ 0x0007002A /* Backspace */
|
||||
};
|
||||
|
||||
static uint8_t eam_impl_get_active_unit(void);
|
||||
static bool eam_impl_is_active_unit(struct eam *eam, uint8_t unit_no);
|
||||
static void eam_impl_bind_keypad(struct eam *eam, uint8_t unit_no);
|
||||
static bool eam_impl_autogen(struct eam_unit *unit, uint8_t *card_id);
|
||||
|
||||
@@ -96,6 +100,7 @@ struct eam *eam_impl_create(void)
|
||||
|
||||
unit->card_path = NULL;
|
||||
unit->hid = NULL;
|
||||
unit->alt_10k = false;
|
||||
|
||||
for (btn_no = 0; btn_no < lengthof(unit->keypad_ctls); btn_no++) {
|
||||
unit->keypad_ctls[btn_no] = (size_t) -1;
|
||||
@@ -108,15 +113,62 @@ struct eam *eam_impl_create(void)
|
||||
}
|
||||
|
||||
eam->autogen = false;
|
||||
eam->alt_10k = false;
|
||||
eam->mux = false;
|
||||
eam->scard = false;
|
||||
eam->mux_keypad = false;
|
||||
eam->mux_scard = false;
|
||||
|
||||
return eam;
|
||||
}
|
||||
|
||||
static uint8_t eam_impl_get_active_unit(void)
|
||||
static bool eam_impl_is_active_unit(struct eam *eam, uint8_t unit_no)
|
||||
{
|
||||
return GetKeyState(VK_NUMLOCK) & 0x0001;
|
||||
log_assert(lengthof(eam->units) == 2);
|
||||
|
||||
if (eam->mux_keypad && eam_impl_do_keypads_conflict(eam)) {
|
||||
// Determine active unit by numlock state
|
||||
return (GetKeyState(VK_NUMLOCK) & 0x0001) == unit_no;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool eam_impl_get_scard(struct eam *eam)
|
||||
{
|
||||
return eam->scard;
|
||||
}
|
||||
void eam_impl_set_scard(struct eam *eam, bool scard)
|
||||
{
|
||||
eam->scard = scard != false;
|
||||
|
||||
if (eam->scard) {
|
||||
eam_scard_init(eam->mux_scard);
|
||||
} else {
|
||||
eam_scard_fini();
|
||||
}
|
||||
}
|
||||
|
||||
bool eam_impl_get_mux_keypad(struct eam *eam)
|
||||
{
|
||||
return eam->mux_keypad;
|
||||
}
|
||||
void eam_impl_set_mux_keypad(struct eam *eam, bool mux_keypad)
|
||||
{
|
||||
eam->mux_keypad = mux_keypad != false;
|
||||
}
|
||||
|
||||
bool eam_impl_get_mux_scard(struct eam *eam)
|
||||
{
|
||||
return eam->mux_scard;
|
||||
}
|
||||
void eam_impl_set_mux_scard(struct eam *eam, bool mux_scard)
|
||||
{
|
||||
eam->mux_scard = mux_scard != false;
|
||||
|
||||
if (eam->scard) {
|
||||
// reinit so we can remap the readers
|
||||
eam_scard_fini();
|
||||
eam_scard_init(eam->mux_scard);
|
||||
}
|
||||
}
|
||||
|
||||
bool eam_impl_get_autogen(struct eam *eam)
|
||||
@@ -129,20 +181,40 @@ void eam_impl_set_autogen(struct eam *eam, bool autogen)
|
||||
eam->autogen = autogen != false;
|
||||
}
|
||||
|
||||
bool eam_impl_get_alt_10k(struct eam *eam)
|
||||
bool eam_impl_do_keypads_conflict(struct eam *eam)
|
||||
{
|
||||
return eam->alt_10k;
|
||||
}
|
||||
log_assert(lengthof(eam->units) == 2);
|
||||
|
||||
void eam_impl_set_alt_10k(struct eam *eam, bool alt_10k)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < lengthof(eam->units); i++) {
|
||||
eam->units[i].bound_ctls = false;
|
||||
// 1. To conflict, both must have an assigned hid device
|
||||
if (eam->units[0].hid == NULL || eam->units[1].hid == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
eam->alt_10k = alt_10k != false;
|
||||
// 2. To conflict, both must use the same keys (i.e. numpad vs top row)
|
||||
if (eam->units[0].alt_10k != eam->units[1].alt_10k) {
|
||||
// keypads are not using the same keys. mux not necessary
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. To conflict, the hids must be the same or either be the naive kbd
|
||||
return (eam->units[0].hid == eam->units[1].hid ||
|
||||
kbd_is_naive(eam->units[0].hid) ||
|
||||
kbd_is_naive(eam->units[1].hid));
|
||||
}
|
||||
|
||||
bool eam_impl_get_alt_10k(struct eam *eam, uint8_t unit_no)
|
||||
{
|
||||
log_assert(unit_no < lengthof(eam->units));
|
||||
|
||||
return eam->units[unit_no].alt_10k;
|
||||
}
|
||||
|
||||
void eam_impl_set_alt_10k(struct eam *eam, uint8_t unit_no, bool alt_10k)
|
||||
{
|
||||
log_assert(unit_no < lengthof(eam->units));
|
||||
|
||||
eam->units[unit_no].bound_ctls = false;
|
||||
eam->units[unit_no].alt_10k = alt_10k != false;
|
||||
}
|
||||
|
||||
struct hid_stub *eam_impl_get_keypad_device(struct eam *eam, uint8_t unit_no)
|
||||
@@ -159,8 +231,6 @@ void eam_impl_set_keypad_device(
|
||||
|
||||
eam->units[unit_no].hid = hid;
|
||||
eam->units[unit_no].bound_ctls = false;
|
||||
|
||||
eam->mux = hid != NULL && eam->units[0].hid == eam->units[1].hid;
|
||||
}
|
||||
|
||||
const char *eam_impl_get_card_path(struct eam *eam, uint8_t unit_no)
|
||||
@@ -203,7 +273,7 @@ uint16_t eam_impl_get_keypad_state(struct eam *eam, uint8_t unit_no)
|
||||
|
||||
log_assert(unit_no < lengthof(eam->units));
|
||||
|
||||
if (eam->mux && eam_impl_get_active_unit() != unit_no) {
|
||||
if (!eam_impl_is_active_unit(eam, unit_no)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -247,7 +317,7 @@ static void eam_impl_bind_keypad(struct eam *eam, uint8_t unit_no)
|
||||
return;
|
||||
}
|
||||
|
||||
if (eam->alt_10k) {
|
||||
if (eam->units[unit_no].alt_10k) {
|
||||
usages = eam_keypad_usages_alt;
|
||||
} else {
|
||||
usages = eam_keypad_usages;
|
||||
@@ -327,7 +397,7 @@ bool eam_impl_get_sensor_state(struct eam *eam, uint8_t unit_no)
|
||||
/* Bump cooldown as long as sensor button is held
|
||||
(cooldown timer might also be set by a USB hotplug event) */
|
||||
|
||||
if (value != 0 && (!eam->mux || eam_impl_get_active_unit() == unit_no)) {
|
||||
if (value != 0 && eam_impl_is_active_unit(eam, unit_no)) {
|
||||
unit->sensor_time = now + EAM_SENSOR_COOLDOWN;
|
||||
unit->sensor_hot = true;
|
||||
}
|
||||
|
||||
@@ -15,10 +15,17 @@
|
||||
struct eam;
|
||||
|
||||
struct eam *eam_impl_create(void);
|
||||
bool eam_impl_get_scard(struct eam *eam);
|
||||
void eam_impl_set_scard(struct eam *eam, bool scard);
|
||||
bool eam_impl_get_mux_keypad(struct eam *eam);
|
||||
void eam_impl_set_mux_keypad(struct eam *eam, bool mux_keypad);
|
||||
bool eam_impl_get_mux_scard(struct eam *eam);
|
||||
void eam_impl_set_mux_scard(struct eam *eam, bool mux_scard);
|
||||
bool eam_impl_get_autogen(struct eam *eam);
|
||||
void eam_impl_set_autogen(struct eam *eam, bool autogen);
|
||||
bool eam_impl_get_alt_10k(struct eam *eam);
|
||||
void eam_impl_set_alt_10k(struct eam *eam, bool alt_10k);
|
||||
bool eam_impl_do_keypads_conflict(struct eam *eam);
|
||||
bool eam_impl_get_alt_10k(struct eam *eam, uint8_t unit_no);
|
||||
void eam_impl_set_alt_10k(struct eam *eam, uint8_t unit_no, bool alt_10k);
|
||||
struct hid_stub *eam_impl_get_keypad_device(struct eam *eam, uint8_t unit_no);
|
||||
void eam_impl_set_keypad_device(
|
||||
struct eam *eam, uint8_t unit_no, struct hid_stub *hid);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "eamio/eam-s11n.h"
|
||||
|
||||
#include "util/fs.h"
|
||||
#include "util/log.h"
|
||||
|
||||
struct eam *eam_impl_config_load(FILE *f)
|
||||
{
|
||||
@@ -16,6 +17,9 @@ struct eam *eam_impl_config_load(FILE *f)
|
||||
char *dev_node;
|
||||
bool autogen;
|
||||
bool alt_10k;
|
||||
bool scard;
|
||||
bool mux_keypad;
|
||||
bool mux_scard;
|
||||
bool has_card_path;
|
||||
bool has_hid;
|
||||
|
||||
@@ -25,12 +29,22 @@ struct eam *eam_impl_config_load(FILE *f)
|
||||
goto early_fail;
|
||||
}
|
||||
|
||||
if (!read_u8(f, &alt_10k)) {
|
||||
if (!read_u8(f, &scard)) {
|
||||
goto early_fail;
|
||||
}
|
||||
|
||||
if (!read_u8(f, &mux_keypad)) {
|
||||
goto early_fail;
|
||||
}
|
||||
|
||||
if (!read_u8(f, &mux_scard)) {
|
||||
goto early_fail;
|
||||
}
|
||||
|
||||
eam_impl_set_autogen(eam, autogen);
|
||||
eam_impl_set_alt_10k(eam, alt_10k);
|
||||
eam_impl_set_mux_keypad(eam, mux_keypad);
|
||||
eam_impl_set_mux_scard(eam, mux_scard);
|
||||
eam_impl_set_scard(eam, scard);
|
||||
|
||||
if (!read_u8(f, &nunits) || nunits != EAM_UNIT_COUNT) {
|
||||
goto early_fail;
|
||||
@@ -47,6 +61,11 @@ struct eam *eam_impl_config_load(FILE *f)
|
||||
goto late_fail;
|
||||
}
|
||||
|
||||
if (!read_u8(f, &alt_10k)) {
|
||||
goto late_fail;
|
||||
}
|
||||
eam_impl_set_alt_10k(eam, unit_no, alt_10k);
|
||||
|
||||
if (has_card_path) {
|
||||
if (!read_str(f, &card_path)) {
|
||||
goto late_fail;
|
||||
@@ -89,26 +108,36 @@ void eam_impl_config_save(struct eam *eam, FILE *f)
|
||||
uint8_t unit_no;
|
||||
bool autogen;
|
||||
bool alt_10k;
|
||||
bool scard;
|
||||
bool mux_keypad;
|
||||
bool mux_scard;
|
||||
bool has_card_path;
|
||||
bool has_hid;
|
||||
|
||||
autogen = eam_impl_get_autogen(eam);
|
||||
alt_10k = eam_impl_get_alt_10k(eam);
|
||||
scard = eam_impl_get_scard(eam);
|
||||
mux_keypad = eam_impl_get_mux_keypad(eam);
|
||||
mux_scard = eam_impl_get_mux_scard(eam);
|
||||
|
||||
nunits = EAM_UNIT_COUNT;
|
||||
|
||||
write_u8(f, &autogen);
|
||||
write_u8(f, &alt_10k);
|
||||
write_u8(f, &scard);
|
||||
write_u8(f, &mux_keypad);
|
||||
write_u8(f, &mux_scard);
|
||||
write_u8(f, &nunits);
|
||||
|
||||
for (unit_no = 0; unit_no < EAM_UNIT_COUNT; unit_no++) {
|
||||
card_path = eam_impl_get_card_path(eam, unit_no);
|
||||
hid = eam_impl_get_keypad_device(eam, unit_no);
|
||||
alt_10k = eam_impl_get_alt_10k(eam, unit_no);
|
||||
|
||||
has_card_path = card_path != NULL;
|
||||
has_hid = hid != NULL;
|
||||
|
||||
write_u8(f, &has_card_path);
|
||||
write_u8(f, &has_hid);
|
||||
write_u8(f, &alt_10k);
|
||||
|
||||
if (has_card_path) {
|
||||
write_str(f, card_path);
|
||||
|
||||
319
src/main/eamio/eam-scard.c
Normal file
319
src/main/eamio/eam-scard.c
Normal file
@@ -0,0 +1,319 @@
|
||||
#include "eam-scard.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
struct scard {
|
||||
SCARDCONTEXT hContext;
|
||||
LPSTR mszReaders;
|
||||
DWORD pcchReaders;
|
||||
LPSTR reader_name[EAM_UNIT_COUNT];
|
||||
SCARD_READERSTATE rs[EAM_UNIT_COUNT];
|
||||
bool mux_reader;
|
||||
};
|
||||
|
||||
static struct scard *scard = NULL;
|
||||
|
||||
#define MAX_APDU_SIZE 255
|
||||
#define PICC_OPERATING_PARAMS 0xDFu
|
||||
BYTE PICC_OPERATING_PARAM_CMD[5] = {0xFFu, 0x00u, 0x51u, PICC_OPERATING_PARAMS, 0x00u};
|
||||
#define PICC_SUCCESS 0x90u
|
||||
static const BYTE UID_CMD[5] = {0xFFu, 0xCAu, 0x00u, 0x00u, 0x00u};
|
||||
enum scard_atr_protocol {
|
||||
SCARD_ATR_PROTOCOL_ISO14443_PART3 = 0x03,
|
||||
SCARD_ATR_PROTOCOL_ISO15693_PART3 = 0x0B,
|
||||
SCARD_ATR_PROTOCOL_FELICA_212K = 0x11,
|
||||
SCARD_ATR_PROTOCOL_FELICA_424K = 0x12,
|
||||
};
|
||||
|
||||
void eam_scard_init(bool mux_reader)
|
||||
{
|
||||
int curReaderIdx = 0;
|
||||
LONG ret;
|
||||
bool success = false;
|
||||
|
||||
if (scard != NULL) {
|
||||
// already init
|
||||
return;
|
||||
}
|
||||
|
||||
// Alloc and init the instance struct
|
||||
scard = (struct scard *) malloc(sizeof(struct scard));
|
||||
if (scard == NULL) {
|
||||
goto end;
|
||||
}
|
||||
memset(scard, 0, sizeof(struct scard));
|
||||
scard->mux_reader = mux_reader;
|
||||
|
||||
// Assign readers to each eam unit
|
||||
ret = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &scard->hContext);
|
||||
if (ret != SCARD_S_SUCCESS) {
|
||||
log_warning("SCardEstablishContext failed: %08lX", (ULONG) ret);
|
||||
goto end;
|
||||
}
|
||||
|
||||
scard->pcchReaders = SCARD_AUTOALLOCATE;
|
||||
|
||||
ret = SCardListReaders(
|
||||
scard->hContext, NULL, (LPSTR) &scard->mszReaders, &scard->pcchReaders);
|
||||
if (ret != SCARD_S_SUCCESS) {
|
||||
log_warning("SCardListReaders failed: %08lX", (ULONG) ret);
|
||||
goto end;
|
||||
}
|
||||
|
||||
// Find up to EAM_UNIT_COUNT readers
|
||||
for (LPSTR reader = scard->mszReaders; *reader != '\0';
|
||||
reader = reader + lstrlen(reader) + 1) {
|
||||
|
||||
// assign the reader
|
||||
scard->reader_name[curReaderIdx] = reader;
|
||||
|
||||
// are we done?
|
||||
curReaderIdx++;
|
||||
if (curReaderIdx == EAM_UNIT_COUNT || mux_reader) {
|
||||
// all readers assigned (or we are only going to use one)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// report results and initialize states
|
||||
for (int i = 0; i < EAM_UNIT_COUNT; i++) {
|
||||
// if we are muxing, assign the first reader to every unit
|
||||
if (mux_reader) {
|
||||
scard->reader_name[i] = scard->reader_name[0];
|
||||
}
|
||||
|
||||
if (scard->reader_name[i] != NULL) {
|
||||
log_info("unit_no %d scard reader: %s", i, scard->reader_name[i]);
|
||||
} else {
|
||||
log_warning("Failed to find reader for unit_no %d", i);
|
||||
}
|
||||
|
||||
scard->rs[i].szReader = scard->reader_name[i];
|
||||
scard->rs[i].dwCurrentState = SCARD_STATE_UNAWARE;
|
||||
}
|
||||
|
||||
success = true;
|
||||
|
||||
end:
|
||||
if (!success) {
|
||||
log_warning("Smartcard Reader init failed");
|
||||
eam_scard_fini();
|
||||
}
|
||||
}
|
||||
|
||||
void eam_scard_fini()
|
||||
{
|
||||
if (scard != NULL) {
|
||||
if (scard->mszReaders != NULL) {
|
||||
SCardFreeMemory(scard->hContext, scard->mszReaders);
|
||||
}
|
||||
|
||||
SCardReleaseContext(scard->hContext);
|
||||
|
||||
free(scard);
|
||||
scard = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool eam_scard_is_present(uint8_t unit_no)
|
||||
{
|
||||
bool is_active;
|
||||
|
||||
if (scard == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
log_assert(unit_no < lengthof(scard->rs));
|
||||
|
||||
if (scard->mux_reader) {
|
||||
// Determine active reader by numlock state
|
||||
is_active = (GetKeyState(VK_NUMLOCK) & 0x0001) == unit_no;
|
||||
} else {
|
||||
is_active = true;
|
||||
}
|
||||
|
||||
if (is_active) {
|
||||
return (scard->rs[unit_no].dwEventState & SCARD_STATE_PRESENT) != 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t eam_scard_read(uint8_t unit_no, uint8_t *card_id, uint8_t nbytes)
|
||||
{
|
||||
uint8_t card_type = EAM_IO_CARD_NONE;
|
||||
|
||||
if (scard == NULL) {
|
||||
return card_type;
|
||||
}
|
||||
|
||||
log_assert(unit_no < lengthof(scard->rs));
|
||||
log_assert(card_id != NULL);
|
||||
log_assert(nbytes == EAM_CARD_NBYTES);
|
||||
|
||||
/**
|
||||
* This function was lifted from scard.cpp in spice2x where its called
|
||||
* scard_update(), then modified for use in the eam io api. Changes in
|
||||
* support of BT5 coding standards were not made to minimize changes to
|
||||
* the original code. Error handling was however added so as to
|
||||
* disconnect from the card reader.
|
||||
*
|
||||
* @note The logic for the UID fix option in spice is not present
|
||||
*/
|
||||
|
||||
// Connect to the smart card.
|
||||
LONG lRet = 0;
|
||||
SCARDHANDLE hCard;
|
||||
DWORD dwActiveProtocol;
|
||||
|
||||
lRet = SCardConnect(scard->hContext, scard->rs[unit_no].szReader, SCARD_SHARE_EXCLUSIVE,
|
||||
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
|
||||
|
||||
if (lRet != SCARD_S_SUCCESS) {
|
||||
log_warning("error connecting to the card: %ld", lRet);
|
||||
return card_type;
|
||||
}
|
||||
|
||||
// set the reader params
|
||||
lRet = 0;
|
||||
const SCARD_IO_REQUEST *pci = dwActiveProtocol == SCARD_PROTOCOL_T1 ? SCARD_PCI_T1 : SCARD_PCI_T0;
|
||||
DWORD cbRecv = MAX_APDU_SIZE;
|
||||
BYTE pbRecv[MAX_APDU_SIZE];
|
||||
if ((lRet = SCardTransmit(hCard, pci, PICC_OPERATING_PARAM_CMD, sizeof(PICC_OPERATING_PARAM_CMD),
|
||||
NULL, pbRecv, &cbRecv)) != SCARD_S_SUCCESS) {
|
||||
log_warning("error setting PICC params: %ld", lRet);
|
||||
goto End;
|
||||
}
|
||||
|
||||
if (cbRecv > 2 && pbRecv[0] != PICC_SUCCESS && pbRecv[1] != PICC_OPERATING_PARAMS) {
|
||||
log_warning("PICC params not valid 0x%02X != 0x%02X",
|
||||
pbRecv[1], PICC_OPERATING_PARAMS);
|
||||
goto End;
|
||||
}
|
||||
|
||||
// Read ATR to determine card type.
|
||||
TCHAR szReader[200];
|
||||
DWORD cchReader = 200;
|
||||
BYTE atr[32];
|
||||
DWORD cByteAtr = 32;
|
||||
lRet = SCardStatus(hCard, szReader, &cchReader, NULL, NULL, atr, &cByteAtr);
|
||||
if (lRet != SCARD_S_SUCCESS) {
|
||||
log_warning("error getting card status: %ld",lRet);
|
||||
goto End;
|
||||
}
|
||||
|
||||
// Only care about 20-byte ATRs returned by arcade-type smart cards
|
||||
if (cByteAtr != 20) {
|
||||
log_warning("ignoring card with len(atr) = %ld", cByteAtr);
|
||||
goto End;
|
||||
}
|
||||
|
||||
// Figure out if we should reverse the UID returned by the card based on the
|
||||
// ATR protocol
|
||||
BYTE cardProtocol = atr[12];
|
||||
BOOL shouldReverseUid = false;
|
||||
if (cardProtocol == SCARD_ATR_PROTOCOL_ISO15693_PART3) {
|
||||
log_info("card protocol: ISO15693_PART3");
|
||||
shouldReverseUid = true;
|
||||
} else if (cardProtocol == SCARD_ATR_PROTOCOL_ISO14443_PART3) {
|
||||
log_info("card protocol: ISO14443_PART3");
|
||||
} else if (cardProtocol == SCARD_ATR_PROTOCOL_FELICA_212K) {
|
||||
log_info("card protocol: FELICA_212K");
|
||||
} else if (cardProtocol == SCARD_ATR_PROTOCOL_FELICA_424K) {
|
||||
log_info("card protocol: FELICA_424K");
|
||||
} else {
|
||||
log_warning("Unknown NFC Protocol: 0x%02X", cardProtocol);
|
||||
//return;
|
||||
}
|
||||
|
||||
// Read UID
|
||||
cbRecv = MAX_APDU_SIZE;
|
||||
if ((lRet = SCardTransmit(hCard, pci, UID_CMD, sizeof(UID_CMD), NULL, pbRecv, &cbRecv)) != SCARD_S_SUCCESS) {
|
||||
log_warning("error querying card UID: %ld", lRet);
|
||||
goto End;
|
||||
}
|
||||
|
||||
// check response
|
||||
// 2 bytes minimum for response code
|
||||
// 3+ bytes for response code plus one byte card number
|
||||
if (cbRecv < 3) {
|
||||
if (cbRecv < 2) {
|
||||
log_warning("UID query failed - not enough bytes (%ld)", cbRecv);
|
||||
} else {
|
||||
log_warning("UID query failed - received {0x%02X} {0x%02X} (%ld bytes)", pbRecv[0], pbRecv[1], cbRecv);
|
||||
}
|
||||
goto End;
|
||||
}
|
||||
|
||||
if (cbRecv < 8) {
|
||||
log_misc("padding card uid to 8 bytes by adding zeroes at the end");
|
||||
memset(&pbRecv[cbRecv], 0, 8 - cbRecv);
|
||||
} else if (cbRecv > 8) {
|
||||
log_misc("taking first 8 bytes of len(uid) = %ld", cbRecv);
|
||||
}
|
||||
|
||||
// Copy UID to struct, reversing if necessary
|
||||
if (shouldReverseUid) {
|
||||
for (DWORD i = 0; i < 8; i++) {
|
||||
card_id[i] = pbRecv[7 - i];
|
||||
}
|
||||
} else {
|
||||
memcpy(card_id, pbRecv, 8);
|
||||
}
|
||||
|
||||
log_info(
|
||||
"reader unit no: %d, card number to be inserted into game: "
|
||||
"%02X%02X %02X%02X %02X%02X %02X%02X",
|
||||
unit_no,
|
||||
card_id[0],
|
||||
card_id[1],
|
||||
card_id[2],
|
||||
card_id[3],
|
||||
card_id[4],
|
||||
card_id[5],
|
||||
card_id[6],
|
||||
card_id[7]);
|
||||
|
||||
if (card_id[0] == 0xe0 && card_id[1] == 0x04) {
|
||||
card_type = EAM_IO_CARD_ISO15696;
|
||||
} else {
|
||||
card_type = EAM_IO_CARD_FELICA;
|
||||
}
|
||||
|
||||
End:
|
||||
SCardDisconnect(hCard, SCARD_LEAVE_CARD);
|
||||
|
||||
return card_type;
|
||||
}
|
||||
|
||||
void eam_scard_poll(uint8_t unit_no)
|
||||
{
|
||||
SCARD_READERSTATE *rs;
|
||||
|
||||
if (scard != NULL) {
|
||||
log_assert(unit_no < lengthof(scard->rs));
|
||||
|
||||
rs = &scard->rs[unit_no];
|
||||
|
||||
if (rs->szReader == NULL) {
|
||||
// no reader present for this unit
|
||||
return;
|
||||
}
|
||||
|
||||
SCardGetStatusChange(scard->hContext, 0, rs, 1);
|
||||
}
|
||||
}
|
||||
|
||||
LPSTR eam_scard_get_reader_name(uint8_t unit_no)
|
||||
{
|
||||
if (scard != NULL) {
|
||||
log_assert(unit_no < lengthof(scard->rs));
|
||||
|
||||
if (scard->rs[unit_no].szReader != NULL) {
|
||||
return scard->reader_name[unit_no];
|
||||
}
|
||||
}
|
||||
|
||||
return "Not Present";
|
||||
}
|
||||
39
src/main/eamio/eam-scard.h
Normal file
39
src/main/eamio/eam-scard.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Smartcard reader support for eamio
|
||||
*/
|
||||
#ifndef EAMIO_SCARD_H
|
||||
#define EAMIO_SCARD_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <windows.h>
|
||||
#include <winioctl.h>
|
||||
#include <winscard.h>
|
||||
|
||||
#include "eam-impl.h"
|
||||
|
||||
void eam_scard_init(bool mux_reader);
|
||||
void eam_scard_fini(void);
|
||||
|
||||
/**
|
||||
* Indicates if a card is currently present on the reader
|
||||
*/
|
||||
bool eam_scard_is_present(uint8_t unit_no);
|
||||
|
||||
/**
|
||||
* Read a present card into card_id buffer
|
||||
*/
|
||||
uint8_t eam_scard_read(uint8_t unit_no, uint8_t *card_id, uint8_t nbytes);
|
||||
|
||||
/**
|
||||
* Poll smartcard reader state
|
||||
*/
|
||||
void eam_scard_poll(uint8_t unit_no);
|
||||
|
||||
/**
|
||||
* Return the name of the reader or "Not Present" if no reader is bound to the
|
||||
* unit. Intended for use in the config ui.
|
||||
*/
|
||||
LPSTR eam_scard_get_reader_name(uint8_t unit_no);
|
||||
|
||||
#endif
|
||||
@@ -23,6 +23,7 @@ src_geninput := \
|
||||
io-thread.c \
|
||||
kbd.c \
|
||||
kbd-data.c \
|
||||
kbd-naive.c \
|
||||
mapper.c \
|
||||
mapper-s11n.c \
|
||||
mouse.c \
|
||||
|
||||
@@ -28,6 +28,7 @@ EXPORTS
|
||||
light_iter_is_valid
|
||||
light_iter_next
|
||||
light_iter_free
|
||||
kbd_is_naive
|
||||
mapper_config_load
|
||||
mapper_config_save
|
||||
mapper_clear_action_map
|
||||
|
||||
36
src/main/geninput/kbd-naive.c
Normal file
36
src/main/geninput/kbd-naive.c
Normal file
@@ -0,0 +1,36 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "geninput/hid.h"
|
||||
#include "geninput/kbd-naive.h"
|
||||
#include "geninput/kbd.h"
|
||||
|
||||
static struct hid_stub *kbd_naive_stub = NULL;
|
||||
static struct hid_ri *kbd_naive_hid_ri = NULL;
|
||||
|
||||
static const char *kbd_naive_dev_node = "kbd-naive";
|
||||
static const wchar_t *kbd_naive_dev_name = L"Any (naive binding)";
|
||||
|
||||
void kbd_naive_init(void)
|
||||
{
|
||||
kbd_naive_stub = hid_mgr_get_named_stub(kbd_naive_dev_node);
|
||||
|
||||
kbd_create(&kbd_naive_hid_ri, kbd_naive_dev_node, kbd_naive_dev_name);
|
||||
|
||||
hid_stub_attach(kbd_naive_stub, (struct hid *) kbd_naive_hid_ri);
|
||||
}
|
||||
|
||||
void kbd_naive_fini(void)
|
||||
{
|
||||
free(kbd_naive_stub);
|
||||
kbd_naive_stub = NULL;
|
||||
}
|
||||
|
||||
void kbd_naive_event_notify(RAWINPUT *ri)
|
||||
{
|
||||
hid_ri_handle_event(kbd_naive_hid_ri, ri);
|
||||
}
|
||||
|
||||
bool kbd_is_naive(struct hid_stub *stub)
|
||||
{
|
||||
return (stub == kbd_naive_stub);
|
||||
}
|
||||
13
src/main/geninput/kbd-naive.h
Normal file
13
src/main/geninput/kbd-naive.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef GENINPUT_KBD_NAIVE_H
|
||||
#define GENINPUT_KBD_NAIVE_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "geninput/hid-mgr.h"
|
||||
|
||||
void kbd_naive_init(void);
|
||||
void kbd_naive_fini(void);
|
||||
void kbd_naive_event_notify(RAWINPUT *ri);
|
||||
bool kbd_is_naive(struct hid_stub *stub);
|
||||
|
||||
#endif
|
||||
@@ -89,7 +89,8 @@ static void kbd_static_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
void kbd_create(struct hid_ri **hid_ri, const char *dev_node)
|
||||
void kbd_create(
|
||||
struct hid_ri **hid_ri, const char *dev_node, const wchar_t *name_override)
|
||||
{
|
||||
struct kbd *kbd;
|
||||
char *tmp;
|
||||
@@ -98,7 +99,11 @@ void kbd_create(struct hid_ri **hid_ri, const char *dev_node)
|
||||
|
||||
kbd = xcalloc(sizeof(*kbd));
|
||||
kbd->super.vptr = &kbd_vtbl;
|
||||
kbd->name = hid_ri_init_name(&kbd_guid, dev_node);
|
||||
if (name_override) {
|
||||
kbd->name = wstr_dup(name_override);
|
||||
} else {
|
||||
kbd->name = hid_ri_init_name(&kbd_guid, dev_node);
|
||||
}
|
||||
|
||||
*hid_ri = &kbd->super;
|
||||
|
||||
|
||||
@@ -6,6 +6,13 @@
|
||||
#define KBD_DEVICE_USAGE_KEYBOARD 0x00010006
|
||||
#define KBD_DEVICE_USAGE_KEYPAD 0x00010007
|
||||
|
||||
void kbd_create(struct hid_ri **hid_ri, const char *dev_node);
|
||||
/**
|
||||
* Creates a keyboard device for use with key bindings
|
||||
*
|
||||
* @note name_override can be NULL and is only intended to be populated when
|
||||
* the desired device name is not the name as indicated by the dev_node
|
||||
*/
|
||||
void kbd_create(
|
||||
struct hid_ri **hid_ri, const char *dev_node, const wchar_t *name_override);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "geninput/hid-mgr.h"
|
||||
#include "geninput/hid.h"
|
||||
#include "geninput/kbd.h"
|
||||
#include "geninput/kbd-naive.h"
|
||||
#include "geninput/mouse.h"
|
||||
#include "geninput/ri.h"
|
||||
|
||||
@@ -45,6 +46,11 @@ void ri_init(HWND hwnd)
|
||||
(unsigned int) GetLastError());
|
||||
}
|
||||
|
||||
/* Init the naive keyboard before scanning for devices. This allows the
|
||||
* actual hid devices to be preferred when using the bind dialog in the
|
||||
* config ui */
|
||||
kbd_naive_init();
|
||||
|
||||
ri_scan_devices();
|
||||
}
|
||||
|
||||
@@ -104,7 +110,7 @@ void ri_scan_devices(void)
|
||||
|
||||
if (ridl[i].dwType == RIM_TYPEKEYBOARD) {
|
||||
ri_handles[i].fake_fd = ridl[i].hDevice;
|
||||
kbd_create(&ri_handles[i].hid_ri, dev_node);
|
||||
kbd_create(&ri_handles[i].hid_ri, dev_node, NULL);
|
||||
|
||||
hid_stub_attach(stub, (struct hid *) ri_handles[i].hid_ri);
|
||||
} else if (ridl[i].dwType == RIM_TYPEMOUSE) {
|
||||
@@ -139,6 +145,13 @@ void ri_handle_msg(HRAWINPUT msg)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform naive kdb updates prior to checking device. If the inputs were
|
||||
generated by another program instead of from an actual hid device, we
|
||||
don't want to miss them due to the hDevice check below. */
|
||||
if (ri.header.dwType == RIM_TYPEKEYBOARD) {
|
||||
kbd_naive_event_notify(&ri);
|
||||
}
|
||||
|
||||
if (ri.header.hDevice == NULL) {
|
||||
/* WTF?? I've seen this happen while remote-controlling someone's
|
||||
desktop using TeamViewer, possibly due to an API hook injected by TV
|
||||
@@ -161,6 +174,8 @@ void ri_fini(void)
|
||||
{
|
||||
RAWINPUTDEVICE filter[3];
|
||||
|
||||
kbd_naive_fini();
|
||||
|
||||
free(ri_handles);
|
||||
ri_handles = NULL;
|
||||
ri_ndevs = 0;
|
||||
|
||||
Reference in New Issue
Block a user