diff --git a/src/main/hook/patch/piubtn.c b/src/main/hook/patch/piubtn.c index 4364c36..b4659f7 100644 --- a/src/main/hook/patch/piubtn.c +++ b/src/main/hook/patch/piubtn.c @@ -37,6 +37,8 @@ static ptapi_io_piubtn_send_t _patch_piubtn_ptapi_io_piubtn_send; static ptapi_io_piubtn_get_input_t _patch_piubtn_ptapi_io_piubtn_get_input; static ptapi_io_piubtn_set_output_t _patch_piubtn_ptapi_io_piubtn_set_output; +static uint32_t _patch_piubtn_poll_delay_ms; + static const struct cnh_usb_emu_virtdev_ep _patch_piubtn_virtdev = { .pid = PIUBTN_DRV_PID, .vid = PIUBTN_DRV_VID, @@ -49,8 +51,14 @@ static const struct cnh_usb_emu_virtdev_ep _patch_piubtn_virtdev = { static void *_patch_piubtn_api_lib_handle; -void patch_piubtn_init(const char *piubtn_lib_path) +void patch_piubtn_init(const char *piubtn_lib_path, uint32_t poll_delay_ms) { + _patch_piubtn_poll_delay_ms = poll_delay_ms; + + if (_patch_piubtn_poll_delay_ms > 0) { + log_debug("Enabled poll delay ms: %d", poll_delay_ms); + } + if (!piubtn_lib_path) { log_die("No piubtn emulation library path specified"); } @@ -140,6 +148,10 @@ static enum cnh_result _patch_piubtn_control_msg( struct cnh_iobuf *buffer, int timeout) { + if (_patch_piubtn_poll_delay_ms > 0) { + usleep(_patch_piubtn_poll_delay_ms * 1000); + } + if (request_type == PIUBTN_DRV_USB_CTRL_TYPE_IN && request == PIUBTN_DRV_USB_CTRL_REQUEST) { if (buffer->nbytes != PIUBTN_DRV_BUFFER_SIZE) { diff --git a/src/main/hook/patch/piubtn.h b/src/main/hook/patch/piubtn.h index 12a046c..d578693 100644 --- a/src/main/hook/patch/piubtn.h +++ b/src/main/hook/patch/piubtn.h @@ -13,9 +13,12 @@ * Initialize the patch module * * @param piubtn_lib_path Path to a library implementing the piubtn API - * @param real_passthrough True to ignore the library and disable any emulation + * @param poll_delay_ms If the polling thread relies on the hardware + * load for timing, CPU load increases massively if the caller is not taking + * care of sleeping properly. Injects an artificial delay to emulate that and + * control the CPU load. */ -void patch_piubtn_init(const char *piubtn_lib_path); +void patch_piubtn_init(const char *piubtn_lib_path, uint32_t poll_delay_ms); /** * Get the input hook handler provided by the piubtn library. diff --git a/src/main/hook/patch/piuio.c b/src/main/hook/patch/piuio.c index b2a29c7..fd28b16 100644 --- a/src/main/hook/patch/piuio.c +++ b/src/main/hook/patch/piuio.c @@ -45,11 +45,18 @@ static const struct cnh_usb_emu_virtdev_ep _patch_piuio_virtdev = { .close = _patch_piuio_close, }; +static uint32_t _patch_piuio_poll_delay_ms; static struct ptapi_io_piuio_api _patch_piuio_api; static enum ptapi_io_piuio_sensor_group _patch_piuio_sensor_group; -void patch_piuio_init(const char *piuio_lib_path) +void patch_piuio_init(const char *piuio_lib_path, uint32_t poll_delay_ms) { + _patch_piuio_poll_delay_ms = poll_delay_ms; + + if (_patch_piuio_poll_delay_ms > 0) { + log_debug("Enabled poll delay ms: %d", poll_delay_ms); + } + if (!piuio_lib_path) { log_die("No piuio emulation library path specified"); } @@ -116,6 +123,10 @@ static enum cnh_result _patch_piuio_control_msg( struct cnh_iobuf *buffer, int timeout) { + if (_patch_piuio_poll_delay_ms > 0) { + usleep(_patch_piuio_poll_delay_ms * 1000); + } + /** * Expected call pattern for a full game state update on a single frame (when * done synchronously) diff --git a/src/main/hook/patch/piuio.h b/src/main/hook/patch/piuio.h index db04f79..0ae3b4b 100644 --- a/src/main/hook/patch/piuio.h +++ b/src/main/hook/patch/piuio.h @@ -11,8 +11,12 @@ * Initialize the patch module * * @param piuio_lib_path Path to a library implementing the piuio API + * @param poll_delay_ms If the polling thread relies on the hardware + * load for timing, CPU load increases massively if the caller is not taking + * care of sleeping properly. Injects an artificial delay to emulate that and + * control the CPU load. */ -void patch_piuio_init(const char *piuio_lib_path); +void patch_piuio_init(const char *piuio_lib_path, uint32_t poll_delay_ms); /** * Shut down the patch module