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