1/*
2 * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230)
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7/* CAmkES provides a generated header that prototypes all the relevant generated
8 * symbols.
9 */
10#include <camkes.h>
11#include <camkes/io.h>
12
13#include <assert.h>
14#include <keyboard/codes.h>
15#include <keyboard/keyboard.h>
16#include <ringbuffer/ringbuffer.h>
17#include <utils/util.h>
18#include <stdbool.h>
19#include <stdint.h>
20#include <stdlib.h>
21
22static ps_io_port_ops_t io_port_ops;
23
24static uint8_t in8(uint16_t port)
25{
26    uint32_t result = 0;
27    int error = ps_io_port_in(&io_port_ops, port, IOSIZE_8, &result);
28    if (error) {
29        return 0;
30    }
31    return (uint8_t) result;
32}
33
34static void out8(uint16_t port, uint8_t value)
35{
36    ps_io_port_out(&io_port_ops, port, IOSIZE_8, value);
37}
38
39int run(void)
40{
41    int error = camkes_io_port_ops(&io_port_ops);
42    assert(!error);
43
44    sel4keyboard_init(0, in8, out8);
45
46    ringbuffer_t *output = rb_new((void *)char_out, sizeof(*char_out));
47    if (output == NULL) {
48        abort();
49    }
50
51    /* Take each received character and pass it on to the switch. */
52    while (true) {
53        int c;
54
55        /* do basic tracking of multi byte sequences */
56        static int escape_code = 0;
57        static int escape_state = 0;
58        static int break_code = 0;
59
60        while (!sel4keyboard_get_scancode(&c));
61
62        /* first parse escape codes etc */
63        switch (c) {
64        case 0xf0:
65            break_code = 0xf0;
66            continue;
67        case 0xe0:
68        case 0xe1:
69            escape_code = c;
70            escape_state = 0;
71            continue;
72        default:
73            /* need to do actual parsing */
74            switch (escape_code) {
75            case 0xe1:
76                /* need to ignore two scancodes */
77                escape_state++;
78                if (escape_state == 2) {
79                    escape_code = 0;
80                    break_code = 0;
81                }
82                continue;
83            case 0xe0:
84                /* key down */
85                break_code = 0;
86                escape_code = 0;
87                continue;
88            default:
89                if (!break_code) {
90                    break_code = 0;
91                    escape_code = 0;
92                    continue;
93                }
94                /* key up */
95                break_code = 0;
96                escape_code = 0;
97                break;
98            }
99            break;
100        }
101
102        char c1 = sel4keyboard_code_to_char(c);
103        if (c1 != 0) {
104            rb_transmit_byte(output, (unsigned char)c1);
105        }
106    }
107
108    return 0;
109}
110