Files
pumpitupdev_pumptools/src/main/hook/patch/piuio-khack.c
T
icex2 eafb2909d1 Appl new code style on whole code base
Use a similar code style to bemanitools though reduce indentation
to 2 spaces. Also some other tweaks to be more similar to google
style.
2021-03-19 15:52:34 +01:00

140 lines
4.1 KiB
C

#include "capnhook/hook/usbhook.h"
#include "io/piuio/defs.h"
#include "util/log.h"
#define PATCH_PIUIO_KHACK_CTRL_REQ_TYPE 0
#define PATCH_PIUIO_KHACK_CTRL_REQ 0
#define PATCH_PIUIO_KHACK_TIMEOUT 10011
#define PATCH_PIUIO_KHACK_BUFFER_SIZE PIUIO_DRV_BUFFER_SIZE * 4
static enum cnh_result patch_piuio_khack_usbhook(struct cnh_usbhook_irp *irp);
static usb_dev_handle *_patch_piuio_khack_usb_handle;
void patch_piuio_khack_init()
{
cnh_usbhook_push_handler(patch_piuio_khack_usbhook);
log_info("Initialized");
}
static enum cnh_result patch_piuio_khack_usbhook(struct cnh_usbhook_irp *irp)
{
enum cnh_result result;
uint8_t out_buffer[PATCH_PIUIO_KHACK_BUFFER_SIZE];
uint8_t in_buffer[PATCH_PIUIO_KHACK_BUFFER_SIZE];
if (irp->op != CNH_USBHOOK_IRP_OP_OPEN &&
_patch_piuio_khack_usb_handle != irp->handle) {
return cnh_usbhook_invoke_next(irp);
}
switch (irp->op) {
case CNH_USBHOOK_IRP_OP_OPEN: {
if (irp->open_usb_dev->descriptor.idVendor == PIUIO_DRV_VID &&
irp->open_usb_dev->descriptor.idProduct == PIUIO_DRV_PID) {
if (_patch_piuio_khack_usb_handle) {
log_warn("Already detected PIUIO previously, ignoring re-detection");
irp->handle = _patch_piuio_khack_usb_handle;
result = CNH_RESULT_SUCCESS;
} else {
log_info("Detected PIUIO");
result = cnh_usbhook_invoke_next(irp);
if (result == CNH_RESULT_SUCCESS) {
_patch_piuio_khack_usb_handle = irp->handle;
}
}
} else {
result = cnh_usbhook_invoke_next(irp);
}
break;
}
case CNH_USBHOOK_IRP_OP_CTRL_MSG: {
// Identifiers for custom kernel hack introduced by some update in ITG 2
// back in the days
if (irp->ctrl_req_type == PATCH_PIUIO_KHACK_CTRL_REQ_TYPE &&
irp->ctrl_req == PATCH_PIUIO_KHACK_CTRL_REQ &&
irp->ctrl_timeout == PATCH_PIUIO_KHACK_TIMEOUT) {
// Hack combines the four calls for each sensor into a single call
if (irp->ctrl_buffer.nbytes != PATCH_PIUIO_KHACK_BUFFER_SIZE) {
log_error(
"Invalid buffer size for kernel hack: %d",
irp->ctrl_buffer.nbytes);
return CNH_RESULT_INVALID_PARAMETER;
}
memcpy(out_buffer, irp->ctrl_buffer.bytes, irp->ctrl_buffer.nbytes);
// Split the hack into single calls
for (uint8_t i = 0; i < 4; i++) {
irp->ctrl_req_type = PIUIO_DRV_USB_CTRL_TYPE_OUT;
irp->ctrl_req = PIUIO_DRV_USB_CTRL_REQUEST;
irp->ctrl_timeout = PIUIO_DRV_USB_REQ_TIMEOUT;
irp->ctrl_buffer.pos = 0;
irp->ctrl_buffer.nbytes = PIUIO_DRV_BUFFER_SIZE;
memcpy(
irp->ctrl_buffer.bytes,
&out_buffer[PIUIO_DRV_BUFFER_SIZE * i],
PIUIO_DRV_BUFFER_SIZE);
result = cnh_usbhook_invoke_next_reset_advance(irp);
if (result != CNH_RESULT_SUCCESS) {
return result;
}
irp->ctrl_req_type = PIUIO_DRV_USB_CTRL_TYPE_IN;
irp->ctrl_req = PIUIO_DRV_USB_CTRL_REQUEST;
irp->ctrl_timeout = PIUIO_DRV_USB_REQ_TIMEOUT;
irp->ctrl_buffer.pos = 0;
irp->ctrl_buffer.nbytes = PIUIO_DRV_BUFFER_SIZE;
result = cnh_usbhook_invoke_next_reset_advance(irp);
if (result != CNH_RESULT_SUCCESS) {
return result;
}
memcpy(
&in_buffer[PIUIO_DRV_BUFFER_SIZE * i],
irp->ctrl_buffer.bytes,
PIUIO_DRV_BUFFER_SIZE);
}
irp->ctrl_req_type = PATCH_PIUIO_KHACK_CTRL_REQ_TYPE;
irp->ctrl_req = PATCH_PIUIO_KHACK_CTRL_REQ;
irp->ctrl_timeout = PATCH_PIUIO_KHACK_TIMEOUT;
irp->ctrl_buffer.pos = PATCH_PIUIO_KHACK_BUFFER_SIZE;
irp->ctrl_buffer.nbytes = PATCH_PIUIO_KHACK_BUFFER_SIZE;
memcpy(
irp->ctrl_buffer.bytes, in_buffer, PATCH_PIUIO_KHACK_BUFFER_SIZE);
}
break;
}
case CNH_USBHOOK_IRP_OP_CLOSE: {
_patch_piuio_khack_usb_handle = NULL;
result = cnh_usbhook_invoke_next(irp);
break;
}
default:
result = cnh_usbhook_invoke_next(irp);
break;
}
return result;
}