r4680 - in developers/werner: . neodog
werner at docs.openmoko.org
werner at docs.openmoko.org
Mon Sep 29 08:07:39 CEST 2008
Author: werner
Date: 2008-09-29 08:07:38 +0200 (Mon, 29 Sep 2008)
New Revision: 4680
Added:
developers/werner/neodog/
developers/werner/neodog/Makefile
developers/werner/neodog/event.c
developers/werner/neodog/neodog.c
developers/werner/neodog/neodog.h
developers/werner/neodog/pmu.c
Log:
Tough watchdog daemon.
Added: developers/werner/neodog/Makefile
===================================================================
--- developers/werner/neodog/Makefile (rev 0)
+++ developers/werner/neodog/Makefile 2008-09-29 06:07:38 UTC (rev 4680)
@@ -0,0 +1,25 @@
+CC=arm-angstrom-linux-gnueabi-gcc
+
+CFLAGS=-Wall -Wshadow -g -O
+
+OBJS=neodog.o event.o pmu.o
+
+.PHONY: all clean depend spotless
+
+all: neodog
+
+neodog: $(OBJS)
+
+depend:
+ $(CPP) $(CFLAGS) -MM -MG *.c >.depend || \
+ { rm -f .depend; exit 1; }
+
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
+
+clean:
+ rm -f $(OBJS) .depend
+
+spotless: clean
+ rm -f neodog
Added: developers/werner/neodog/event.c
===================================================================
--- developers/werner/neodog/event.c (rev 0)
+++ developers/werner/neodog/event.c 2008-09-29 06:07:38 UTC (rev 4680)
@@ -0,0 +1,58 @@
+/*
+ * event.c - Direct I2C polling in case events are lost
+ *
+ * Copyright (C) 2008 by OpenMoko, Inc.
+ * Written by Werner Almesberger <werner at openmoko.org>
+ * All Rights Reserved
+ *
+ * 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 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+
+#include <linux/input.h>
+
+#include "neodog.h"
+
+
+#define EVENT_DEVICE "/dev/input/event2"
+
+
+int process_event(int fd)
+{
+ struct input_event ev;
+ ssize_t got;
+
+ got = read(fd, &ev, sizeof(ev));
+ if (got < 0) {
+ perror("read");
+ return 0;
+ }
+ if (got != sizeof(ev))
+ return 0;
+ if (ev.type != EV_KEY)
+ return 0;
+ if (ev.code != KEY_POWER)
+ return 0;
+ return ev.value ? 1 : -1;
+}
+
+
+int open_event(void)
+{
+ int fd;
+
+ fd = open(EVENT_DEVICE, O_RDONLY);
+ if (fd < 0) {
+ perror(EVENT_DEVICE);
+ exit(1);
+ }
+ return fd;
+}
Added: developers/werner/neodog/neodog.c
===================================================================
--- developers/werner/neodog/neodog.c (rev 0)
+++ developers/werner/neodog/neodog.c 2008-09-29 06:07:38 UTC (rev 4680)
@@ -0,0 +1,133 @@
+/*
+ * neodog.c - Tough watchdog daemon
+ *
+ * Copyright (C) 2008 by OpenMoko, Inc.
+ * Written by Werner Almesberger <werner at openmoko.org>
+ * All Rights Reserved
+ *
+ * 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 2 of the License, or
+ * (at your option) any later version.
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+#include <sched.h>
+#include <poll.h>
+#include <sys/mman.h>
+
+#include <linux/unistd.h>
+#include <linux/reboot.h>
+
+#include "neodog.h"
+
+
+#define TIMEOUT 8 /* power down if ONKEY is held for 8 seconds */
+
+
+static void invulnerabilize(void)
+{
+ struct sched_param prm;
+
+ if (mlockall(MCL_CURRENT | MCL_FUTURE) < 0) {
+ perror("mlockall");
+ exit(1);
+ }
+ prm.sched_priority = sched_get_priority_max(SCHED_FIFO);
+ if (prm.sched_priority < 0) {
+ perror("sched_get_priority_max SCHED_FIFO");
+ exit(1);
+ }
+ if (sched_setscheduler(0,SCHED_FIFO,&prm) < 0) {
+ perror("sched_setscheduler SCHED_FIFO");
+ exit(1);
+ }
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ signal(SIGTERM, SIG_IGN);
+ signal(SIGUSR1, SIG_IGN);
+ signal(SIGUSR2, SIG_IGN);
+}
+
+
+static void power_off(int sig)
+{
+#ifdef DEBUG
+ fprintf(stderr, "***ALARM***\n");
+ return;
+#endif
+ syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
+ LINUX_REBOOT_CMD_POWER_OFF);
+}
+
+
+static void set_alarm(int on)
+{
+ static int is_on = 0;
+
+#ifdef DEBUG
+ fprintf(stderr, "set_alarm(%d)\n", on);
+#endif
+ if (on == is_on)
+ return;
+ is_on = on;
+ if (on)
+ alarm(TIMEOUT);
+ else
+ alarm(0);
+}
+
+
+int main(void)
+{
+ struct pollfd event = {
+ .fd = open_event(),
+ .events = POLLIN,
+ };
+ time_t next = 0;
+ int pmu;
+
+ /*
+ * It's a bit overkill to listen to events and to pull the PMU.
+ * The events give us better response granularity, but we also need to
+ * poll in case something overruns the event buffer.
+ */
+ pmu = open_pmu();
+ invulnerabilize();
+ signal(SIGALRM, power_off);
+ while (1) {
+ int fds;
+ time_t now;
+
+ fds = poll(&event, 1, 1000);
+ if (fds < 0) {
+ perror("poll");
+ return 1;
+ }
+ time(&now);
+ if (fds) {
+ switch (process_event(event.fd)) {
+ case 0:
+ break;
+ case 1:
+ set_alarm(0);
+ break;
+ case -1:
+ set_alarm(0);
+ break;
+ default:
+ abort();
+ }
+ }
+ if (!fds || now >= next) {
+ set_alarm(get_onkey(pmu));
+ next = now+1;
+ }
+ }
+}
Added: developers/werner/neodog/neodog.h
===================================================================
--- developers/werner/neodog/neodog.h (rev 0)
+++ developers/werner/neodog/neodog.h 2008-09-29 06:07:38 UTC (rev 4680)
@@ -0,0 +1,23 @@
+/*
+ * neodog.h - Tough watchdog daemon
+ *
+ * Copyright (C) 2008 by OpenMoko, Inc.
+ * Written by Werner Almesberger <werner at openmoko.org>
+ * All Rights Reserved
+ *
+ * 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 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef NEODOG_H
+#define NEODOG_H
+
+int get_onkey(int fd);
+int open_pmu(void);
+
+int process_event(int fd);
+int open_event(void);
+
+#endif /* !NEODOG_H */
Added: developers/werner/neodog/pmu.c
===================================================================
--- developers/werner/neodog/pmu.c (rev 0)
+++ developers/werner/neodog/pmu.c 2008-09-29 06:07:38 UTC (rev 4680)
@@ -0,0 +1,65 @@
+/*
+ * pmu.c - Direct I2C polling in case events are lost
+ *
+ * Copyright (C) 2008 by OpenMoko, Inc.
+ * Written by Werner Almesberger <werner at openmoko.org>
+ * All Rights Reserved
+ *
+ * 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 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+
+#include "neodog.h"
+
+
+#define I2C_DEVICE "/dev/i2c-0"
+#define I2C_ADDRESS 0x73
+
+#define OOCSTAT 0x12
+#define OOCSTAT_ONKEY 1
+
+
+int get_onkey(int fd)
+{
+ uint8_t oocstat;
+ struct i2c_smbus_ioctl_data msg = {
+ .read_write = I2C_SMBUS_READ,
+ .command = OOCSTAT,
+ .size = I2C_SMBUS_BYTE_DATA,
+ .data = (void *) &oocstat,
+ };
+
+ if (ioctl(fd, I2C_SMBUS, (void *) &msg) < 0) {
+ perror("ioctl(I2C_RDWR)");
+ exit(1);
+ }
+ return !(oocstat & OOCSTAT_ONKEY);
+}
+
+
+int open_pmu(void)
+{
+ int fd;
+
+ fd = open(I2C_DEVICE, O_RDWR);
+ if (fd < 0) {
+ perror(I2C_DEVICE);
+ exit(1);
+ }
+ if (ioctl(fd, I2C_SLAVE_FORCE, I2C_ADDRESS) < 0) {
+ perror("ioctl(I2C_SLAVE_FORCE)");
+ exit(1);
+ }
+ return fd;
+}
More information about the commitlog
mailing list