This commit is contained in:
daydensteve
2026-03-02 03:02:52 -08:00
committed by GitHub
18 changed files with 849 additions and 67 deletions

View File

@@ -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
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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
View 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";
}

View 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

View File

@@ -23,6 +23,7 @@ src_geninput := \
io-thread.c \
kbd.c \
kbd-data.c \
kbd-naive.c \
mapper.c \
mapper-s11n.c \
mouse.c \

View File

@@ -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

View 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);
}

View 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

View File

@@ -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;

View File

@@ -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

View File

@@ -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;