// Code for handling USB Human Interface Devices (HID).
//
// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU LGPLv3 license.

#include "biosvar.h" // GET_GLOBAL
#include "config.h" // CONFIG_*
#include "output.h" // dprintf
#include "ps2port.h" // ATKBD_CMD_GETID
#include "usb.h" // usb_ctrlrequest
#include "usb-hid.h" // usb_keyboard_setup
#include "util.h" // process_key

struct usb_pipe *keyboard_pipe VARFSEG;
struct usb_pipe *mouse_pipe VARFSEG;


/****************************************************************
 * Setup
 ****************************************************************/

// Send USB HID protocol message.
static int
set_protocol(struct usb_pipe *pipe, u16 val)
{
    struct usb_ctrlrequest req;
    req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
    req.bRequest = HID_REQ_SET_PROTOCOL;
    req.wValue = cpu_to_le16(val);
    req.wIndex = 0;
    req.wLength = 0;
    return usb_send_default_control(pipe, &req, NULL);
}

// Send USB HID SetIdle request.
static int
set_idle(struct usb_pipe *pipe, int ms)
{
    struct usb_ctrlrequest req;
    req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
    req.bRequest = HID_REQ_SET_IDLE;
    req.wValue = cpu_to_le16((ms/4)<<8);
    req.wIndex = 0;
    req.wLength = 0;
    return usb_send_default_control(pipe, &req, NULL);
}

#define KEYREPEATWAITMS 500
#define KEYREPEATMS 33

// Format of USB keyboard event data
struct keyevent {
    u8 modifiers;
    u8 reserved;
    u8 keys[6];
};

#define MAX_KBD_EVENT 16

static int
usb_kbd_setup(struct usbdevice_s *usbdev
              , struct usb_endpoint_descriptor *epdesc)
{
    if (! CONFIG_USB_KEYBOARD)
        return -1;
    if (keyboard_pipe)
        // XXX - this enables the first found keyboard (could be random)
        return -1;

    if (le16_to_cpu(epdesc->wMaxPacketSize) < sizeof(struct keyevent)
        || le16_to_cpu(epdesc->wMaxPacketSize) > MAX_KBD_EVENT) {
        dprintf(1, "USB keyboard wMaxPacketSize=%d; aborting\n"
                , le16_to_cpu(epdesc->wMaxPacketSize));
        return -1;
    }

    // Enable "boot" protocol.
    int ret = set_protocol(usbdev->defpipe, 0);
    if (ret)
        return -1;
    // Periodically send reports to enable key repeat.
    ret = set_idle(usbdev->defpipe, KEYREPEATMS);
    if (ret)
        dprintf(3, "Warning: Failed to set key repeat rate\n");

    keyboard_pipe = usb_alloc_pipe(usbdev, epdesc);
    if (!keyboard_pipe)
        return -1;

    dprintf(1, "USB keyboard initialized\n");
    return 0;
}

// Format of USB mouse event data
struct mouseevent {
    u8 buttons;
    u8 x, y;
};

#define MAX_MOUSE_EVENT 8

static int
usb_mouse_setup(struct usbdevice_s *usbdev
                , struct usb_endpoint_descriptor *epdesc)
{
    if (! CONFIG_USB_MOUSE)
        return -1;
    if (mouse_pipe)
        // XXX - this enables the first found mouse (could be random)
        return -1;

    if (le16_to_cpu(epdesc->wMaxPacketSize) < sizeof(struct mouseevent)
        || le16_to_cpu(epdesc->wMaxPacketSize) > MAX_MOUSE_EVENT) {
        dprintf(1, "USB mouse wMaxPacketSize=%d; aborting\n"
                , le16_to_cpu(epdesc->wMaxPacketSize));
        return -1;
    }

    // Enable "boot" protocol.
    int ret = set_protocol(usbdev->defpipe, 0);
    if (ret)
        return -1;

    mouse_pipe = usb_alloc_pipe(usbdev, epdesc);
    if (!mouse_pipe)
        return -1;

    dprintf(1, "USB mouse initialized\n");
    return 0;
}

// Initialize a found USB HID device (if applicable).
int
usb_hid_setup(struct usbdevice_s *usbdev)
{
    if (! CONFIG_USB_KEYBOARD && ! CONFIG_USB_MOUSE)
        return -1;
    dprintf(2, "usb_hid_setup %p\n", usbdev->defpipe);

    struct usb_interface_descriptor *iface = usbdev->iface;
    if (iface->bInterfaceSubClass != USB_INTERFACE_SUBCLASS_BOOT)
        // Doesn't support boot protocol.
        return -1;

    // Find intr in endpoint.
    struct usb_endpoint_descriptor *epdesc = usb_find_desc(
        usbdev, USB_ENDPOINT_XFER_INT, USB_DIR_IN);
    if (!epdesc) {
        dprintf(1, "No usb hid intr in?\n");
        return -1;
    }

    if (iface->bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD)
        return usb_kbd_setup(usbdev, epdesc);
    if (iface->bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)
        return usb_mouse_setup(usbdev, epdesc);
    return -1;
}


/****************************************************************
 * Keyboard events
 ****************************************************************/

// Mapping from USB key id to ps2 key sequence.
static u16 KeyToScanCode[] VAR16 = {
    0x0000, 0x0000, 0x0000, 0x0000, 0x001e, 0x0030, 0x002e, 0x0020,
    0x0012, 0x0021, 0x0022, 0x0023, 0x0017, 0x0024, 0x0025, 0x0026,
    0x0032, 0x0031, 0x0018, 0x0019, 0x0010, 0x0013, 0x001f, 0x0014,
    0x0016, 0x002f, 0x0011, 0x002d, 0x0015, 0x002c, 0x0002, 0x0003,
    0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b,
    0x001c, 0x0001, 0x000e, 0x000f, 0x0039, 0x000c, 0x000d, 0x001a,
    0x001b, 0x002b, 0x0000, 0x0027, 0x0028, 0x0029, 0x0033, 0x0034,
    0x0035, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
    0x0041, 0x0042, 0x0043, 0x0044, 0x0057, 0x0058, 0xe037, 0x0046,
    0xe145, 0xe052, 0xe047, 0xe049, 0xe053, 0xe04f, 0xe051, 0xe04d,
    0xe04b, 0xe050, 0xe048, 0x0045, 0xe035, 0x0037, 0x004a, 0x004e,
    0xe01c, 0x004f, 0x0050, 0x0051, 0x004b, 0x004c, 0x004d, 0x0047,
    0x0048, 0x0049, 0x0052, 0x0053
};

// Mapping from USB modifier id to ps2 key sequence.
static u16 ModifierToScanCode[] VAR16 = {
    //lcntl, lshift, lalt, lgui, rcntl, rshift, ralt, rgui
    0x001d, 0x002a, 0x0038, 0xe05b, 0xe01d, 0x0036, 0xe038, 0xe05c
};

#define RELEASEBIT 0x80

// Translate data from KeyToScanCode[] to calls to process_key().
static void
prockeys(u16 scancode, u8 key_release, u8 mods)
{
    if (scancode > 0xff) {
        if (scancode == 0xe145) {
            // XXX - a real AT keyboard would immediately send the key release
            if (mods & ((1<<0) | (1<<4))) {
                // Cntr+Break key
                process_key(0xe0);
                process_key(0x46 | key_release);
            } else {
                // Pause key
                process_key(0xe1);
                process_key(0x1d | key_release);
                process_key(0x45 | key_release);
            }
            return;
        } else if (scancode == 0xe037 && mods & ((1<<2) | (1<<6))) {
            // Alt+SysReq key
            process_key(0x54 | key_release);
            return;
        }
        process_key(0xe0);
    }
    process_key(scancode | key_release);
}

// Handle a USB key press/release event.
static void
procscankey(u8 key, u8 key_release, u8 mods)
{
    if (key >= ARRAY_SIZE(KeyToScanCode))
        return;
    u16 scancode = GET_GLOBAL(KeyToScanCode[key]);
    if (scancode)
        prockeys(scancode, key_release, mods);
}

// Handle a USB modifier press/release event.
static void
procmodkey(u8 mods, u8 key_release)
{
    int i;
    for (i=0; mods; i++)
        if (mods & (1<<i)) {
            // Modifier key change.
            prockeys(GET_GLOBAL(ModifierToScanCode[i]), key_release, 0);
            mods &= ~(1<<i);
        }
}

struct usbkeyinfo {
    union {
        struct {
            u8 modifiers;
            u8 repeatcount;
            u8 keys[6];
        };
        u64 data;
    };
};
struct usbkeyinfo LastUSBkey VARLOW;

// Process USB keyboard data.
static void
handle_key(struct keyevent *data)
{
    dprintf(9, "Got key %x %x\n", data->modifiers, data->keys[0]);

    // Load old keys.
    struct usbkeyinfo old;
    old.data = GET_LOW(LastUSBkey.data);

    // Check for keys no longer pressed.
    int addpos = 0;
    int i;
    for (i=0; i<ARRAY_SIZE(old.keys); i++) {
        u8 key = old.keys[i];
        if (!key)
            break;
        int j;
        for (j=0;; j++) {
            if (j>=ARRAY_SIZE(data->keys)) {
                // Key released.
                procscankey(key, RELEASEBIT, data->modifiers);
                if (i+1 >= ARRAY_SIZE(old.keys) || !old.keys[i+1])
                    // Last pressed key released - disable repeat.
                    old.repeatcount = 0xff;
                break;
            }
            if (data->keys[j] == key) {
                // Key still pressed.
                data->keys[j] = 0;
                old.keys[addpos++] = key;
                break;
            }
        }
    }
    procmodkey(old.modifiers & ~data->modifiers, RELEASEBIT);

    // Process new keys
    procmodkey(data->modifiers & ~old.modifiers, 0);
    old.modifiers = data->modifiers;
    for (i=0; i<ARRAY_SIZE(data->keys); i++) {
        u8 key = data->keys[i];
        if (!key)
            continue;
        // New key pressed.
        procscankey(key, 0, data->modifiers);
        old.keys[addpos++] = key;
        old.repeatcount = KEYREPEATWAITMS / KEYREPEATMS + 1;
    }
    if (addpos < ARRAY_SIZE(old.keys))
        old.keys[addpos] = 0;

    // Check for key repeat event.
    if (addpos) {
        if (!old.repeatcount)
            procscankey(old.keys[addpos-1], 0, data->modifiers);
        else if (old.repeatcount != 0xff)
            old.repeatcount--;
    }

    // Update old keys
    SET_LOW(LastUSBkey.data, old.data);
}

// Check if a USB keyboard event is pending and process it if so.
static void
usb_check_key(void)
{
    if (! CONFIG_USB_KEYBOARD)
        return;
    struct usb_pipe *pipe = GET_GLOBAL(keyboard_pipe);
    if (!pipe)
        return;

    for (;;) {
        u8 data[MAX_KBD_EVENT];
        int ret = usb_poll_intr(pipe, data);
        if (ret)
            break;
        handle_key((void*)data);
    }
}

// Test if USB keyboard is active.
inline int
usb_kbd_active(void)
{
    if (! CONFIG_USB_KEYBOARD)
        return 0;
    return GET_GLOBAL(keyboard_pipe) != NULL;
}

// Handle a ps2 style keyboard command.
inline int
usb_kbd_command(int command, u8 *param)
{
    if (! CONFIG_USB_KEYBOARD)
        return -1;
    dprintf(9, "usb keyboard cmd=%x\n", command);
    switch (command) {
    case ATKBD_CMD_GETID:
        // Return the id of a standard AT keyboard.
        param[0] = 0xab;
        param[1] = 0x83;
        return 0;
    default:
        return -1;
    }
}


/****************************************************************
 * Mouse events
 ****************************************************************/

// Process USB mouse data.
static void
handle_mouse(struct mouseevent *data)
{
    dprintf(9, "Got mouse b=%x x=%x y=%x\n", data->buttons, data->x, data->y);

    s8 x = data->x, y = -data->y;
    u8 flag = ((data->buttons & 0x7) | (1<<3)
               | (x & 0x80 ? (1<<4) : 0) | (y & 0x80 ? (1<<5) : 0));
    process_mouse(flag);
    process_mouse(x);
    process_mouse(y);
}

// Check if a USB mouse event is pending and process it if so.
static void
usb_check_mouse(void)
{
    if (! CONFIG_USB_MOUSE)
        return;
    struct usb_pipe *pipe = GET_GLOBAL(mouse_pipe);
    if (!pipe)
        return;

    for (;;) {
        u8 data[MAX_MOUSE_EVENT];
        int ret = usb_poll_intr(pipe, data);
        if (ret)
            break;
        handle_mouse((void*)data);
    }
}

// Test if USB mouse is active.
inline int
usb_mouse_active(void)
{
    if (! CONFIG_USB_MOUSE)
        return 0;
    return GET_GLOBAL(mouse_pipe) != NULL;
}

// Handle a ps2 style mouse command.
inline int
usb_mouse_command(int command, u8 *param)
{
    if (! CONFIG_USB_MOUSE)
        return -1;
    dprintf(9, "usb mouse cmd=%x\n", command);
    switch (command) {
    case PSMOUSE_CMD_ENABLE:
    case PSMOUSE_CMD_DISABLE:
    case PSMOUSE_CMD_SETSCALE11:
        return 0;
    case PSMOUSE_CMD_SETSCALE21:
    case PSMOUSE_CMD_SETRATE:
    case PSMOUSE_CMD_SETRES:
        // XXX
        return 0;
    case PSMOUSE_CMD_RESET_BAT:
    case PSMOUSE_CMD_GETID:
        // Return the id of a standard AT mouse.
        param[0] = 0xaa;
        param[1] = 0x00;
        return 0;

    case PSMOUSE_CMD_GETINFO:
        param[0] = 0x00;
        param[1] = 4;
        param[2] = 100;
        return 0;

    default:
        return -1;
    }
}

// Check for USB events pending - called periodically from timer interrupt.
void
usb_check_event(void)
{
    usb_check_key();
    usb_check_mouse();
}
