Add discover user event
authorGeoff Levand <geoffrey.levand@am.sony.com>
Sun, 12 Apr 2009 15:11:54 +0000 (15:11 +0000)
committerJeremy Kerr <jk@ozlabs.org>
Tue, 30 Jun 2009 07:29:22 +0000 (15:29 +0800)
Add a gereric event interface to pb-discover.

Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
discover/device-handler.c
discover/event-parser.c [new file with mode: 0644]
discover/parser.h
discover/pb-discover.c
discover/user-event.c [new file with mode: 0644]
discover/user-event.h [new file with mode: 0644]
rules.mk

index 908409c6540ff52c71b3962d700486a38d309f76..c72390b438d7222540b467619d6f2865117eb503 100644 (file)
@@ -335,6 +335,52 @@ static int handle_remove_udev_event(struct device_handler *handler,
        return 0;
 }
 
+static int handle_add_user_event(struct device_handler *handler,
+               struct event *event)
+{
+       struct device *device;
+
+       assert(event->device);
+
+       device = talloc_zero(handler, struct device);
+
+       if (!device)
+               goto fail;
+
+       device->id = talloc_strdup(device, event->device);
+       list_init(&device->boot_options);
+
+       parse_user_event(device, event);
+
+       discover_server_notify_add(handler->server, device);
+
+       /* add device to handler device array */
+       device_handler_add(handler, device);
+
+       return 0;
+
+fail:
+       talloc_free(device);
+       return 0;
+}
+
+static int handle_remove_user_event(struct device_handler *handler,
+               struct event *event)
+{
+       struct device *device = device_handler_find(handler, event->device);
+
+       if (!device)
+               return 0;
+
+       discover_server_notify_remove(handler->server, device);
+
+       /* remove device from handler device array */
+       device_handler_remove(handler, device);
+
+       talloc_free(device);
+       return 0;
+}
+
 int device_handler_event(struct device_handler *handler,
                struct event *event)
 {
@@ -356,6 +402,18 @@ int device_handler_event(struct device_handler *handler,
                }
                break;
        case EVENT_TYPE_USER:
+               switch (event->action) {
+               case EVENT_ACTION_ADD:
+                       rc = handle_add_user_event(handler, event);
+                       break;
+               case EVENT_ACTION_REMOVE:
+                       rc = handle_remove_user_event(handler, event);
+                       break;
+               default:
+                       pb_log("%s unknown action: %d\n", __func__,
+                               event->action);
+                       break;
+               }
                break;
        default:
                pb_log("%s unknown type: %d\n", __func__, event->type);
diff --git a/discover/event-parser.c b/discover/event-parser.c
new file mode 100644 (file)
index 0000000..0cfda9a
--- /dev/null
@@ -0,0 +1,55 @@
+#define _GNU_SOURCE
+
+#include <assert.h>
+
+#include "log/log.h"
+#include "talloc/talloc.h"
+#include "event.h"
+#include "parser-utils.h"
+
+int parse_user_event(struct device *device, struct event *event)
+{
+       struct boot_option *opt;
+       const char *p;
+
+       opt = talloc_zero(device, struct boot_option);
+
+       if (!opt)
+               goto fail;
+
+       p = event_get_param(event, "name");
+
+       if (!p) {
+               pb_log("%s: no name found\n", __func__);
+               goto fail;
+       }
+
+       opt->id = talloc_asprintf(opt, "%s#%s", device->id, p);
+       opt->name = talloc_strdup(opt, p);
+
+       p = event_get_param(event, "image");
+       assert(p);
+
+       if (!p) {
+               pb_log("%s: no image found\n", __func__);
+               goto fail;
+       }
+
+       opt->boot_image_file = talloc_strdup(opt, p);
+
+       p = event_get_param(event, "args");
+       assert(p);
+
+       opt->boot_args = talloc_strdup(opt, p);
+
+       opt->description = talloc_asprintf(opt, "%s %s", opt->boot_image_file,
+               opt->boot_args);
+
+       device_add_boot_option(device, opt);
+
+       return 0;
+
+fail:
+       talloc_free(opt);
+       return -1;
+}
index ff8657813e8d8ddc27bb7629bb1f81769d2859ef..1b88831d72b4b0d8de6f452874c0f98011114eca 100644 (file)
@@ -23,5 +23,6 @@ enum generic_icon_type {
 void parser_init(void);
 
 void iterate_parsers(struct discover_context *ctx);
+int parse_user_event(struct device *device, struct event *event);
 
 #endif /* _PARSER_H */
index 4d618147f15c8e1a18a4ec6a900dd92c240ba2b7..d7ea0caec4ee74a2e3ddbe3a47956174c7f330ed 100644 (file)
@@ -7,6 +7,7 @@
 #include <log/log.h>
 
 #include "udev.h"
+#include "user-event.h"
 #include "discover-server.h"
 #include "device-handler.h"
 
@@ -22,6 +23,7 @@ int main(void)
        struct device_handler *handler;
        struct discover_server *server;
        struct udev *udev;
+       struct user_event *uev;
        FILE *log;
 
        log = fopen("pb-discover.log", "a");
@@ -52,7 +54,12 @@ int main(void)
        if (!udev)
                return EXIT_FAILURE;
 
+       uev = user_event_init(handler);
+       if (!uev)
+               return EXIT_FAILURE;
+
        udev_trigger(udev);
+       user_event_trigger(uev);
 
        for (running = 1; running;) {
                if (waiter_poll())
diff --git a/discover/user-event.c b/discover/user-event.c
new file mode 100644 (file)
index 0000000..afc4c43
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ *  Copyright (C) 2009 Sony Computer Entertainment Inc.
+ *  Copyright 2009 Sony Corp.
+ *
+ *  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; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#define _GNU_SOURCE
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+
+#include <log/log.h>
+#include <talloc/talloc.h>
+#include <waiter/waiter.h>
+
+#include "device-handler.h"
+#include "event.h"
+#include "user-event.h"
+
+
+struct user_event {
+       struct device_handler *handler;
+       int socket;
+};
+
+static void user_event_print_event(struct event __attribute__((unused)) *event)
+{
+       const char *action, *params[] = {
+               "name", "image", "args",
+               NULL,
+       };
+       int i;
+
+       action = event->action == EVENT_ACTION_ADD ? "add" : "remove";
+
+       pb_log("user_event %s event:\n", action);
+       pb_log("\tdevice: %s\n", event->device);
+
+       for (i = 0; params[i]; i++)
+               pb_log("\t%-12s => %s\n",
+                               params[i], event_get_param(event, params[i]));
+}
+
+static void user_event_handle_message(struct user_event *uev, char *buf,
+       int len)
+{
+       int result;
+       struct event *event;
+
+       event = talloc(uev, struct event);
+       event->type = EVENT_TYPE_USER;
+
+       result = event_parse_ad_message(event, buf, len);
+
+       if (result)
+               return;
+
+       user_event_print_event(event);
+       device_handler_event(uev->handler, event);
+       talloc_free(event);
+
+       return;
+}
+
+static int user_event_process(void *arg)
+{
+       struct user_event *uev = arg;
+       char buf[PBOOT_USER_EVENT_SIZE];
+       int len;
+
+       len = recvfrom(uev->socket, buf, sizeof(buf), 0, NULL, NULL);
+
+       if (len < 0) {
+               pb_log("%s: socket read failed: %s", __func__, strerror(errno));
+               return 0;
+       }
+
+       if (len == 0) {
+               pb_log("%s: empty", __func__);
+               return 0;
+       }
+
+       pb_log("%s: %u bytes\n", __func__, len);
+
+       user_event_handle_message(uev, buf, len);
+
+       return 0;
+}
+
+static int user_event_destructor(void *arg)
+{
+       struct user_event *uev = arg;
+
+       pb_log("%s\n", __func__);
+
+       if (uev->socket >= 0)
+               close(uev->socket);
+
+       return 0;
+}
+
+struct user_event *user_event_init(struct device_handler *handler)
+{
+       struct sockaddr_un addr;
+       struct user_event *uev;
+
+       unlink(PBOOT_USER_EVENT_SOCKET);
+
+       uev = talloc(NULL, struct user_event);
+
+       uev->handler = handler;
+
+       uev->socket = socket(AF_UNIX, SOCK_DGRAM, 0);
+       if (uev->socket < 0) {
+               pb_log("%s: Error creating event handler socket: %s\n",
+                       __func__, strerror(errno));
+               goto out_err;
+       }
+
+       talloc_set_destructor(uev, user_event_destructor);
+
+       memset(&addr, 0, sizeof(addr));
+       addr.sun_family = AF_UNIX;
+       strcpy(addr.sun_path, PBOOT_USER_EVENT_SOCKET);
+
+       if (bind(uev->socket, (struct sockaddr *)&addr, sizeof(addr))) {
+               pb_log("Error binding event handler socket: %s\n",
+                       strerror(errno));
+       }
+
+       waiter_register(uev->socket, WAIT_IN, user_event_process, uev);
+
+       pb_log("%s: waiting on %s\n", __func__, PBOOT_USER_EVENT_SOCKET);
+
+       return uev;
+
+out_err:
+       talloc_free(uev);
+       return NULL;
+}
+
+/**
+ * user_event_trigger - Trigger known user events
+ *
+ * SIGUSR1 causes udhcpc to renew the current lease or obtain a new lease.
+ */
+
+void user_event_trigger(struct user_event __attribute__((unused)) *uev)
+{
+       /* FIXME: todo */
+}
+
+void user_event_destroy(struct user_event *uev)
+{
+       talloc_free(uev);
+}
diff --git a/discover/user-event.h b/discover/user-event.h
new file mode 100644 (file)
index 0000000..e134d0c
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  Copyright (C) 2009 Sony Computer Entertainment Inc.
+ *  Copyright 2009 Sony Corp.
+ *
+ *  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; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#if !defined(_PB_DISCOVER_USER_EVENT_H)
+#define _PB_DISCOVER_USER_EVENT_H
+
+#include "device-handler.h"
+
+#define PBOOT_USER_EVENT_SOCKET "/tmp/petitboot.ev"
+#define PBOOT_USER_EVENT_SIZE (1 * 1024)
+
+struct user_event;
+
+struct user_event *user_event_init(struct device_handler *handler);
+void user_event_trigger(struct user_event *uev);
+void user_event_destroy(struct user_event *uev);
+
+#endif
index 1c91661cc722924fa253ffbd67bbb3a85a2a04b4..ff807e40f36b83c574f84e3bdb74a185fcb3f365 100644 (file)
--- a/rules.mk
+++ b/rules.mk
@@ -17,7 +17,7 @@ parser_test = test/parser-test
 
 # install targets and components
 daemons = $(pb_discover)
-parsers = kboot yaboot
+parsers = event kboot yaboot
 uis = $(pb_test)
 tests = $(parser_test)
 
@@ -40,8 +40,9 @@ waiter_objs = lib/waiter/waiter.o
 # daemon objs
 parser_objs = discover/parser.o discover/parser-conf.o discover/paths.o \
        $(foreach p, $(parsers), discover/$(p)-parser.o)
-discover_objs = discover/event.o  discover/udev.o discover/discover-server.o \
-       discover/device-handler.o discover/paths.o discover/parser-utils.o
+discover_objs = discover/event.o discover/user-event.o discover/udev.o \
+       discover/discover-server.o discover/device-handler.o discover/paths.o \
+       discover/parser-utils.o
 
 # client objs
 ui_common_objs = ui/common/discover-client.o ui/common/loader.o \