void sensor_free(Sensor *sensor) { if (sensor->name) free(sensor->name); if (sensor->child_name) free(sensor->child_name); #if defined(__linux__) if (sensor->path) free(sensor->path); #endif free(sensor); } Eina_Bool sensor_update(Sensor *sensor) { #if defined(__linux__) char *d = file_contents(sensor->path); if (d) { double val = atof(d); if (sensor->type == THERMAL) sensor->value = val /= 1000; else if (sensor->type == FANRPM) sensor->value = val; free(d); return 1; } return 0; #elif defined(__OpenBSD__) struct sensor snsr; size_t slen = sizeof(struct sensor); if (sensor->invalid) { sensor->value = 0; return 0; } if (sysctl(sensor->mibs, 5, &snsr, &slen, NULL, 0) == -1) return 0; if (sensor->type == THERMAL) sensor->value = (snsr.value - 273150000) / 1000000.0; else if (sensor->type == FANRPM) sensor->value = snsr.value; return 1; #elif defined(__FreeBSD__) || defined(__DragonFly__) int value; size_t len = sizeof(value); if ((sysctlbyname(sensor->name, &value, &len, NULL, 0)) != -1) { sensor->value = (float) (value - 2732) / 10; return 1; } #endif return 0; } Eina_List * sensors_find(void) { Eina_List *sensors = NULL; #if defined(__OpenBSD__) Sensor *sensor; int mibs[5] = { CTL_HW, HW_SENSORS, 0, 0, 0 }; int devn, n; struct sensor snsr; struct sensordev snsrdev; size_t slen = sizeof(struct sensor); size_t sdlen = sizeof(struct sensordev); char buf[32]; enum sensor_type type; for (devn = 0;; devn++) { mibs[2] = devn; if (sysctl(mibs, 3, &snsrdev, &sdlen, NULL, 0) == -1) { if (errno == ENOENT) break; continue; } for (type = 0; type < SENSOR_MAX_TYPES; type++) { mibs[3] = type; for (n = 0; n < snsrdev.sensors_count; n++) { mibs[4] = n; if (sysctl(mibs, 5, &snsr, &slen, NULL, 0) == -1) continue; if (!slen || ((snsr.type != SENSOR_TEMP) && (snsr.type != SENSOR_FANRPM))) continue; if ((snsr.flags & SENSOR_FINVALID)) continue; sensor = calloc(1, sizeof(Sensor)); if (sensor) { sensor->name = strdup(snsrdev.xname); snprintf(buf, sizeof(buf), "%i", n); sensor->child_name = strdup(buf); if (snsr.type == SENSOR_TEMP) sensor->type = THERMAL; else if (snsr.type == SENSOR_FANRPM) sensor->type = FANRPM; memcpy(sensor->mibs, &mibs, sizeof(mibs)); sensors = eina_list_append(sensors, sensor); } } } } #elif defined(__FreeBSD__) || defined(__DragonFly__) Sensor *sensor; int value; char buf[256]; size_t len = sizeof(value); if ((sysctlbyname("hw.acpi.thermal.tz0.temperature", &value, &len, NULL, 0)) != -1) { sensor = calloc(1, sizeof(Sensor)); if (sensor) { sensor->name = strdup("hw.acpi.thermal.tz0.temperature"); sensor->value = (float) (value - 2732) / 10; sensors = eina_list_append(sensors, sensor); } } int n = system_cpu_count_get(); for (int i = 0; i < n; i++) { len = sizeof(value); snprintf(buf, sizeof(buf), "dev.cpu.%i.temperature", i); if ((sysctlbyname(buf, &value, &len, NULL, 0)) != -1) { sensor = calloc(1, sizeof(Sensor)); if (sensor) { sensor->name = strdup(buf); sensor->value = (float) (value - 2732) / 10; sensors = eina_list_append(sensors, sensor); } } } #elif defined(__linux__) Sensor *sensor; DIR *dir; struct dirent *dh; char buf[4096]; int seen[128]; dir = opendir("/sys/class/hwmon"); if (!dir) return NULL; while ((dh = readdir(dir)) != NULL) { struct dirent **names = NULL; snprintf(buf, sizeof(buf), "/sys/class/hwmon/%s", dh->d_name); char *link = realpath(buf, NULL); if (!link) continue; int n = scandir(link, &names, 0, alphasort); if (n < 0) continue; int idx = 0; memset(&seen, 0, sizeof(seen)); for (int i = 0; i < n; i++) { if ((!strncmp(names[i]->d_name, "temp", 4)) || (!strncmp(names[i]->d_name, "fan", 3))) { int id = atoi(names[i]->d_name + 4); if ((!id) || (id > sizeof(seen))) { free(names[i]); continue; } int found = 0; for (int j = 0; seen[j] != 0 && j < sizeof(seen); j++) if (seen[j] == id) found = 1; if (found) { free(names[i]); continue; } snprintf(buf, sizeof(buf), "%s/fan%i_input", link, id); if (ecore_file_exists(buf)) { sensor = calloc(1, sizeof(Sensor)); if (sensor) { sensor->type = FANRPM; sensor->path = strdup(buf); snprintf(buf, sizeof(buf), "%s/name", link); sensor->name = file_contents(buf); snprintf(buf, sizeof(buf), "%s/fan%i_label", link, id); if (ecore_file_exists(buf)) sensor->child_name = file_contents(buf); else { snprintf(buf, sizeof(buf), "fan%i", id); sensor->child_name = strdup(buf); } sensors = eina_list_append(sensors, sensor); } } snprintf(buf, sizeof(buf), "%s/temp%i_input", link, id); if (ecore_file_exists(buf)) { sensor = calloc(1, sizeof(Sensor)); if (sensor) { sensor->type = THERMAL; sensor->path = strdup(buf); snprintf(buf, sizeof(buf), "%s/name", link); sensor->name = file_contents(buf); snprintf(buf, sizeof(buf), "%s/temp%i_label", link, id); if (ecore_file_exists(buf)) sensor->child_name = file_contents(buf); else { snprintf(buf, sizeof(buf), "%i", id); sensor->child_name = strdup(buf); } sensors = eina_list_append(sensors, sensor); } } seen[idx++] = id; } free(names[i]); } free(names); free(link); } closedir(dir); #elif defined(__MacOS__) #endif return sensors; } Eina_List * batteries_find(void) { Eina_List *list = NULL; #if defined(__OpenBSD__) struct sensordev snsrdev; size_t sdlen = sizeof(struct sensordev); int mibs[5] = { CTL_HW, HW_SENSORS, 0, 0, 0 }; int devn; for (devn = 0; ; devn++) { mibs[2] = devn; if (sysctl(mibs, 3, &snsrdev, &sdlen, NULL, 0) == -1) { if (errno == ENXIO) continue; if (errno == ENOENT) break; } if (!strncmp(snsrdev.xname, "acpibat", 7)) { Battery *bat = calloc(1, sizeof(Battery)); if (bat) { bat->name = strdup(snsrdev.xname); bat->model = strdup("Unknown"); bat->vendor = strdup("Unknown"); bat->mibs[0] = mibs[0]; bat->mibs[1] = mibs[1]; bat->mibs[2] = mibs[2]; bat->present = 1; list = eina_list_append(list, bat); } } } #elif defined(__FreeBSD__) int n_units, fd; union acpi_battery_ioctl_arg battio; fd = open("/dev/acpi", O_RDONLY); if (fd == -1) return NULL; if (ioctl(fd, ACPIIO_BATT_GET_UNITS, &n_units) == -1) return NULL; for (int i = 0; i < n_units; i++) { battio.unit = i; if (ioctl(fd, ACPIIO_BATT_GET_BIX, &battio) != -1) { Battery *bat = calloc(1, sizeof(Battery)); if (bat) { if (battio.bst.state == ACPI_BATT_STAT_NOT_PRESENT) bat->present = 0; else bat->present = 1; bat->vendor = strdup(battio.bix.oeminfo); bat->model = strdup(battio.bix.model); bat->unit = i; list = eina_list_append(list, bat); } } } close(fd); #elif defined(__linux__) char *type; struct dirent **names; char *buf; char path[PATH_MAX]; int i, n; n = scandir("/sys/class/power_supply", &names, 0, alphasort); if (n < 0) return 0; for (i = 0; i < n; i++) { snprintf(path, sizeof(path), "/sys/class/power_supply/%s/type", names[i]->d_name); type = file_contents(path); if (type) { if (!strncmp(type, "Battery", 7)) { Battery *bat = calloc(1, sizeof(Battery)); if (bat) { bat->name = strdup(names[i]->d_name); snprintf(path, sizeof(path), "/sys/class/power_supply/%s/manufacturer", names[i]->d_name); bat->vendor = file_contents(path); snprintf(path, sizeof(path), "/sys/class/power_supply/%s/model_name", names[i]->d_name); bat->model = file_contents(path); snprintf(path, sizeof(path), "/sys/class/power_supply/%s/present", names[i]->d_name); bat->present = 1; buf = file_contents(path); if (buf) { bat->present = atoi(buf); free(buf); } list = eina_list_append(list, bat); } } free(type); } free(names[i]); } free(names); #endif return list; } void battery_free(Battery *bat) { if (bat->name) free(bat->name); if (bat->model) free(bat->model); if (bat->vendor) free(bat->vendor); free(bat); } void battery_update(Battery *bat) { double charge_full = 0, charge_current = 0; #if defined(__OpenBSD__) size_t slen = sizeof(struct sensor); struct sensor snsr; bat->mibs[3] = SENSOR_WATTHOUR; bat->mibs[4] = 0; if (sysctl(bat->mibs, 5, &snsr, &slen, NULL, 0) != -1) charge_full = (double) snsr.value; bat->mibs[4] = 3; if (sysctl(bat->mibs, 5, &snsr, &slen, NULL, 0) != -1) charge_current = (double) snsr.value; if ((!charge_current) || (!charge_full)) { bat->mibs[3] = SENSOR_AMPHOUR; bat->mibs[4] = 0; if (sysctl(bat->mibs, 5, &snsr, &slen, NULL, 0) != -1) charge_full = (double) snsr.value; bat->mibs[4] = 3; if (sysctl(bat->mibs, 5, &snsr, &slen, NULL, 0) != -1) charge_current = (double) snsr.value; } #elif defined(__FreeBSD__) || defined(__DragonFly__) int fd; union acpi_battery_ioctl_arg battio; if (!bat->present) return; fd = open("/dev/acpi", O_RDONLY); if (fd == -1) return; battio.unit = bat->unit; if (ioctl(fd, ACPIIO_BATT_GET_BIX, &battio) != -1) { if (battio.bif.lfcap == 0) charge_full = battio.bif.dcap; else charge_full = battio.bif.lfcap; battio.unit = bat->unit; if (ioctl(fd, ACPIIO_BATT_GET_BST, &battio) != -1) charge_current = battio.bst.cap; } close(fd); #elif defined(__linux__) char path[PATH_MAX]; struct dirent *dh; struct stat st; DIR *dir; char *buf, *link = NULL, *naming = NULL; naming = NULL; snprintf(path, sizeof(path), "/sys/class/power_supply/%s", bat->name); if ((stat(path, &st) < 0) || (!S_ISDIR(st.st_mode))) return; link = realpath(path, NULL); if (!link) return; dir = opendir(path); if (!dir) goto done; while ((dh = readdir(dir)) != NULL) { char *e; if (dh->d_name[0] == '.') continue; if ((e = strstr(dh->d_name, "_full\0"))) { naming = strndup(dh->d_name, e - dh->d_name); break; } } closedir(dir); if (naming) { snprintf(path, sizeof(path), "%s/%s_full", link, naming); buf = file_contents(path); if (buf) { charge_full = atol(buf); free(buf); } snprintf(path, sizeof(path), "%s/%s_now", link, naming); buf = file_contents(path); if (buf) { charge_current = atol(buf); free(buf); } free(naming); } else { snprintf(path, sizeof(path), "%s/capacity_level", link); buf = file_contents(path); if (buf) { if (buf[0] == 'F') bat->charge_current = 100; else if (buf[0] == 'H') bat->charge_current = 75; else if (buf[0] == 'N') bat->charge_current = 50; else if (buf[0] == 'L') bat->charge_current = 25; else if (buf[0] == 'C') bat->charge_current = 5; free(buf); } } done: if (link) free(link); #else #endif bat->charge_full = charge_full; bat->charge_current = charge_current; if (charge_full) bat->percent = 100 * (charge_current / charge_full); else bat->percent = 0; } Eina_Bool power_ac_present(void) { Eina_Bool have_ac = 0; #if defined(__OpenBSD__) struct sensordev snsrdev; size_t sdlen = sizeof(struct sensordev); static int mibs[5] = { CTL_HW, HW_SENSORS, 0, 0, 0 }; int devn; for (devn = 0; !mibs[3] ; devn++) { mibs[2] = devn; if (sysctl(mibs, 3, &snsrdev, &sdlen, NULL, 0) == -1) { if (errno == ENXIO) continue; if (errno == ENOENT) break; } if (!strncmp(snsrdev.xname, "acpiac", 6)) { mibs[3] = 9; mibs[4] = 0; break; } } if (mibs[3] == 9) { struct sensor snsr; size_t slen = sizeof(struct sensor); if (sysctl(mibs, 5, &snsr, &slen, NULL, 0) != -1) have_ac = (int)snsr.value; } #elif defined(__FreeBSD__) || defined(__DragonFly__) int val, fd; fd = open("/dev/acpi", O_RDONLY); if (fd != -1) { if (ioctl(fd, ACPIIO_ACAD_GET_STATUS, &val) != -1) have_ac = val; close(fd); } #elif defined(__linux__) char *buf = file_contents("/sys/class/power_supply/AC/online"); if (buf) { have_ac = atoi(buf); free(buf); } #endif return have_ac; }