/*
 *
 * Copyright (C) 2017 Patrick Rudolph <siro@das-labor.org>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <libpayload-config.h>
#include <libpayload.h>

static int x_axis;
static int y_axis;
static int z_axis;
static u32 buttons;
static u8 is_intellimouse;
static u8 is_explorer_intellimouse;
static u8 initialized;
static unsigned char mouse_buf[4];
static unsigned char mouse_buf_idx;

static u8 mouse_cmd(unsigned char cmd)
{
	i8042_cmd(0xd4);

	i8042_write_data(cmd);

	return i8042_wait_read_aux() == 0xfa;
}

static u8 mouse_cmd_data(u8 cmd, u8 val)
{
	if (!mouse_cmd(cmd))
		return 0;

	return mouse_cmd(val);
}

/** Try to detect Microsoft Intelli mouse */
static u8 mouse_is_intellimouse(void)
{
	/* Silence mouse. */
	if (!mouse_cmd(0xf5))
		return 0;

	/* Set standard. */
	if (!mouse_cmd(0xf6))
		return 0;

	/* Magic sequence. */
	if (!mouse_cmd_data(0xf3, 0xc8))
		return 0;
	if (!mouse_cmd_data(0xf3, 0x64))
		return 0;
	if (!mouse_cmd_data(0xf3, 0x50))
		return 0;

	/* Get mouse id */
	if (!mouse_cmd(0xf2))
		return 0;

	if (i8042_wait_read_aux() != 0x03)
		return 0;

	return 1;
}

/** Try to detect Microsoft Explorer mouse */
static u8 mouse_is_intellimouse_explorer(void)
{
	/* Silence mouse. */
	if (!mouse_cmd(0xf5))
		return 0;

	/* Set standard. */
	if (!mouse_cmd(0xf6))
		return 0;

	/* Magic sequence. */
	if (!mouse_cmd_data(0xf3, 0xc8))
		return 0;
	if (!mouse_cmd_data(0xf3, 0xc8))
		return 0;
	if (!mouse_cmd_data(0xf3, 0x50))
		return 0;

	/* Get mouse id */
	if (!mouse_cmd(0xf2))
		return 0;

	if (i8042_wait_read_aux() != 4)
		return 0;

	return 1;
}

/** Decode temporary buffer
 * Sanity check to prevent out of order decode.
 * Decode PS/2 data.
 * Supported devices:
 *  Generic 3 button mouse
 *  Microsoft Intelli mouse
 *  Microsoft Explorer mouse
 */
static void mouse_decode(void)
{
	/* Buffer full check and sanity check */
	if (is_intellimouse) {
		if (mouse_buf_idx < 4)
			return;
		if ((mouse_buf[3] & 0x10) != (mouse_buf[3] & 0x08)) {
			mouse_buf_idx = 0;
			return;
		}
	} else if (is_explorer_intellimouse) {
		if (mouse_buf_idx < 4)
			return;
		if (mouse_buf[3] & 0xc0) {
			mouse_buf_idx = 0;
			return;
		}
	} else {
		if (mouse_buf_idx < 3)
			return;
	}

	/* Common protocol */
	x_axis += mouse_buf[1] ? mouse_buf[1] - ((mouse_buf[0] << 4) & 0x100) : 0;
	y_axis += mouse_buf[2] ? ((mouse_buf[0] << 3) & 0x100) - mouse_buf[2] : 0;
	buttons = mouse_buf[0] & 0x7;

	/* Extended protocol */
	if (is_intellimouse) {
		z_axis += (mouse_buf[3] & 0x7) - (mouse_buf[3] & 0x08) ? 8 : 0;
	} else if (is_explorer_intellimouse) {
		z_axis += (mouse_buf[3] & 0x7) - (mouse_buf[3] & 0x08) ? 8 : 0;
		buttons = (mouse_buf[0] & 0x7) | (mouse_buf[3] & 0x30) >> 1;
	}

	mouse_buf_idx = 0;
}

/** Insert data into internal temporary buffer. */
static void insert_buf(unsigned char c)
{
	/* Validate input:
	 * First byte shall have bit 3 set ! */
	if (!mouse_buf_idx && !(c & 8))
		return;

	mouse_buf[mouse_buf_idx++] = c;
}

/** Probe i8042 for new aux data and try to decode it. */
static void mouse_sample(void)
{
	if (!initialized)
		return;

	while (i8042_data_ready_aux()) {
		insert_buf(i8042_read_data_aux());
		mouse_decode();
	}
}

/** Mouse cursor interface method
 * Return and reset internal state.
 */
static void mouse_state(int *x, int *y, int *z, u32 *b)
{
	if (!initialized)
		return;

	mouse_sample();

	if (x) {
		*x = x_axis;
		x_axis = 0;
	}
	if (y) {
		*y = y_axis;
		y_axis = 0;
	}
	if (z) {
		*z = z_axis;
		z_axis = 0;
	}
	if (b)
		*b = buttons;
}

static struct mouse_cursor_input_driver curs = {
	.get_state = mouse_state,
	.input_type = CURSOR_INPUT_TYPE_PS2,
};

/** Probe for PS/2 mouse */
void i8042_mouse_init(void)
{
	int ret;

	/**
	 * Initialize keyboard controller.
	 * Might fail in case no AUX port or firmware disabled the AUX port.
	 */
	if (!i8042_probe() || !i8042_has_aux())
		return;

	/* Empty mouse buffer. */
	while (i8042_data_ready_aux())
		i8042_read_data_aux();

	/* Enable mouse.
	 * Documentation is unclear at this point.
	 * Some recommend to wait for response, some claim there's none.
	 * No response on Lenovo H8 EC.
	 * Ignore it ... */
	ret = i8042_cmd(0xa8);
	if (ret == -1)
		return;

	/* Silence mouse. */
	if (!mouse_cmd(0xf5))
		return;

	/* Read mouse id. */
	if (!mouse_cmd(0xf2))
		return;

	ret = i8042_wait_read_aux();
	if (ret)
		return;

	/* Get and enable features (scroll wheel and 5 buttons) */
	is_intellimouse = mouse_is_intellimouse();
	is_explorer_intellimouse = mouse_is_intellimouse_explorer();

	/* Set defaults. */
	if (!mouse_cmd(0xf6))
		return;

	/* Enable data transmission. */
	if (!mouse_cmd(0xf4))
		return;

	initialized = 1;

	/* Register mouse cursor driver */
	mouse_cursor_add_input_driver(&curs);
}

/* Disable PS/2 mouse. */
void i8042_mouse_disconnect(void)
{
	/* If 0x64 returns 0xff, then we have no keyboard
	 * controller */
	if (inb(0x64) == 0xFF || !initialized)
		return;

	/* Empty keyboard buffer */
	while (i8042_data_ready_aux())
		i8042_read_data_aux();

	/* Disable mouse. */
	i8042_cmd(0xa7);

	initialized = 0;

	/* Release keyboard controller driver */
	i8042_close();
}
