r4925 - in developers/werner: . athintd

werner at docs.openmoko.org werner at docs.openmoko.org
Mon Feb 23 15:23:32 CET 2009


Author: werner
Date: 2009-02-23 15:23:31 +0100 (Mon, 23 Feb 2009)
New Revision: 4925

Added:
   developers/werner/athintd/
   developers/werner/athintd/Makefile
   developers/werner/athintd/athintd.c
Log:
Daemon to execute an arbitrary command when the AR6k driver signals
a firmware failure. Requires the AR6k driver to be compiled with
-DSEND_EVENT_TO_APP. Work in progress.



Added: developers/werner/athintd/Makefile
===================================================================
--- developers/werner/athintd/Makefile	                        (rev 0)
+++ developers/werner/athintd/Makefile	2009-02-23 14:23:31 UTC (rev 4925)
@@ -0,0 +1,35 @@
+CC=arm-angstrom-linux-gnueabi-gcc
+
+CFLAGS=-Wall -Wshadow -g -O
+LDFLAGS=-lm
+
+PREFIX=/usr
+
+NAME=athintd
+OBJS=athintd.o
+
+.PHONY:		all install uninstall clean depend spotless
+
+all:		$(NAME)
+
+$(NAME):	$(OBJS)
+
+install:	$(NAME)
+		install -D $(NAME) $(PREFIX)/bin/$(NAME)
+
+uninstall:
+		rm -f $(PREFIX)/bin/$(NAME)
+
+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 $(NAME)

Added: developers/werner/athintd/athintd.c
===================================================================
--- developers/werner/athintd/athintd.c	                        (rev 0)
+++ developers/werner/athintd/athintd.c	2009-02-23 14:23:31 UTC (rev 4925)
@@ -0,0 +1,183 @@
+/*
+ * athintd.c - Atheros AR6k Interrupt Handling Daemon
+ *
+ * Copyright (C) 2009 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 <unistd.h>
+#include <string.h>
+#include <syslog.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <linux/if.h>
+#include <linux/if_link.h>
+#include <linux/wireless.h>
+
+
+#define	WMI_ERROR_REPORT_EVENTID	(0x1001+1022-1010)
+
+
+/*
+ * struct iw_point is traditionally accessed with weird pointer operations.
+ * We keep it simple and just use what's there :-)
+ */
+
+struct iw_point_msg {
+	uint16_t	length;         /* number of fields or size in bytes */
+	uint16_t	flags;          /* Optional params */
+};
+
+
+static int debug;
+static const char *cmd;
+
+
+#if 0
+
+            ar6000_send_event_to_app(ar, WMI_ERROR_REPORT_EVENTID,
+                                     (A_UINT8 *)&errEvent,
+                                     sizeof(WMI_TARGET_ERROR_REPORT_EVENT));
+
+    wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
+
+RTM_NEWLINK
+#endif
+
+
+static void custom(const void *data, int len)
+{
+	uint16_t id;
+
+	if (debug)
+		fprintf(stderr, "ID 0x%02x 0%02x\n",
+		    ((const uint8_t *) data)[0],
+		    ((const uint8_t *) data)[1]);
+	if (len < 2)
+		return;
+	memcpy(&id, data, 2);
+	if (id != WMI_ERROR_REPORT_EVENTID)
+		return;
+	syslog(LOG_ERR, "running %s", cmd);
+	system(cmd);
+}
+
+
+static void wireless(const void *data, int len)
+{
+	const void *pos, *end = data+len;
+	struct iw_event iwe;
+	struct iw_point_msg iw_point;
+	const void *payload;
+
+	for (pos = data; pos+IW_EV_LCP_LEN <= end; pos += iwe.len) {
+		memcpy(&iwe, pos, IW_EV_LCP_LEN);
+		if (debug)
+			fprintf(stderr, "CMD 0x%04x\n", iwe.cmd);
+		if (iwe.len <= IW_EV_LCP_LEN)
+			return;
+		if (iwe.cmd != IWEVCUSTOM)
+			continue;
+		memcpy(&iw_point, pos+IW_EV_LCP_LEN, sizeof(iw_point));
+		if (debug)
+			fprintf(stderr, "len %u flags 0x%x\n",
+			    iw_point.length, iw_point.flags);
+		payload = pos+IW_EV_LCP_LEN+sizeof(iw_point);
+		if (payload+iw_point.length > end)
+			return;
+		custom(payload, iw_point.length);
+	}
+}
+
+
+static void newlink(const struct ifinfomsg *msg, ssize_t len)
+{
+	const struct rtattr *attr;
+
+	for (attr = IFLA_RTA(msg); RTA_OK(attr, len);
+	    attr = RTA_NEXT(attr, len))
+		if (attr->rta_type == IFLA_WIRELESS)
+			wireless(RTA_DATA(attr), RTA_PAYLOAD(attr));
+}
+
+
+static void msg(const void *buf, ssize_t len)
+{
+	const struct nlmsghdr *hdr;
+
+	for (hdr = buf; NLMSG_OK(hdr, len); hdr = NLMSG_NEXT(hdr, len)) {
+		switch (hdr->nlmsg_type) {
+		case NLMSG_NOOP:
+		case NLMSG_OVERRUN:
+		case NLMSG_DONE:
+		case NLMSG_ERROR:
+			return;
+		case RTM_NEWLINK:
+			newlink(NLMSG_DATA(hdr), IFLA_PAYLOAD(hdr));
+			break;
+		}
+	}
+}
+
+
+static void loop(void)
+{
+	struct sockaddr_nl addr;
+	int s;
+	ssize_t got;
+
+	s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
+	if (s < 0) {
+		perror("socket");
+		exit(1);
+	}
+
+	memset(&addr, 0, sizeof(addr));
+	addr.nl_family = AF_NETLINK;
+	addr.nl_groups = RTMGRP_LINK;
+
+	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		perror("bind");
+                exit(1);
+        }
+
+	while (1) {
+		char buf[4096];
+
+		got = read(s, buf, sizeof(buf));
+		if (got < 0) {
+			perror("read");
+			exit(1);
+		}
+		msg(buf, got);
+	}
+}
+
+
+static void usage(const char *name)
+{
+	fprintf(stderr, "usage: %s command\n", name);
+	exit(1);
+}
+
+
+int main(int argc, char **argv)
+{
+	if (argc != 2)
+		usage(*argv);
+	cmd = argv[1];
+	openlog("athintd", LOG_CONS, LOG_USER);
+	loop();
+	return 0;
+}




More information about the commitlog mailing list