1// Copyright 2016 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 <hid/hid.h>
6#include <hid/usages.h>
7
8#include <string.h>
9#include <strings.h>
10
11#define KEYSET(bitmap,n) (bitmap[(n) >> 5] |= (1 << ((n) & 31)))
12#define KEYCLR(bitmap,n) (bitmap[(n) >> 5] &= ~(1 << ((n) & 31)))
13
14void hid_kbd_parse_report(uint8_t buf[8], hid_keys_t* keys) {
15    memset(keys, 0, sizeof(hid_keys_t));
16    // modifiers start at bit 224
17    keys->keymask[7] = buf[0];
18    for (int i = 2; i < 8; i++) {
19        if (buf[i] == 0) break;
20        KEYSET(keys->keymask, buf[i]);
21    }
22}
23
24void hid_kbd_pressed_keys(const hid_keys_t* prev, const hid_keys_t* cur, hid_keys_t* pressed) {
25    memset(pressed, 0, sizeof(hid_keys_t));
26    for (int i = 0; i < 8; i++) {
27        pressed->keymask[i] = (prev->keymask[i] ^ cur->keymask[i]) & cur->keymask[i];
28    }
29}
30
31void hid_kbd_released_keys(const hid_keys_t* prev, const hid_keys_t* cur, hid_keys_t* released) {
32    memset(released, 0, sizeof(hid_keys_t));
33    for (int i = 0; i < 8; i++) {
34        released->keymask[i] = (prev->keymask[i] ^ cur->keymask[i]) & prev->keymask[i];
35    }
36}
37
38uint8_t hid_kbd_next_key(hid_keys_t* keys) {
39    for (int i = 0; i < 8; i++) {
40        int key = ffs(keys->keymask[i]);
41        if (key) {
42            key += i*32 - 1;
43            KEYCLR(keys->keymask, key);
44            return key;
45        }
46    }
47    return 0;
48}
49
50uint8_t hid_map_key(uint32_t usage, bool shift, keychar_t* keymap) {
51    if (usage > HID_USAGE_KEY_KP_DOT) return 0;
52    if (shift) {
53        return keymap[usage].shift_c;
54    } else {
55        return keymap[usage].c;
56    }
57}
58