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