+
+#define DATA_BUFFER_SIZE_MAX 4096
+#define SOC_SENSOR_MAX 64
+
+int sys_get_cpu_temperature(int* temperature);
+int sys_get_soc_temperature(int index, int* temperature);
+
+enum MHD_Result hwmonitor_request(struct MHD_Connection *conn)
+{
+ const char* mime = "text/html";
+ const char* fmt;
+ int size = 0;
+ bool json = false;
+ int cpu_temperature = 0, soc_temperature[SOC_SENSOR_MAX] = {0}, soc_index;
+ enum MHD_Result ret = MHD_NO;
+ struct MHD_Response *resp;
+ char data[DATA_BUFFER_SIZE_MAX];
+ const char* html_header =
+ "\r\n"
+ "\r\n"
+ "\r\n"
+ "\r\n"
+ "HWMonitor\r\n"
+ "\r\n"
+ "\r\n"
+ "HWMonitor
\r\n";
+
+ const char* html_footer =
+ "\r\n"
+ "\r\n";
+
+ fmt = MHD_lookup_connection_value(conn, MHD_GET_ARGUMENT_KIND, "fmt");
+ if(fmt && !strcmp(fmt, "json")) {
+ mime = "application/json";
+ json = true;
+ }
+
+ sys_get_cpu_temperature(&cpu_temperature);
+ for(soc_index = 0; soc_index < SOC_SENSOR_MAX; soc_index++) {
+ if(sys_get_soc_temperature(soc_index, soc_temperature + soc_index)) {
+ break;
+ }
+ }
+
+ if(json) {
+ int n = snprintf(data, DATA_BUFFER_SIZE_MAX, "{");
+ size += n;
+
+ if(cpu_temperature > 0) {
+ n = snprintf(data + size, DATA_BUFFER_SIZE_MAX - size, "\"cpu_temperature\":%d,", cpu_temperature);
+ size += n;
+ }
+
+ if(soc_index > 0) {
+ n = snprintf(data + size, DATA_BUFFER_SIZE_MAX - size, "\"soc_temperature\":[");
+ size += n;
+ for(int i = 0; i < soc_index; i++) {
+ n = snprintf(data + size, DATA_BUFFER_SIZE_MAX - size, "%d,", soc_temperature[i]);
+ size += n;
+ }
+
+ size--;
+ n = snprintf(data + size, DATA_BUFFER_SIZE_MAX - size, "],");
+ size += n;
+ }
+
+ if(size > 1) {
+ size--;
+ }
+ n = snprintf(data + size, DATA_BUFFER_SIZE_MAX - size, "}");
+ size += n;
+ } else {
+ int n = snprintf(data, DATA_BUFFER_SIZE_MAX, "%s", html_header);
+ size += n;
+
+ if(cpu_temperature > 0) {
+ n = snprintf(data + size, DATA_BUFFER_SIZE_MAX - size, "CPU Temperature: %d°C %d°F
\r\n", cpu_temperature, cpu_temperature * 18 / 10 + 32);
+ size += n;
+ }
+
+ if(soc_index > 0) {
+ n = snprintf(data + size, DATA_BUFFER_SIZE_MAX - size, "SOC Temperature:
\r\n");
+ size += n;
+ for(int i = 0; i < soc_index; i++) {
+ n = snprintf(data + size, DATA_BUFFER_SIZE_MAX - size, " [S%02d]: %d°C %d°F
\r\n", i + 1, soc_temperature[i], soc_temperature[i] * 18 / 10 + 32);
+ size += n;
+ }
+ }
+
+ n = snprintf(data + size, DATA_BUFFER_SIZE_MAX - size, "%s", html_footer);
+ size += n;
+ }
+
+ if((resp=MHD_create_response_from_buffer(size, data,
+ MHD_RESPMEM_PERSISTENT))) {
+ MHD_add_response_header(resp, MHD_HTTP_HEADER_CONTENT_TYPE,
+ mime);
+ ret = websrv_queue_response(conn, MHD_HTTP_OK, resp);
+ MHD_destroy_response(resp);
+ }
+
+ return ret;
+}
\ No newline at end of file
diff --git a/src/hwmonitor.h b/src/hwmonitor.h
new file mode 100644
index 0000000..02c0316
--- /dev/null
+++ b/src/hwmonitor.h
@@ -0,0 +1,25 @@
+/* Copyright (C) 2025 Sunny Qeen
+ Copyright (C) 2024 John Törnblom
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, see
+. */
+
+#pragma once
+
+#include
+
+/**
+ * Respond to a hwmonitor request.
+ **/
+enum MHD_Result hwmonitor_request(struct MHD_Connection *conn);
diff --git a/src/pc/sys.c b/src/pc/sys.c
index 53d7e5c..722c025 100644
--- a/src/pc/sys.c
+++ b/src/pc/sys.c
@@ -87,3 +87,14 @@ sys_launch_payload(const char* cwd, uint8_t* elf, size_t elf_size,
return sys_launch_homebrew(cwd, filename, args, env);
}
+int
+sys_get_cpu_temperature(int* temperature) {
+ printf("get cpu temperature");
+ return -1;
+}
+
+int
+sys_get_soc_temperature(int index, int* temperature) {
+ printf("get soc[%02d] temperature", index);
+ return -1;
+}
diff --git a/src/ps5/sys.c b/src/ps5/sys.c
index f8d9199..92fe039 100644
--- a/src/ps5/sys.c
+++ b/src/ps5/sys.c
@@ -61,6 +61,8 @@ int sceSystemServiceKillApp(int app_id, int how, int reason, int core_dump);
int sceSystemServiceLaunchApp(const char* title_id, char** argv,
app_launch_ctx_t* ctx);
+int sceKernelGetCpuTemperature(int *);
+int sceKernelGetSocSensorTemperature(int, int *);
/**
* Decode an escaped argument.
@@ -372,6 +374,19 @@ sys_launch_title(const char* title_id, const char* args) {
return err;
}
+
+int
+sys_get_cpu_temperature(int* temperature) {
+ return sceKernelGetCpuTemperature(temperature);
+}
+
+
+int
+sys_get_soc_temperature(int index, int* temperature) {
+ return sceKernelGetSocSensorTemperature(index, temperature);
+}
+
+
/**
*
**/
diff --git a/src/websrv.c b/src/websrv.c
index ec9e097..eaf6eab 100644
--- a/src/websrv.c
+++ b/src/websrv.c
@@ -31,6 +31,7 @@ along with this program; see the file COPYING. If not, see
#include "smb.h"
#include "sys.h"
#include "version.h"
+#include "hwmonitor.h"
#include "websrv.h"
@@ -324,6 +325,9 @@ websrv_on_request(void *cls, struct MHD_Connection *conn,
if(!strcmp("/version", url)) {
return version_request(conn);
}
+ if(!strcmp("/hwmonitor", url)) {
+ return hwmonitor_request(conn);
+ }
if(!strcmp("/", url) || !url[0]) {
return asset_request(conn, "/index.html");
}