/** * collectd - src/apple_sensors.c * Copyright (C) 2006,2007 Florian octo Forster * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Florian octo Forster **/ #include "collectd.h" #include "plugin.h" #include "utils/common/common.h" #if HAVE_MACH_MACH_TYPES_H #include #endif #if HAVE_MACH_MACH_INIT_H #include #endif #if HAVE_MACH_MACH_ERROR_H #include #endif #if HAVE_MACH_MACH_PORT_H #include #endif #if HAVE_COREFOUNDATION_COREFOUNDATION_H #include #endif #if HAVE_IOKIT_IOKITLIB_H #include #endif #if HAVE_IOKIT_IOTYPES_H #include #endif static mach_port_t io_master_port = MACH_PORT_NULL; static int as_init(void) { kern_return_t status; if (io_master_port != MACH_PORT_NULL) { mach_port_deallocate(mach_task_self(), io_master_port); io_master_port = MACH_PORT_NULL; } status = IOMasterPort(MACH_PORT_NULL, &io_master_port); if (status != kIOReturnSuccess) { ERROR("IOMasterPort failed: %s", mach_error_string(status)); io_master_port = MACH_PORT_NULL; return -1; } return 0; } static void as_submit(const char *type, const char *type_instance, double val) { value_list_t vl = VALUE_LIST_INIT; vl.values = &(value_t){.gauge = val}; vl.values_len = 1; sstrncpy(vl.plugin, "apple_sensors", sizeof(vl.plugin)); sstrncpy(vl.type, type, sizeof(vl.type)); sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance)); plugin_dispatch_values(&vl); } static int as_read(void) { kern_return_t status; io_iterator_t iterator; io_object_t io_obj; CFMutableDictionaryRef prop_dict; CFTypeRef property; char type[128]; char inst[128]; int value_int; double value_double; if (!io_master_port || (io_master_port == MACH_PORT_NULL)) return -1; status = IOServiceGetMatchingServices( io_master_port, IOServiceNameMatching("IOHWSensor"), &iterator); if (status != kIOReturnSuccess) { ERROR("IOServiceGetMatchingServices failed: %s", mach_error_string(status)); return -1; } while ((io_obj = IOIteratorNext(iterator))) { prop_dict = NULL; status = IORegistryEntryCreateCFProperties( io_obj, &prop_dict, kCFAllocatorDefault, kNilOptions); if (status != kIOReturnSuccess) { DEBUG("IORegistryEntryCreateCFProperties failed: %s", mach_error_string(status)); continue; } /* Copy the sensor type. */ property = NULL; if (!CFDictionaryGetValueIfPresent(prop_dict, CFSTR("type"), &property)) continue; if (CFGetTypeID(property) != CFStringGetTypeID()) continue; if (!CFStringGetCString(property, type, sizeof(type), kCFStringEncodingASCII)) continue; type[sizeof(type) - 1] = '\0'; /* Copy the sensor location. This will be used as `instance'. */ property = NULL; if (!CFDictionaryGetValueIfPresent(prop_dict, CFSTR("location"), &property)) continue; if (CFGetTypeID(property) != CFStringGetTypeID()) continue; if (!CFStringGetCString(property, inst, sizeof(inst), kCFStringEncodingASCII)) continue; inst[sizeof(inst) - 1] = '\0'; for (int i = 0; i < 128; i++) { if (inst[i] == '\0') break; else if (isalnum(inst[i])) inst[i] = (char)tolower(inst[i]); else inst[i] = '_'; } /* Get the actual value. Some computation, based on the `type' * is neccessary. */ property = NULL; if (!CFDictionaryGetValueIfPresent(prop_dict, CFSTR("current-value"), &property)) continue; if (CFGetTypeID(property) != CFNumberGetTypeID()) continue; if (!CFNumberGetValue(property, kCFNumberIntType, &value_int)) continue; /* Found e.g. in the 1.5GHz PowerBooks */ if (strcmp(type, "temperature") == 0) { value_double = ((double)value_int) / 65536.0; sstrncpy(type, "temperature", sizeof(type)); } else if (strcmp(type, "temp") == 0) { value_double = ((double)value_int) / 10.0; sstrncpy(type, "temperature", sizeof(type)); } else if (strcmp(type, "fanspeed") == 0) { value_double = ((double)value_int) / 65536.0; sstrncpy(type, "fanspeed", sizeof(type)); } else if (strcmp(type, "voltage") == 0) { /* Leave this to the battery plugin. */ continue; } else if (strcmp(type, "adc") == 0) { value_double = ((double)value_int) / 10.0; sstrncpy(type, "fanspeed", sizeof(type)); } else { DEBUG("apple_sensors: Read unknown sensor type: %s", type); value_double = (double)value_int; } as_submit(type, inst, value_double); CFRelease(prop_dict); IOObjectRelease(io_obj); } /* while (iterator) */ IOObjectRelease(iterator); return 0; } /* int as_read */ void module_register(void) { plugin_register_init("apple_sensors", as_init); plugin_register_read("apple_sensors", as_read); } /* void module_register */