1// Copyright 2017 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <fcntl.h>
6#include <poll.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11#include <hid/hid.h>
12#include <hid/usages.h>
13
14#include <zircon/device/input.h>
15#include <zircon/syscalls.h>
16
17#include <port/port.h>
18
19#include "keyboard.h"
20
21#define LOW_REPEAT_KEY_FREQ 250000000
22#define HIGH_REPEAT_KEY_FREQ 50000000
23
24static int modifiers_from_keycode(uint8_t keycode) {
25    switch (keycode) {
26    case HID_USAGE_KEY_LEFT_SHIFT:
27        return MOD_LSHIFT;
28    case HID_USAGE_KEY_RIGHT_SHIFT:
29        return MOD_RSHIFT;
30    case HID_USAGE_KEY_LEFT_ALT:
31        return MOD_LALT;
32    case HID_USAGE_KEY_RIGHT_ALT:
33        return MOD_RALT;
34    case HID_USAGE_KEY_LEFT_CTRL:
35        return MOD_LCTRL;
36    case HID_USAGE_KEY_RIGHT_CTRL:
37        return MOD_RCTRL;
38    }
39    return 0;
40}
41
42static void set_caps_lock_led(int keyboard_fd, bool caps_lock) {
43    // The following bit to set is specified in "Device Class Definition
44    // for Human Interface Devices (HID)", Version 1.11,
45    // http://www.usb.org/developers/hidpage/HID1_11.pdf.  Zircon leaves
46    // USB keyboards in boot mode, so the relevant section is Appendix B,
47    // "Boot Interface Descriptors", "B.1 Protocol 1 (Keyboard)".
48    const int kUsbCapsLockBit = 1 << 1;
49
50    const int kNumBytes = 1;
51    uint8_t msg_buf[sizeof(input_set_report_t) + kNumBytes];
52    auto* msg = reinterpret_cast<input_set_report_t*>(msg_buf);
53    msg->id = 0;
54    msg->type = INPUT_REPORT_OUTPUT;
55    msg->data[0] = caps_lock ? kUsbCapsLockBit : 0;
56    ssize_t result = ioctl_input_set_report(keyboard_fd, msg, sizeof(msg_buf));
57    if (result != kNumBytes) {
58#if !BUILD_FOR_TEST
59        printf("ioctl_input_set_report() failed (returned %zd)\n", result);
60#endif
61    }
62}
63
64struct vc_input {
65    port_fd_handler_t fh;
66    port_handler_t th;
67    zx_handle_t timer;
68
69    keypress_handler_t handler;
70    int fd;
71
72    uint8_t previous_report_buf[8];
73    uint8_t report_buf[8];
74    hid_keys_t state[2];
75    int cur_idx;
76    int prev_idx;
77    int modifiers;
78    uint64_t repeat_interval;
79    bool repeat_enabled;
80};
81
82// returns true if key was pressed and none were released
83bool vc_input_process(vc_input_t* vi, uint8_t report[8]) {
84    bool do_repeat = false;
85
86    // process the key
87    uint8_t keycode;
88    hid_keys_t keys;
89
90    hid_kbd_parse_report(report, &vi->state[vi->cur_idx]);
91
92    hid_kbd_pressed_keys(&vi->state[vi->prev_idx], &vi->state[vi->cur_idx], &keys);
93    hid_for_every_key(&keys, keycode) {
94        vi->modifiers |= modifiers_from_keycode(keycode);
95        if (keycode == HID_USAGE_KEY_CAPSLOCK) {
96            vi->modifiers ^= MOD_CAPSLOCK;
97            set_caps_lock_led(vi->fd, vi->modifiers & MOD_CAPSLOCK);
98        }
99        vi->handler(keycode, vi->modifiers);
100        do_repeat = true;
101    }
102
103    hid_kbd_released_keys(&vi->state[vi->prev_idx], &vi->state[vi->cur_idx], &keys);
104    hid_for_every_key(&keys, keycode) {
105        vi->modifiers &= ~modifiers_from_keycode(keycode);
106        do_repeat = false;
107    }
108
109    // swap key states
110    vi->cur_idx = 1 - vi->cur_idx;
111    vi->prev_idx = 1 - vi->prev_idx;
112
113    return do_repeat;
114}
115
116#if !BUILD_FOR_TEST
117static void vc_input_destroy(vc_input_t* vi) {
118    port_cancel(&port, &vi->th);
119    if (vi->fd >= 0) {
120        port_fd_handler_done(&vi->fh);
121        close(vi->fd);
122    }
123    zx_handle_close(vi->timer);
124    free(vi);
125}
126
127static zx_status_t vc_timer_cb(port_handler_t* ph, zx_signals_t signals, uint32_t evt) {
128    vc_input_t* vi = containerof(ph, vc_input_t, th);
129
130    // if interval is infinite, repeat was canceled
131    if (vi->repeat_interval != ZX_TIME_INFINITE) {
132        vc_input_process(vi, vi->previous_report_buf);
133        vc_input_process(vi, vi->report_buf);
134
135        // increase repeat rate if we're not yet at the fastest rate
136        if ((vi->repeat_interval = vi->repeat_interval * 3 / 4) < HIGH_REPEAT_KEY_FREQ) {
137            vi->repeat_interval = HIGH_REPEAT_KEY_FREQ;
138        }
139
140        zx_timer_set(vi->timer, zx_deadline_after(vi->repeat_interval), 0);
141    }
142
143    // return non-OK to avoid needlessly re-arming the repeating wait
144    return ZX_ERR_NEXT;
145}
146
147static zx_status_t vc_input_cb(port_fd_handler_t* fh, unsigned pollevt, uint32_t evt) {
148    vc_input_t* vi = containerof(fh, vc_input_t, fh);
149    ssize_t r;
150
151    if (!(pollevt & POLLIN)) {
152        r = ZX_ERR_PEER_CLOSED;
153    } else {
154        memcpy(vi->previous_report_buf, vi->report_buf, sizeof(vi->report_buf));
155        r = read(vi->fd, vi->report_buf, sizeof(vi->report_buf));
156    }
157    if (r <= 0) {
158        vc_input_destroy(vi);
159        return ZX_ERR_STOP;
160    }
161    if ((size_t)(r) != sizeof(vi->report_buf)) {
162        vi->repeat_interval = ZX_TIME_INFINITE;
163        return ZX_OK;
164    }
165
166    if (vc_input_process(vi, vi->report_buf) && vi->repeat_enabled) {
167        vi->repeat_interval = LOW_REPEAT_KEY_FREQ;
168        zx_timer_set(vi->timer, zx_deadline_after(vi->repeat_interval), 0);
169    } else {
170        vi->repeat_interval = ZX_TIME_INFINITE;
171    }
172    return ZX_OK;
173}
174#endif
175
176zx_status_t vc_input_create(vc_input_t** out, keypress_handler_t handler, int fd) {
177    vc_input_t* vi = reinterpret_cast<vc_input_t*>(calloc(1, sizeof(vc_input_t)));
178    if (vi == NULL) {
179        return ZX_ERR_NO_MEMORY;
180    }
181
182    vi->fd = fd;
183    vi->handler = handler;
184
185    vi->cur_idx = 0;
186    vi->prev_idx = 1;
187    vi->modifiers = 0;
188    vi->repeat_interval = ZX_TIME_INFINITE;
189    vi->repeat_enabled = true;
190
191    char* flag = getenv("virtcon.keyrepeat");
192    if (flag && (!strcmp(flag, "0") || !strcmp(flag, "false"))) {
193        printf("vc: Key repeat disabled\n");
194        vi->repeat_enabled = false;
195    }
196
197#if !BUILD_FOR_TEST
198    zx_status_t r;
199    if ((r = zx_timer_create(0, ZX_CLOCK_MONOTONIC, &vi->timer)) < 0) {
200        free(vi);
201        return r;
202    }
203
204    vi->fh.func = vc_input_cb;
205    if ((r = port_fd_handler_init(&vi->fh, fd, POLLIN | POLLHUP | POLLRDHUP)) < 0) {
206        zx_handle_close(vi->timer);
207        free(vi);
208        return r;
209    }
210
211    if ((r = port_wait(&port, &vi->fh.ph)) < 0) {
212        port_fd_handler_done(&vi->fh);
213        zx_handle_close(vi->timer);
214        free(vi);
215        return r;
216    }
217
218    vi->th.handle = vi->timer;
219    vi->th.waitfor = ZX_TIMER_SIGNALED;
220    vi->th.func = vc_timer_cb;
221    port_wait_repeating(&port, &vi->th);
222#endif
223
224    *out = vi;
225    return ZX_OK;
226}
227
228#if !BUILD_FOR_TEST
229zx_status_t new_input_device(int fd, keypress_handler_t handler) {
230    // test to see if this is a device we can read
231    int proto = INPUT_PROTO_NONE;
232    ssize_t rc = ioctl_input_get_protocol(fd, &proto);
233    if ((rc < 0) || (proto != INPUT_PROTO_KBD)) {
234        // skip devices that aren't keyboards
235        close(fd);
236        return ZX_ERR_NOT_SUPPORTED;
237    }
238
239    zx_status_t r;
240    vc_input_t* vi;
241    if ((r = vc_input_create(&vi, handler, fd)) < 0) {
242        close(fd);
243    }
244    return r;
245}
246#endif
247