/*
 * Copyright 2016 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <errno.h>
#include <libudev.h>
#include <string.h>

#include "dev.h"
#include "input.h"
#include "term.h"
#include "util.h"

static struct udev* udev = NULL;
static struct udev_monitor* udev_monitor = NULL;
static int udev_fd = -1;

static bool dev_is_keyboard_device(struct udev_device* dev)
{
	const char *keyboard = udev_device_get_property_value(dev, "ID_INPUT_KEYBOARD");

	if (keyboard && !strcmp(keyboard, "1"))
		return true;

	return false;
}

static void dev_add_existing_input_devs(void)
{
	struct udev_enumerate* udev_enum;
	struct udev_list_entry* devices, *deventry;
	udev_enum = udev_enumerate_new(udev);
	udev_enumerate_add_match_subsystem(udev_enum, "input");
	udev_enumerate_scan_devices(udev_enum);
	devices = udev_enumerate_get_list_entry(udev_enum);
	udev_list_entry_foreach(deventry, devices) {
		const char* syspath;
		struct udev_device* dev;
		syspath = udev_list_entry_get_name(deventry);
		dev = udev_device_new_from_syspath(udev, syspath);
		if (dev_is_keyboard_device(dev))
			input_add(udev_device_get_devnode(dev));
		udev_device_unref(dev);
	}
	udev_enumerate_unref(udev_enum);
}

int dev_init(void)
{
	udev = udev_new();
	if (!udev)
		return -ENOENT;

	udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
	if (!udev_monitor) {
		udev_unref(udev);
		udev = NULL;
		return -ENOENT;
	}
	udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "input",
							NULL);
	udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "drm",
							"drm_minor");
	udev_monitor_enable_receiving(udev_monitor);
	udev_fd = udev_monitor_get_fd(udev_monitor);

	dev_add_existing_input_devs();

	return 0;
}

void dev_close(void)
{
	if (!udev_monitor) {
		return;
	}
	udev_monitor_unref(udev_monitor);
	udev_monitor = NULL;
	udev_unref(udev);
	udev = NULL;
	udev_fd = -1;
}

void dev_add_fds(fd_set* read_set, fd_set* exception_set, int *maxfd)
{
	FD_SET(udev_fd, read_set);
	FD_SET(udev_fd, exception_set);
	if (udev_fd > *maxfd)
		*maxfd = udev_fd;
}

void dev_dispatch_io(fd_set* read_set, fd_set* exception_set)
{
	if (FD_ISSET(udev_fd, exception_set)) {
		/* udev died on us? */
		LOG(ERROR, "Exception on udev fd");
		return;
	}

	if (FD_ISSET(udev_fd, read_set)
	    && !FD_ISSET(udev_fd, exception_set)) {
		/* we got an udev notification */
		struct udev_device* dev =
		    udev_monitor_receive_device(udev_monitor);
		if (dev) {
			if (!strcmp("input", udev_device_get_subsystem(dev))) {
				if (!strcmp("add", udev_device_get_action(dev))) {
					if (dev_is_keyboard_device(dev))
						input_add(udev_device_get_devnode(dev));
				} else if (!strcmp("remove", udev_device_get_action(dev))) {
					input_remove(udev_device_get_devnode(dev));
				}
			} else if (!strcmp("drm", udev_device_get_subsystem(dev))
					&& !strcmp("drm_minor", udev_device_get_devtype(dev))
					&& !strcmp("change", udev_device_get_action(dev))) {
				const char *hotplug = udev_device_get_property_value(dev, "HOTPLUG");
				if (hotplug && atoi(hotplug) == 1)
					term_monitor_hotplug();
			}
			udev_device_unref(dev);
		}
	}
}
