1/*
2 * Copyright 2017, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12
13#include "keyboard_chardev.h"
14#include <stdbool.h>
15#include <stdlib.h>
16#include <string.h>
17#include <assert.h>
18
19static struct keyboard_state kb_state;
20static keycode_state_t kc_state;
21
22void
23keyboard_cdev_handle_led_changed(void *cookie)
24{
25    /* Update LED states. */
26    keyboard_set_led(&kb_state, kc_state.scroll_lock, kc_state.num_lock, kc_state.caps_lock);
27    kc_state.led_state_changed = false;
28}
29
30static int
31keyboard_getchar(struct ps_chardevice *device)
32{
33    keyboard_key_event_t ev = keyboard_poll_ps2_keyevent(&kb_state);
34    return keycode_process_vkey_event_to_char(&kc_state, ev.vkey, ev.pressed, NULL);
35}
36
37static ssize_t
38keyboard_write(ps_chardevice_t* d, const void* vdata, size_t count, chardev_callback_t rcb UNUSED,
39               void* token UNUSED)
40{
41    /* Keyboard has no write support. */
42    return 0;
43}
44
45static ssize_t
46keyboard_read(ps_chardevice_t* d, void* vdata, size_t count, chardev_callback_t rcb UNUSED,
47              void* token UNUSED)
48{
49    int ret;
50    int i;
51    char* data = (char*) vdata;
52    for (i = 0; i < count; i++) {
53        ret = keyboard_getchar(d);
54        if (ret != EOF) {
55            *data++ = ret;
56        } else {
57            return i;
58        }
59    }
60    return count;
61}
62
63static void
64keyboard_handle_irq(ps_chardevice_t* device UNUSED)
65{
66    /* No IRQ handling required here. */
67}
68
69int
70keyboard_cdev_init(const struct dev_defn* defn, const ps_io_ops_t* ops, ps_chardevice_t* dev)
71{
72    memset(dev, 0, sizeof(*dev));
73
74    /* Set up all the  device properties. */
75    dev->id         = defn->id;
76    dev->vaddr      = (void*) NULL; /* Save the IO port base number. */
77    dev->read       = &keyboard_read;
78    dev->write      = &keyboard_write;
79    dev->handle_irq = &keyboard_handle_irq;
80    dev->irqs       = defn->irqs;
81    dev->ioops      = *ops;
82
83    /* Initialise keyboard drivers. */
84    if (keyboard_init(&kb_state, ops, NULL)) {
85        return -1;
86    }
87
88    /* Initialise keycode. */
89    keycode_init(&kc_state, NULL, NULL,
90                 keyboard_cdev_handle_led_changed);
91
92    /* Set initial LED state. */
93    keyboard_cdev_handle_led_changed(NULL);
94
95    return 0;
96}
97