From 93bf47fb764cbd8b32157168a5cf695c56afc611 Mon Sep 17 00:00:00 2001 From: Tau Date: Thu, 8 Nov 2018 10:17:47 -0500 Subject: [PATCH] nu/hwmon.c: Add emulated hardware monitoring driver --- nu/hwmon.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++ nu/hwmon.h | 3 ++ nu/meson.build | 2 ++ 3 files changed, 95 insertions(+) create mode 100644 nu/hwmon.c create mode 100644 nu/hwmon.h diff --git a/nu/hwmon.c b/nu/hwmon.c new file mode 100644 index 0000000..2e34f1c --- /dev/null +++ b/nu/hwmon.c @@ -0,0 +1,90 @@ +#include + +#include +#include + +#include "util/dprintf.h" + +#include "hook/iohook.h" + +#include "nu/hwmon.h" + +enum { + HWMON_IOCTL_READ_CPU_TEMP = 0x80006000, +}; + +static HRESULT hwmon_handle_irp(struct irp *irp); +static HRESULT hwmon_handle_open(struct irp *irp); +static HRESULT hwmon_handle_close(struct irp *irp); +static HRESULT hwmon_handle_ioctl(struct irp *irp); + +static HRESULT hwmon_ioctl_read_cpu_temp(struct irp *irp); + +static HANDLE hwmon_fd; + +void hwmon_hook_init(void) +{ + hwmon_fd = iohook_open_dummy_fd(); + iohook_push_handler(hwmon_handle_irp); +} + +static HRESULT hwmon_handle_irp(struct irp *irp) +{ + assert(irp != NULL); + + if (irp->op != IRP_OP_OPEN && irp->fd != hwmon_fd) { + return iohook_invoke_next(irp); + } + + switch (irp->op) { + case IRP_OP_OPEN: return hwmon_handle_open(irp); + case IRP_OP_CLOSE: return hwmon_handle_close(irp); + case IRP_OP_IOCTL: return hwmon_handle_ioctl(irp); + default: return HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION); + } +} + +static HRESULT hwmon_handle_open(struct irp *irp) +{ + if (wcscmp(irp->open_filename, L"\\\\.\\sghwmonitor") != 0) { + return iohook_invoke_next(irp); + } + + dprintf("Hwmon: Opened device\n"); + irp->fd = hwmon_fd; + + return S_OK; +} + +static HRESULT hwmon_handle_close(struct irp *irp) +{ + dprintf("Hwmon: Closed device\n"); + + return S_OK; +} + +static HRESULT hwmon_handle_ioctl(struct irp *irp) +{ + switch (irp->ioctl) { + case HWMON_IOCTL_READ_CPU_TEMP: + return hwmon_ioctl_read_cpu_temp(irp); + + default: + dprintf("Hwmon: Unknown ioctl %08x write %i read %i\n", + irp->ioctl, + irp->write.nbytes, + irp->read.nbytes); + + return HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION); + } +} + +static HRESULT hwmon_ioctl_read_cpu_temp(struct irp *irp) +{ + /* Assuming this is Celsius. It also seems to be biased by -23 (based on the + caller code) despite being a 32-bit int. */ + + dprintf("Hwmon: Read CPU temperature\n"); + + return iobuf_write_le32(&irp->read, 52); +} diff --git a/nu/hwmon.h b/nu/hwmon.h new file mode 100644 index 0000000..49d457d --- /dev/null +++ b/nu/hwmon.h @@ -0,0 +1,3 @@ +#pragma once + +void hwmon_hook_init(void); diff --git a/nu/meson.build b/nu/meson.build index 669b7ac..293fc67 100644 --- a/nu/meson.build +++ b/nu/meson.build @@ -15,6 +15,8 @@ nu_lib = static_library( 'gpio.c', 'gpio.h', 'guid.c', + 'hwmon.c', + 'hwmon.h', 'nusec.c', 'nusec.h', 'nvram.c',