#define LOG_MODULE "aciodrv-proc-panb" #include #include "aciodrv/device.h" #include "aciodrv/panb.h" #include "util/log.h" #include "util/thread.h" static int auto_poll_proc(void *auto_poll_param); static int auto_poll_threadid; static CRITICAL_SECTION keypair_lock; static struct ac_io_panb_keypair _keypair[AC_IO_PANB_MAX_KEYPAIRS]; static CRITICAL_SECTION auto_poll_stop_lock; static bool auto_poll_stop; static int auto_poll_proc(void *param) { struct aciodrv_device_ctx *device = (struct aciodrv_device_ctx *) param; struct ac_io_panb_poll_in poll_in; bool stop; do { aciodrv_panb_recv_poll(device, &poll_in); EnterCriticalSection(&keypair_lock); memcpy(_keypair, poll_in.keypair, AC_IO_PANB_MAX_KEYPAIRS); LeaveCriticalSection(&keypair_lock); EnterCriticalSection(&auto_poll_stop_lock); stop = auto_poll_stop; LeaveCriticalSection(&auto_poll_stop_lock); } while (!stop); return 0; } bool aciodrv_proc_panb_init(struct aciodrv_device_ctx *device) { log_assert(device); if (!aciodrv_panb_start_auto_input(device, 0, AC_IO_PANB_NUM_NODES)) { return false; } auto_poll_stop = false; InitializeCriticalSection(&keypair_lock); InitializeCriticalSection(&auto_poll_stop_lock); auto_poll_threadid = thread_create(auto_poll_proc, (void *) device, 0x4000, 0); return true; } bool aciodrv_proc_panb_get_state(uint8_t *button_state) { struct ac_io_panb_keypair keypair[AC_IO_PANB_MAX_KEYPAIRS]; EnterCriticalSection(&keypair_lock); memcpy(keypair, _keypair, AC_IO_PANB_MAX_KEYPAIRS); LeaveCriticalSection(&keypair_lock); /* splice the keypairs into separate button values */ for (int i = 0; i < AC_IO_PANB_MAX_KEYPAIRS; i++) { uint8_t but1 = keypair[i].key1; uint8_t but2 = keypair[i].key2; button_state[2 * i] = but1; button_state[2 * i + 1] = but2; } return true; } void aciodrv_proc_panb_fini(struct aciodrv_device_ctx *device) { EnterCriticalSection(&auto_poll_stop_lock); auto_poll_stop = true; LeaveCriticalSection(&auto_poll_stop_lock); thread_join(auto_poll_threadid, NULL); thread_destroy(auto_poll_threadid); DeleteCriticalSection(&keypair_lock); DeleteCriticalSection(&auto_poll_stop_lock); /* reset is the only way to disable the auto polling on device side */ aciodrv_device_reset(device); }