2 * Copyright (C) 2009 Sony Computer Entertainment Inc.
3 * Copyright 2009 Sony Corp.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #if defined(HAVE_CONFIG_H)
27 #include <sys/socket.h>
28 #include <sys/types.h>
33 #include <types/types.h>
34 #include <talloc/talloc.h>
35 #include <waiter/waiter.h>
37 #include "device-handler.h"
40 #include "user-event.h"
44 struct device_handler *handler;
48 static const char *event_action_name(enum event_action action)
51 case EVENT_ACTION_ADD:
53 case EVENT_ACTION_REMOVE:
55 case EVENT_ACTION_CONF:
64 static void user_event_print_event(struct event __attribute__((unused)) *event)
68 pb_log("user_event %s event:\n", event_action_name(event->action));
69 pb_log("\tdevice: %s\n", event->device);
71 for (i = 0; i < event->n_params; i++)
72 pb_log("\t%-12s => %s\n",
73 event->params[i].name, event->params[i].value);
76 static enum conf_method parse_conf_method(const char *str)
79 if (!strcasecmp(str, "dhcp")) {
80 return CONF_METHOD_DHCP;
82 return CONF_METHOD_UNKNOWN;
85 static struct resource *user_event_resource(struct discover_boot_option *opt,
86 struct event *event, const char *param_name)
92 val = event_get_param(event, param_name);
96 url = pb_url_parse(opt, val);
100 res = create_url_resource(opt, url);
109 static int parse_user_event(struct discover_context *ctx, struct event *event)
111 struct discover_boot_option *d_opt;
112 struct boot_option *opt;
116 dev = ctx->device->device;
118 d_opt = discover_boot_option_create(ctx, ctx->device);
124 p = event_get_param(event, "name");
127 pb_log("%s: no name found\n", __func__);
131 opt->id = talloc_asprintf(opt, "%s#%s", dev->id, p);
132 opt->name = talloc_strdup(opt, p);
134 d_opt->boot_image = user_event_resource(d_opt, event, "image");
135 if (!d_opt->boot_image) {
136 pb_log("%s: no boot image found for %s!\n", __func__,
141 d_opt->initrd = user_event_resource(d_opt, event, "initrd");
143 p = event_get_param(event, "args");
146 opt->boot_args = talloc_strdup(opt, p);
148 opt->description = talloc_asprintf(opt, "%s %s", opt->boot_image_file,
149 opt->boot_args ? : "");
151 if (event_get_param(event, "default"))
152 opt->is_default = true;
154 discover_context_add_boot_option(ctx, d_opt);
163 static int user_event_conf(struct user_event *uev, struct event *event)
165 struct device_handler *handler = uev->handler;
166 struct discover_device *dev;
167 enum conf_method method;
171 val = event_get_param(event, "url");
175 url = pb_url_parse(event, val);
179 val = event_get_param(event, "method");
183 method = parse_conf_method(val);
184 if (method == CONF_METHOD_UNKNOWN)
187 dev = discover_device_create(handler, event->device);
189 device_handler_conf(handler, dev, url, method);
194 static int user_event_add(struct user_event *uev, struct event *event)
196 struct device_handler *handler = uev->handler;
197 struct discover_context *ctx;
198 struct discover_device *dev;
200 dev = discover_device_create(handler, event->device);
201 ctx = device_handler_discover_context_create(handler, dev);
203 parse_user_event(ctx, event);
205 device_handler_discover_context_commit(handler, ctx);
212 static int user_event_remove(struct user_event *uev, struct event *event)
214 struct device_handler *handler = uev->handler;
215 struct discover_device *dev;
217 dev = device_lookup_by_id(handler, event->device);
221 device_handler_remove(handler, dev);
226 static void user_event_handle_message(struct user_event *uev, char *buf,
232 event = talloc(uev, struct event);
233 event->type = EVENT_TYPE_USER;
235 result = event_parse_ad_message(event, buf, len);
240 user_event_print_event(event);
242 switch (event->action) {
243 case EVENT_ACTION_ADD:
244 result = user_event_add(uev, event);
246 case EVENT_ACTION_REMOVE:
247 result = user_event_remove(uev, event);
249 case EVENT_ACTION_CONF:
250 result = user_event_conf(uev, event);
261 static int user_event_process(void *arg)
263 struct user_event *uev = arg;
264 char buf[PBOOT_USER_EVENT_SIZE];
267 len = recvfrom(uev->socket, buf, sizeof(buf), 0, NULL, NULL);
270 pb_log("%s: socket read failed: %s", __func__, strerror(errno));
275 pb_log("%s: empty", __func__);
279 pb_log("%s: %u bytes\n", __func__, len);
281 user_event_handle_message(uev, buf, len);
286 static int user_event_destructor(void *arg)
288 struct user_event *uev = arg;
290 pb_log("%s\n", __func__);
292 if (uev->socket >= 0)
298 struct user_event *user_event_init(struct waitset *waitset,
299 struct device_handler *handler)
301 struct sockaddr_un addr;
302 struct user_event *uev;
304 unlink(PBOOT_USER_EVENT_SOCKET);
306 uev = talloc(NULL, struct user_event);
308 uev->handler = handler;
310 uev->socket = socket(AF_UNIX, SOCK_DGRAM, 0);
311 if (uev->socket < 0) {
312 pb_log("%s: Error creating event handler socket: %s\n",
313 __func__, strerror(errno));
317 talloc_set_destructor(uev, user_event_destructor);
319 memset(&addr, 0, sizeof(addr));
320 addr.sun_family = AF_UNIX;
321 strcpy(addr.sun_path, PBOOT_USER_EVENT_SOCKET);
323 if (bind(uev->socket, (struct sockaddr *)&addr, sizeof(addr))) {
324 pb_log("Error binding event handler socket: %s\n",
328 waiter_register_io(waitset, uev->socket, WAIT_IN,
329 user_event_process, uev);
331 pb_log("%s: waiting on %s\n", __func__, PBOOT_USER_EVENT_SOCKET);
340 void user_event_destroy(struct user_event *uev)