#define WIN32_NO_STATUS #include #undef WIN32_NO_STATUS #include #include #include #include #include "idmac/jvs.h" #include "hook/iobuf.h" #include "hook/iohook.h" #include "hooklib/uart.h" #include "hooklib/setupapi.h" #include "jvs/jvs-bus.h" #include "util/dprintf.h" #include "util/dump.h" #include "util/str.h" enum { JVS_IOCTL_HELLO = 0x80006004, JVS_IOCTL_SENSE = 0x8000600C, JVS_IOCTL_TRANSACT = 0x8000E008, }; static HRESULT jvs_handle_irp(struct irp *irp); static HRESULT jvs_handle_irp_locked(struct irp *irp); static CRITICAL_SECTION jvs_lock; static struct uart jvs_uart; static uint8_t jvs_written_bytes[516]; static uint8_t jvs_readable_bytes[516]; static uint8_t temp_bytes[516]; static struct jvs_node *jvs_root; static jvs_provider_t jvs_provider; static struct iobuf tmp = { .nbytes = 516, .pos = 0, .bytes = temp_bytes }; static bool last = false; static uint8_t num_cts = 0; HRESULT jvs_hook_init(const struct jvs_config *cfg, jvs_provider_t provider) { HRESULT hr; assert(cfg != NULL); if (!cfg->enable) { return S_FALSE; } InitializeCriticalSection(&jvs_lock); uart_init(&jvs_uart, 2); jvs_uart.written.bytes = jvs_written_bytes; jvs_uart.written.nbytes = sizeof(jvs_written_bytes); jvs_uart.readable.bytes = jvs_readable_bytes; jvs_uart.readable.nbytes = sizeof(jvs_readable_bytes); jvs_provider = provider; return iohook_push_handler(jvs_handle_irp); } static HRESULT jvs_handle_irp(struct irp *irp) { HRESULT hr; assert(irp != NULL); if (!uart_match_irp(&jvs_uart, irp)) { return iohook_invoke_next(irp); } EnterCriticalSection(&jvs_lock); hr = jvs_handle_irp_locked(irp); LeaveCriticalSection(&jvs_lock); return hr; } static HRESULT jvs_handle_irp_locked(struct irp *irp) { #if 0 dprintf("\nJVS Port: Outbound frame:\n"); dump_const_iobuf(&irp->write); #endif struct iobuf req_iobuf; HRESULT hr; struct jvs_node *root; if (irp->op == IRP_OP_OPEN) { dprintf("iDmac JVS: Starting backend\n"); if (jvs_provider != NULL) { hr = jvs_provider(&root); if (SUCCEEDED(hr)) { jvs_root = root; } } } if (irp->op == IRP_OP_IOCTL) { switch (irp->ioctl) { case IOCTL_SERIAL_GET_MODEMSTATUS: //jvs_uart.cts_on = jvs_root->sense_out; //dprintf("JVS: Set CTS to %X\n", jvs_root->sense_out); jvs_uart.cts_on = jvs_root->sense_out; break; case IOCTL_SERIAL_GET_COMMSTATUS: //dprintf("JVS: Set cbInQue to %d\n", (int)tmp.pos); jvs_uart.readable.pos = tmp.pos; default: break; } } if (irp->op == IRP_OP_READ) { if (irp->read.nbytes > 1) { //dprintf("JVS: Readable buffer is %d / %d\n", (int)irp->read.nbytes, (int)tmp.pos); iobuf_write(&irp->read, tmp.bytes, tmp.pos); tmp.pos = 0; } else { dprintf("JVS: Readable buffer is 1!\n"); } } hr = uart_handle_irp(&jvs_uart, irp); if (FAILED(hr) || irp->op != IRP_OP_WRITE) { return hr; } //jvs_bus_transact(jvs_root, irp->write.bytes, irp->write.nbytes, &irp->read); jvs_bus_transact(jvs_root, irp->write.bytes, irp->write.nbytes, &tmp); jvs_uart.written.pos = 0; return S_OK; }