diff --git a/include/sys.h b/include/sys.h index bf71827..a634bfb 100644 --- a/include/sys.h +++ b/include/sys.h @@ -1,6 +1,8 @@ #ifndef LINUXSMARTIE_SYS_H #define LINUXSMARTIE_SYS_H +#include "utils.h" + #include #define SYS_GET_TIME_STR(t) sys_get_time_string((char[16]){0}, 16, t) @@ -20,6 +22,8 @@ struct disk_t { struct network_t { uint32_t download; uint32_t upload; + sensor_file_t f_rx; + sensor_file_t f_tx; char device[16]; }; @@ -41,8 +45,10 @@ void sys_get_disk(struct disk_t *disk); void sys_get_network(struct network_t *network); +void sys_netdev_detect(struct network_t *network); + void sys_detect(struct syssensors_t *s, const char *platform); -void sys_update_sensors(struct syssensors_t *s); +void sys_update_sensors(const struct syssensors_t *s); #endif // LINUXSMARTIE_SYS_H \ No newline at end of file diff --git a/include/utils.h b/include/utils.h index f484e19..3b137d1 100644 --- a/include/utils.h +++ b/include/utils.h @@ -2,7 +2,7 @@ #define LINUXSMARTIE_UTILS_H #include -#include +#include // NOLINT yes its, needed for ssize_t #if __STDC_VERSION__ >= 202000L #define C_STD "C23" @@ -22,17 +22,20 @@ #define P_BYTES(bytes, start) pretty_bytes((bytes), (start), (char[16]){0}, 16) #define P_NUM(num) pretty_num((num), (char[16]){0}, 16) -typedef enum { +typedef enum : uint8_t { SENSOR_I16, + SENSOR_U8, + SENSOR_U16, + SENSOR_U64, + SENSOR_FLOAT, } sensor_type_t; typedef struct { - char path[256]; + sensor_type_t type; int fd; void* value; uint32_t divider; - sensor_type_t type; -} sensor_t; +} sensor_file_t; int get_instance_lock(); @@ -46,22 +49,12 @@ char *pretty_bytes(uint64_t bytes, int8_t start_suffix, char *buf, size_t bufsz) int get_hwmon_dir(char *path, size_t bufsz); -ssize_t read_file(const char *dir, const char *file, char *buffer, size_t n); +void open_sensor(sensor_file_t* s, const char* dir, const char *file, void* value, uint32_t divider, sensor_type_t type); -void fast_read_num_u64(const char *dir, const char *file, char *buf, uint64_t *result, uint32_t divider); +void fast_read_sensor_into_mem(const sensor_file_t *s, void* val); -void fast_read_num_u16(const char *dir, const char *file, char *buf, uint16_t *result, uint32_t divider); +void fast_read_sensor(const sensor_file_t *s); -void fast_read_num_u8(const char *dir, const char *file, char *buf, uint8_t *result, uint32_t divider); - -void fast_read_num_i16(const char *dir, const char *file, char *buf, int16_t *result, uint32_t divider); - -void fast_read_num_f(const char *dir, const char *file, char *buf, float *result, uint32_t divider); - -void open_sensor(sensor_t* s, const char* dir, const char *file, void* value, uint32_t divider, sensor_type_t type); - -void fast_read_sensor_i16(const sensor_t *s); - -void close_sensor(const sensor_t* s); +void close_sensor(const sensor_file_t* s); #endif diff --git a/src/cpu.c b/src/cpu.c index e8fd60e..e86a6ea 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -3,10 +3,13 @@ #include "utils.h" #include +#include #include #include -static uint64_t max_energy_range_uj = 0; +static sensor_file_t* sensors; +static sensor_file_t* cpu_freqs; +static constexpr uint64_t max_energy_range_uj = 65532610987; void cpu_detect(struct cpu_sensors_t *t, const char *pci_dev) { t->module = unknown; @@ -20,14 +23,34 @@ void cpu_detect(struct cpu_sensors_t *t, const char *pci_dev) { return; } - static char buf[32]; - fast_read_num_u64("/sys/class/powercap/intel-rapl:0/", "max_energy_range_uj", buf, &max_energy_range_uj, 1); - t->module = read_file(t->hwmon, "/in1_input", nullptr, 0) ? zenpower : k10temp; // if we can read zenpower file then zenpower. idk if this is reliable, we're trying to avoid just reading the name + // fast_read_num_u64("/sys/class/powercap/intel-rapl:0/", "max_energy_range_uj", buf, &max_energy_range_uj, 1); + // t->module = read_file(t->hwmon, "/in1_input", nullptr, 0) ? zenpower : k10temp; // if we can read zenpower file then zenpower. idk if this is reliable, we're trying to avoid just reading the name + t->module = k10temp; // just assume its k10temp until we figure out a better way to detect it applog(LOG_INF, "Detected %d cores, module enum #%d in path %s", t->num_cores, t->module, t->hwmon); + + cpu_freqs = malloc(sizeof(sensor_file_t) * t->num_cores); + sensors = malloc(sizeof(sensor_file_t) * (t->module == zenpower ? 4 : 3)); + + for (uint8_t i = 0; i < t->num_cores; i++) { + char p[128]; + sprintf(p, "/sys/devices/system/cpu/cpu%d/cpufreq/", i); + open_sensor(&cpu_freqs[i], p, "cpuinfo_avg_freq", nullptr, 1000, SENSOR_U64); + } + + if (max_energy_range_uj != 0) + open_sensor(&sensors[0], "/sys/class/powercap/intel-rapl:0/", "energy_uj", nullptr, 1, SENSOR_U64); + + if (t->module == k10temp) { + open_sensor(&sensors[1], t->hwmon, "/temp1_input", &t->tctl, 1000, SENSOR_I16); + open_sensor(&sensors[2], t->hwmon, "/temp3_input", &t->tccd1, 1000, SENSOR_I16); + } else if (t->module == zenpower) { + open_sensor(&sensors[1], t->hwmon, "/temp1_input", &t->tdie, 1000, SENSOR_I16); + open_sensor(&sensors[2], t->hwmon, "/temp2_input", &t->tctl, 1000, SENSOR_I16); + open_sensor(&sensors[3], t->hwmon, "/temp3_input", &t->tccd1, 1000, SENSOR_I16); + } } void cpu_update(struct cpu_sensors_t *c) { - static char buf[32]; struct energy_t { struct timespec ts; uint64_t energy; @@ -40,7 +63,7 @@ void cpu_update(struct cpu_sensors_t *c) { // read power from intel-rapl? works on amd too, btop uses this trick, seems accurate // it tracks with "socket power" in hwinfo on windows, its actually the same thing i had in lcdsmartie clock_gettime(CLOCK_MONOTONIC, &curr.ts); - fast_read_num_u64("/sys/class/powercap/intel-rapl:0/", "energy_uj", buf, &curr.energy, 1); + fast_read_sensor_into_mem(&sensors[0], &curr.energy); if (curr.energy >= prev.energy) energy_delta = curr.energy - prev.energy; @@ -56,11 +79,9 @@ void cpu_update(struct cpu_sensors_t *c) { // lots of reads but still faster than reading /proc/cpuinfo c->avg_freq = 0; - char p[128]; for (uint8_t i = 0; i < c->num_cores; i++) { uint64_t t = 0; - sprintf(p, "/sys/devices/system/cpu/cpu%d/cpufreq/", i); - fast_read_num_u64(p, "cpuinfo_avg_freq", buf, &t, 1000); + fast_read_sensor_into_mem(&cpu_freqs[i], &t); c->avg_freq += (uint32_t)t; } c->avg_freq /= (c->num_cores > 1) ? c->num_cores : 1; @@ -69,15 +90,15 @@ void cpu_update(struct cpu_sensors_t *c) { return; if (c->module == k10temp) { - fast_read_num_i16(c->hwmon, "/temp1_input", buf, &c->tctl, 1000); - fast_read_num_i16(c->hwmon, "/temp3_input", buf, &c->tccd1, 1000); + fast_read_sensor(&sensors[1]); + fast_read_sensor(&sensors[2]); } // commented out unused values so its faster if (c->module == zenpower) { - fast_read_num_i16(c->hwmon, "/temp1_input", buf, &c->tdie, 1000); - fast_read_num_i16(c->hwmon, "/temp2_input", buf, &c->tctl, 1000); - fast_read_num_i16(c->hwmon, "/temp3_input", buf, &c->tccd1, 1000); + fast_read_sensor(&sensors[1]); + fast_read_sensor(&sensors[2]); + fast_read_sensor(&sensors[3]); // utils::fastReadNum<1000>(c->hwmon + "/in1_input", buf, c->vcore); // utils::fastReadNum<1000>(c->hwmon + "/in2_input", buf, c->vsoc); } diff --git a/src/gpu.c b/src/gpu.c index b213db8..1710319 100644 --- a/src/gpu.c +++ b/src/gpu.c @@ -6,8 +6,16 @@ #include "log.h" #include "utils.h" +#include +#include +#include +#include + static constexpr char rel_metrics_path[] = "/../../gpu_metrics"; // gpu_metrics path relative to hwmon path -static constexpr uint16_t max_metrics_length = 512; // length of the metrics buffer +static constexpr uint16_t max_metrics_length = 512; // length of the metrics buffer + +static sensor_file_t* sensors; +static int gpu_metrics_fd; void gpu_detect(struct gpu_sensors_t *t, const char *pci) { snprintf(t->hwmon, sizeof(t->hwmon), "/sys/bus/pci/devices/%s/hwmon", pci); @@ -19,43 +27,55 @@ void gpu_detect(struct gpu_sensors_t *t, const char *pci) { } t->has_gpu_metrics = false; - char raw_metrics[max_metrics_length]; - if (!read_file(t->hwmon, rel_metrics_path, raw_metrics, sizeof(raw_metrics))) - return; - const struct metrics_table_header *header = (struct metrics_table_header *)raw_metrics; - applog(LOG_INF, "Found gpu_metrics_v%d_%d", header->format_revision, header->content_revision); - t->has_gpu_metrics = true; + char p[160]; + char *nt = stpcpy(p, t->hwmon); + strcpy(nt, rel_metrics_path); + gpu_metrics_fd = open(p, O_RDONLY | O_CLOEXEC); + if (gpu_metrics_fd > 0) { + t->has_gpu_metrics = true; + char raw_metrics[max_metrics_length]; + read(gpu_metrics_fd, raw_metrics, sizeof(raw_metrics)); + const struct metrics_table_header *header = (struct metrics_table_header *)raw_metrics; + applog(LOG_INF, "Found gpu_metrics_v%d_%d", header->format_revision, header->content_revision); + } + + sensors = malloc(sizeof(sensor_file_t) * (t->has_gpu_metrics ? 10 : 5)); + + // we always open these + open_sensor(&sensors[0], t->hwmon, "/in0_input", &t->vcore, 1000, SENSOR_FLOAT); + open_sensor(&sensors[1], t->hwmon, "/fan1_input", &t->fan_speed, 1, SENSOR_U16); + open_sensor(&sensors[2], t->hwmon, "/power1_cap", &t->power_cap, 1000000, SENSOR_U16); + open_sensor(&sensors[3], t->hwmon, "/power1_average", &t->power_avg, 1000000, SENSOR_U16); + open_sensor(&sensors[4], t->hwmon, "/../../mem_info_vram_used", &t->vram_used, 1, SENSOR_U64); + + if (t->has_gpu_metrics == false) { + open_sensor(&sensors[5], t->hwmon, "/freq1_input", &t->clock_core, 1000000, SENSOR_U16); + open_sensor(&sensors[6], t->hwmon, "/freq2_input", &t->clock_mem, 1000000, SENSOR_U16); + open_sensor(&sensors[7], t->hwmon, "/power1_input",&t->power_avg, 1000000, SENSOR_U16); + open_sensor(&sensors[8], t->hwmon, "/temp1_input", &t->temp_edge, 1000, SENSOR_U8); + open_sensor(&sensors[9], t->hwmon, "/../../gpu_busy_percent", &t->usage_core, 1, SENSOR_U8); + } } /* some metrics are missing in gpu_metrics, we always fill them from fs, unused metrics are commented out */ -static void fill_missing_metrics(struct gpu_sensors_t *g) { - char buf[32]; - fast_read_num_f(g->hwmon, "/in0_input", buf, &g->vcore, 1000); +static void fill_missing_metrics() { // g->fan_pwm = std::stoi(readFile(g->hwmon + "/pwm1", 4)) * 100 / 256; - fast_read_num_u16(g->hwmon, "/fan1_input", buf, &g->fan_speed, 1); - fast_read_num_u16(g->hwmon, "/power1_cap", buf, &g->power_cap, 1000000); - fast_read_num_u16(g->hwmon, "/power1_average", buf, &g->power_avg, 1000000); // utils::fastReadNum(g->hwmon + "/power1_cap_max", g->power_cap_max) / 1000000; - fast_read_num_u64(g->hwmon, "/../../mem_info_vram_used", buf, &g->vram_used, 1); // utils::fastReadNum(g->hwmon + "/../../mem_info_vram_total", g->vram_total); + for (uint8_t i = 0; i < 5; i++) + fast_read_sensor(&sensors[i]); } /* get sensors for pre-vega cards (rx480/580) */ -static void update_from_fs(struct gpu_sensors_t *g) { - char buf[32]; - fast_read_num_u16(g->hwmon, "/freq1_input", buf, &g->clock_core, 1000000); - fast_read_num_u16(g->hwmon, "/freq2_input", buf, &g->clock_mem, 1000000); - fast_read_num_u16(g->hwmon, "/power1_input", buf, &g->power_avg, 1000000); - fast_read_num_u8(g->hwmon, "/temp1_input", buf, &g->temp_edge, 1000); - fast_read_num_u8(g->hwmon, "/../../gpu_busy_percent", buf, &g->usage_core, 1); +static void update_from_fs() { + for (uint8_t i = 5; i < 10; i++) + fast_read_sensor(&sensors[i]); } static void update_from_metrics(struct gpu_sensors_t *g) { char raw_metrics[max_metrics_length]; - - if (!read_file(g->hwmon, rel_metrics_path, raw_metrics, sizeof(raw_metrics))) - return; - + lseek(gpu_metrics_fd, 0, SEEK_SET); + read(gpu_metrics_fd, raw_metrics, sizeof(raw_metrics)); const struct metrics_table_header *header = (struct metrics_table_header *)raw_metrics; switch (header->format_revision * 10 + header->content_revision) { @@ -106,11 +126,11 @@ void gpu_update(struct gpu_sensors_t *g) { const bool hwmon_valid = g->hwmon[0] != '\0'; if (hwmon_valid) - fill_missing_metrics(g); + fill_missing_metrics(); if (g->has_gpu_metrics) update_from_metrics(g); else if (hwmon_valid) - update_from_fs(g); + update_from_fs(); if (g->fan_speed > 9999) g->fan_speed = 9999; // sanity check fan speed } \ No newline at end of file diff --git a/src/lcd.c b/src/lcd.c index 55ccb29..a3ce436 100644 --- a/src/lcd.c +++ b/src/lcd.c @@ -10,10 +10,7 @@ #define MIN(a, b) ((a) < (b) ? (a) : (b)) -int lcd_open(struct lcd_t *lcd, bool reopen); -void lcd_write(struct lcd_t *lcd, const uint8_t *cmdbuf, uint16_t len); - -int lcd_open(struct lcd_t *lcd, const bool reopen) { +static int lcd_open(struct lcd_t *lcd, const bool reopen) { applog(LOG_INF, "Opening serial port at %s", lcd->port); if (lcd->fd <= 0 || reopen) lcd->fd = open(lcd->port, O_WRONLY | O_NOCTTY); @@ -36,7 +33,7 @@ void lcd_close(struct lcd_t *lcd) { lcd->fd = -1; } -void lcd_write(struct lcd_t *lcd, const uint8_t *cmdbuf, const uint16_t len) { +static void lcd_write(struct lcd_t *lcd, const uint8_t *cmdbuf, const uint16_t len) { if (write(lcd->fd, cmdbuf, len) <= 0) { applog(LOG_ERR, "failed to execute write(), lost access to port?"); lcd_close(lcd); @@ -109,7 +106,7 @@ inline void lcd_clear_buf(struct lcd_t *lcd) { /* flushes writebuffer to lcd, hyperoptmized, flushes buffer and commands in a single write operation */ -inline void lcd_flush_buf(struct lcd_t *lcd) { +void lcd_flush_buf(struct lcd_t *lcd) { constexpr uint8_t set_disp[] = {254, 71, 1, 1}; // set cursor to char 1, line 1 memcpy(&lcd->writebuf.text[0], set_disp, 4); memcpy(&lcd->writebuf.text[2 * LCD_COLS + 4], set_disp, 4); diff --git a/src/main.c b/src/main.c index d5193cc..ff0023f 100644 --- a/src/main.c +++ b/src/main.c @@ -23,13 +23,13 @@ static constexpr char netif[] = "enp4s0f0"; static constexpr char cpu_pcidev[] = "0000:00:18.3"; static constexpr char gpu_pcidev[] = "0000:0a:00.0"; -struct control_t { +static struct { pthread_mutex_t sensors_mtx; pthread_cond_t sensors_ready; atomic_bool running; } control; -struct sensors_t { // NOLINT yes it is +struct sensors_t { // NOLINT stfu time_t ts; struct memory_t ram; struct disk_t home; @@ -56,6 +56,7 @@ static void *sensors_thread(void *arg) { cpu_detect(&sensors->cpu, cpu_pcidev); gpu_detect(&sensors->gpu, gpu_pcidev); sys_detect(&sensors->sys, "nct6775.656"); + sys_netdev_detect(&sensors->net); aio_detect(&sensors->aio); /* main sensor loop */ @@ -90,7 +91,7 @@ static void *sensors_thread(void *arg) { static void *display_thread(void *arg) { applog(LOG_START, "display thread started"); - struct sensors_t *sensors = arg; + const struct sensors_t *sensors = arg; /* lcd setup */ struct lcd_t lcd = { @@ -191,7 +192,7 @@ int main() { } /* malloc memory for the struct */ - struct sensors_t *sensors = malloc(sizeof(*sensors)); // no actual point in mallocing and it is ever so sligtly slower to access heap vs stack, but its cool + struct sensors_t *sensors = malloc(sizeof(struct sensors_t)); // no actual point in mallocing but its cool if (sensors == nullptr) { applog(LOG_ERR, "can't allocate mem for the sensor struct. You don't got %lu bytes bro?", sizeof(*sensors)); free(sensors); diff --git a/src/sys.c b/src/sys.c index ce727f6..fee405b 100644 --- a/src/sys.c +++ b/src/sys.c @@ -8,7 +8,7 @@ #include "sys.h" #include "utils.h" -static sensor_t sensors[1]; +static sensor_file_t sensors; char *sys_get_time_string(char *buf, const size_t bufsz, const time_t t) { const struct tm *tm = localtime(&t); @@ -61,26 +61,30 @@ void sys_get_network(struct network_t *network) { uint64_t tx; }; - static char path[128]; - static char buf[32]; static struct _net_t prev; struct _net_t current = {}; - snprintf(path, sizeof(path), "/sys/class/net/%s/statistics/", network->device); clock_gettime(CLOCK_MONOTONIC, ¤t.ts); - fast_read_num_u64(path, "rx_bytes", buf, ¤t.rx, 1); - fast_read_num_u64(path, "tx_bytes", buf, ¤t.tx, 1); + fast_read_sensor_into_mem(&network->f_rx, ¤t.rx); + fast_read_sensor_into_mem(&network->f_tx, ¤t.tx); const int64_t diff_us = timespec_diff_us(¤t.ts, &prev.ts); const uint64_t rx_delta = current.rx >= prev.rx ? current.rx - prev.rx : 0; const uint64_t tx_delta = current.tx >= prev.tx ? current.tx - prev.tx : 0; const double diff_s = (double)diff_us / 1000000.0; network->download = (uint32_t)((double)rx_delta / diff_s); network->upload = (uint32_t)((double)tx_delta / diff_s); - if (rx_delta < 2000000000ULL && tx_delta < 2000000000ULL) - prev = current; + prev = current; // still fucky? } +void sys_netdev_detect(struct network_t *network) { + applog(LOG_INF, "Opening netdev %s", network->device); + static char path[128]; + snprintf(path, sizeof(path), "/sys/class/net/%s/statistics/", network->device); + open_sensor(&network->f_rx, path, "rx_bytes", nullptr, 1, SENSOR_U64); + open_sensor(&network->f_tx, path, "tx_bytes", nullptr, 1, SENSOR_U64); +} + void sys_detect(struct syssensors_t *s, const char *platform) { snprintf(s->hwmon, sizeof(s->hwmon), "/sys/devices/platform/%s/hwmon", platform); const int ret = get_hwmon_dir(s->hwmon, sizeof(s->hwmon)); @@ -90,22 +94,12 @@ void sys_detect(struct syssensors_t *s, const char *platform) { return; } applog(LOG_INF, "Detected system sensors in %s", s->hwmon); - - open_sensor(&sensors[0], s->hwmon, "/temp5_input", &s->t_sensor, 1000, SENSOR_I16); + open_sensor(&sensors, s->hwmon, "/temp5_input", &s->t_sensor, 1000, SENSOR_I16); } -void sys_update_sensors(struct syssensors_t *s) { +void sys_update_sensors(const struct syssensors_t *s) { if (!s->hwmon[0]) return; - static size_t num_sensors = 0; - if (num_sensors == 0) - num_sensors = sizeof(sensors) / sizeof(sensors[0]); - - // static char buf[8]; - // fast_read_num_u16(s->hwmon, "/fan2_input", buf, &s->fan_speed[0], 1); // cpu fan, aka aio pump now - // fast_read_num_u16(s->hwmon, "/fan7_input", buf, &s->fan_speed[1], 1); // cpu opt - // fast_read_num_i16(s->hwmon, "/temp5_input", buf, &s->t_sensor, 1000); - for (size_t i = 0; i < num_sensors; i++) - fast_read_sensor_i16(&sensors[i]); + fast_read_sensor(&sensors); } diff --git a/src/utils.c b/src/utils.c index 123dc4e..a2568c4 100644 --- a/src/utils.c +++ b/src/utils.c @@ -13,7 +13,7 @@ #include "log.h" #include "utils.h" -int get_instance_lock(void) { +int get_instance_lock() { const char *xdg_runtime_dir = getenv("XDG_RUNTIME_DIR"); char tmp_dir[256]; snprintf(tmp_dir, sizeof(tmp_dir), "%s/linuxSmartie.lock", xdg_runtime_dir); @@ -80,82 +80,72 @@ int get_hwmon_dir(char *path, const size_t bufsz) { return -1; } -/* instead of building the path here we could build it once in *_detect funcs for each sensor, but thats a lot of paths damn - * actual slowdown is in the syscalls anyway, open(), read(), close () */ - -/* read n bytes from path into buffer */ -// file descriptors shouldnt change once opened, so we could open once, cache them, just call read() in the loop, then close all of them on program exit? -inline ssize_t read_file(const char *dir, const char *file, char *buffer, const size_t n) { - char path[160]; // bug alert +void open_sensor(sensor_file_t* s, const char* dir, const char *file, void* value, const uint32_t divider, const sensor_type_t type) { + char path[256]; char *nt = stpcpy(path, dir); // nt is a pointer to the null terminator of the copied string strcpy(nt, file); // copy to the null terminator of prev copy, append basically - const int fd = open(path, O_RDONLY | O_CLOEXEC); - if (fd < 0) { - if (buffer != nullptr) // if its null means we're just checking if it exists at all, so dont log it - applog(LOG_ERR, "Error reading %s", path); - return 0; - } - const ssize_t len = read(fd, buffer, n); - if (len > 0 && buffer) - buffer[len] = '\0'; - close(fd); - return len; -} - -inline void fast_read_num_u64(const char *dir, const char *file, char *buf, uint64_t *result, const uint32_t divider) { - read_file(dir, file, buf, 32); - *result = strtoull(buf, nullptr, 10) / divider; -} - -inline void fast_read_num_u16(const char *dir, const char *file, char *buf, uint16_t *result, const uint32_t divider) { - read_file(dir, file, buf, 32); - *result = (uint16_t)(strtol(buf, nullptr, 10) / divider); -} - -inline void fast_read_num_u8(const char *dir, const char *file, char *buf, uint8_t *result, const uint32_t divider) { - read_file(dir, file, buf, 32); - *result = (uint8_t)(strtol(buf, nullptr, 10) / divider); -} - -inline void fast_read_num_i16(const char *dir, const char *file, char *buf, int16_t *result, const uint32_t divider) { - read_file(dir, file, buf, 32); - *result = (int16_t)(strtol(buf, nullptr, 10) / divider); -} - -inline void fast_read_num_f(const char *dir, const char *file, char *buf, float *result, const uint32_t divider) { - read_file(dir, file, buf, 32); - const uint64_t val = strtoull(buf, nullptr, 10); - *result = (float)val / (float)divider; -} - -void open_sensor(sensor_t* s, const char* dir, const char *file, void* value, const uint32_t divider, const sensor_type_t type) { - char *nt = stpcpy(s->path, dir); // nt is a pointer to the null terminator of the copied string - strcpy(nt, file); // copy to the null terminator of prev copy, append basically s->divider = divider; s->value = value; s->type = type; - s->fd = open(s->path, O_RDONLY | O_CLOEXEC); + s->fd = open(path, O_RDONLY | O_CLOEXEC); + if (s->fd < 0) + applog(LOG_ERR, "couldn't open %s", path); } -inline void fast_read_sensor_i16(const sensor_t *s) { +inline void fast_read_sensor_into_mem(const sensor_file_t *s, void* val) { + if (s->fd < 0) { + applog(LOG_ERR, "invalid sensor fd %d", s->fd); + return; + } + char buf[32]; lseek(s->fd, 0, SEEK_SET); const ssize_t len = read(s->fd, buf, sizeof(buf)); - if (len > 0) - buf[len] = '\0'; - // return if read failed + + if (len <= 0) { + applog(LOG_ERR, "error reading sensor"); + return; + } + + buf[len] = '\0'; switch (s->type) { case SENSOR_I16: - *(int16_t*)s->value = (int16_t)(strtol(buf, nullptr, 10) / s->divider); + *(int16_t*)val = (int16_t)(strtol(buf, nullptr, 10) / s->divider); + break; + + case SENSOR_U8: + *(uint8_t*)val = (uint8_t)(strtol(buf, nullptr, 10) / s->divider); + break; + + case SENSOR_U16: + *(uint16_t*)val = (uint16_t)(strtol(buf, nullptr, 10) / s->divider); + break; + + case SENSOR_U64: + *(uint64_t*)val = strtoull(buf, nullptr, 10) / s->divider; + break; + + case SENSOR_FLOAT: + const uint64_t t = strtoull(buf, nullptr, 10); + *(float*)val = (float)t / (float)s->divider; break; default: - return; + applog(LOG_ERR, "unknown sensor type %d", s->type); + break; } } -void close_sensor(const sensor_t* s) { +inline void fast_read_sensor(const sensor_file_t *s) { + if (s->value != nullptr) { + fast_read_sensor_into_mem(s, s->value); + return; + } + applog(LOG_ERR, "attempted to read into nullptr"); +} + +void close_sensor(const sensor_file_t* s) { close(s->fd); } \ No newline at end of file