#include "mts_supercap.h" extern struct gpio_pin *gpio_pin_by_attr_name(const char *name); static supercap_info_t supercap = { .name = "Super Cap", .label_monitor = "supercap-monitor", .signal = SIGPWR, .pid = 0, .pwf_count = 0, .pin_is_one = 0, }; ssize_t mts_attr_show_supercap_monitor(struct device *dev, struct device_attribute *attr, char *buf) { int ret; //button_info_t *button = button_by_monitor_name(attr->attr.name); //if (!button) { // return -ENODEV; //} mutex_lock(&mts_io_mutex); ret = sprintf(buf, "%d %d\n", supercap.pid, supercap.signal); mutex_unlock(&mts_io_mutex); return ret; } ssize_t mts_attr_store_supercap_monitor(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { pid_t pid; int signal; int result = sscanf(buf, "%i %i", &pid, &signal); //button_info_t *button = button_by_monitor_name(attr->attr.name); //if (!button) { // return -ENODEV; //} if (result != 2) { return -EINVAL; } if(result == 2) { mutex_lock(&mts_io_mutex); supercap.pid = pid; supercap.signal = signal; mutex_unlock(&mts_io_mutex); } return count; } static void supercap_worker(struct work_struct *ignored); static DECLARE_DELAYED_WORK(supercap_work, supercap_worker); static void supercap_worker(struct work_struct *ignored) { struct gpio_pin *pin; struct pid *vpid; int running_on_cap = 0; mutex_lock(&mts_io_mutex); pin = gpio_pin_by_attr_name("power-fail"); if (pin) { running_on_cap = !gpio_get_value(pin->pin.gpio); } if (supercap.pid > 0) { vpid = find_vpid(supercap.pid); } if (vpid) { if (running_on_cap == 0 && supercap.pwf_count == 0) { schedule_delayed_work(&supercap_work, SUPERCAP_CHECK_INTERVAL); } else if ( (supercap.pwf_count >= 0) && (supercap.pwf_count < SUPERCAP_TOTAL_INTERVALS) ) { /* check if 90% of checks were running_on_cap == 1 */ supercap.pwf_count++; if (running_on_cap == 1) { supercap.pin_is_one++; } if (supercap.pin_is_one >= 45) { /* send configured signal to reset handler pid */ log_debug("Super Cap positives %d long signal", supercap.pin_is_one); kill_pid(vpid, supercap.signal, 1); /* reset and start over since hit the reset condition (maybe we should clean up and go away?) */ supercap.pwf_count = 0; supercap.pin_is_one = 0; } } else if (supercap.pwf_count == SUPERCAP_TOTAL_INTERVALS) { /* reset and start over since didn't reach 90% at total intervals */ supercap.pwf_count = 0; supercap.pin_is_one = 0; } } /* vpid */ mutex_unlock(&mts_io_mutex); schedule_delayed_work(&supercap_work, SUPERCAP_CHECK_INTERVAL); } void init_supercap_worker(void) { supercap_worker(NULL); } void cleanup_supercap_worker(void) { cancel_delayed_work_sync(&supercap_work); } DEVICE_ATTR_MTS(dev_attr_supercap_monitor, supercap.label_monitor, mts_attr_show_supercap_monitor, mts_attr_store_supercap_monitor);