#include #include #include #include #include #include #include #include #include "board/config.h" #include "board/guid.h" #include "board/usio.h" #include "hook/iobuf.h" #include "hook/iohook.h" #include "hooklib/setupapi.h" #include "util/dprintf.h" #include "util/dump.h" #pragma pack(push, 1) enum { USIO_CMD_SET_COMM_TIMEOUT = 0x01, USIO_CMD_SET_SAMPLING_COUNT = 0x02, USIO_CMD_CLEAR_BOARD_STATUS = 0x03, USIO_CMD_SET_GENERAL_OUTPUT = 0x04, USIO_CMD_SET_PWM_OUTPUT = 0x05, USIO_CMD_UNIMPLEMENTED = 0x41, USIO_CMD_UPDATE_FIRMWARE = 0x85, }; #pragma pack(pop) static HRESULT usio_handle_irp(struct irp *irp); static HRESULT usio_handle_open(struct irp *irp); static HRESULT usio_handle_close(struct irp *irp); static HRESULT usio_handle_read(struct irp *irp); static HRESULT usio_handle_write(struct irp *irp); static HRESULT usio_handle_ioctl(struct irp *irp); static HRESULT usio_ioctl_get_manufacturer_string(struct irp *irp); static HRESULT usio_ioctl_get_product_string(struct irp *irp); static const wchar_t usio_path[] = L"$usio"; //static const wchar_t usio_path[] = L"USBIO_Device0"; static HANDLE usio_fd; static const struct usio_ops *usio_ops; static void *usio_ops_ctx; HRESULT usio_hook_init( const struct usio_config *cfg, const struct usio_ops *ops, void *ctx) { HRESULT hr; assert(cfg != NULL); assert(ops != NULL); if (!cfg->enable) { return S_FALSE; } hr = iohook_open_nul_fd(&usio_fd); if (FAILED(hr)) { return hr; } usio_ops = ops; usio_ops_ctx = ctx; iohook_push_handler(usio_handle_irp); hr = setupapi_add_phantom_dev(&usio_guid, usio_path); if (FAILED(hr)) { return hr; } dprintf("USIO: Init\n"); return S_OK; } static HRESULT usio_handle_irp(struct irp *irp) { assert(irp != NULL); if (irp->op != IRP_OP_OPEN && irp->fd != usio_fd) { return iohook_invoke_next(irp); } switch (irp->op) { case IRP_OP_OPEN: return usio_handle_open(irp); case IRP_OP_CLOSE: return usio_handle_close(irp); case IRP_OP_READ: return usio_handle_read(irp); case IRP_OP_WRITE: return usio_handle_write(irp); case IRP_OP_IOCTL: return usio_handle_ioctl(irp); default: return HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION); } } static HRESULT usio_handle_open(struct irp *irp) { if (wcscmp(irp->open_filename, usio_path) != 0) { return iohook_invoke_next(irp); } dprintf("USIO: Device opened\n"); irp->fd = usio_fd; return S_OK; } static HRESULT usio_handle_close(struct irp *irp) { dprintf("USIO: Device closed\n"); return S_OK; } static HRESULT usio_handle_read(struct irp *irp) { dprintf("USIO: Read\n"); dump_iobuf(&irp->read); return S_OK; } static HRESULT usio_handle_write(struct irp *irp) { dprintf("USIO: Write\n"); dump_const_iobuf(&irp->write); return S_OK; } static HRESULT usio_handle_ioctl(struct irp *irp) { switch (irp->ioctl) { case IOCTL_HID_GET_MANUFACTURER_STRING: dprintf("USIO: Get Manufacturer String\n"); //return usio_ioctl_get_manufacturer_string(irp); case IOCTL_HID_GET_PRODUCT_STRING: dprintf("USIO: Get Product String\n"); //return usio_ioctl_get_product_string(irp); case IOCTL_HID_GET_INPUT_REPORT: dprintf("USIO: Control IN (untested!!)\n"); //return usio_handle_read(irp); case IOCTL_HID_SET_OUTPUT_REPORT: dprintf("USIO: Control OUT (untested!!)\n"); //return usio_handle_write(irp); default: dprintf("USIO: Unknown ioctl %#08x, write %i read %i\n", irp->ioctl, (int) irp->write.nbytes, (int) irp->read.nbytes); #if 1 dprintf("USIO: Written\n"); dump_const_iobuf(&irp->write); dprintf("USIO: Read\n"); dump_iobuf(&irp->read); #endif return HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION); } }