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