37,48 → 37,130 |
|
#include <ipc/ipc.h> |
#include <ipc/services.h> |
#include <sysinfo.h> |
#include <stdio.h> |
#include <unistd.h> |
#include <stdlib.h> |
#include <stdio.h> |
#include <ipc/ns.h> |
#include <async.h> |
#include <errno.h> |
#include <arch/kbd.h> |
#include <libadt/fifo.h> |
#include <kbd/kbd.h> |
#include <kbd/keycode.h> |
|
#include <kbd.h> |
#include <libadt/fifo.h> |
#include <key_buffer.h> |
#include <async.h> |
#include <keys.h> |
#include <kbd_port.h> |
#include <kbd_ctl.h> |
#include <layout.h> |
|
#define NAME "kbd" |
|
int cons_connected = 0; |
int phone2cons = -1; |
keybuffer_t keybuffer; |
keybuffer_t keybuffer; |
|
static void irq_handler(ipc_callid_t iid, ipc_call_t *call) |
/** Currently active modifiers. */ |
static unsigned mods = KM_NUM_LOCK; |
|
/** Currently pressed lock keys. We track these to tackle autorepeat. */ |
static unsigned lock_keys; |
|
int cir_service = 0; |
int cir_phone = -1; |
|
#define NUM_LAYOUTS 3 |
|
static layout_op_t *layout[NUM_LAYOUTS] = { |
&us_qwerty_op, |
&us_dvorak_op, |
&cz_op |
}; |
|
static int active_layout = 0; |
|
void kbd_push_scancode(int scancode) |
{ |
int chr; |
/* printf("scancode: 0x%x\n", scancode);*/ |
kbd_ctl_parse_scancode(scancode); |
} |
|
#ifdef MOUSE_ENABLED |
if (mouse_arch_process(phone2cons, call)) |
return; |
#endif |
|
kbd_arch_process(&keybuffer, call); |
void kbd_push_ev(int type, unsigned int key) |
{ |
kbd_event_t ev; |
unsigned mod_mask; |
|
if (cons_connected && phone2cons != -1) { |
/* |
* recode to ASCII - one interrupt can produce more than one |
* code so result is stored in fifo |
*/ |
while (!keybuffer_empty(&keybuffer)) { |
if (!keybuffer_pop(&keybuffer, (int *)&chr)) |
break; |
switch (key) { |
case KC_LCTRL: mod_mask = KM_LCTRL; break; |
case KC_RCTRL: mod_mask = KM_RCTRL; break; |
case KC_LSHIFT: mod_mask = KM_LSHIFT; break; |
case KC_RSHIFT: mod_mask = KM_RSHIFT; break; |
case KC_LALT: mod_mask = KM_LALT; break; |
case KC_RALT: mod_mask = KM_RALT; break; |
default: mod_mask = 0; break; |
} |
|
async_msg_1(phone2cons, KBD_PUSHCHAR, chr); |
if (mod_mask != 0) { |
if (type == KE_PRESS) |
mods = mods | mod_mask; |
else |
mods = mods & ~mod_mask; |
} |
|
switch (key) { |
case KC_CAPS_LOCK: mod_mask = KM_CAPS_LOCK; break; |
case KC_NUM_LOCK: mod_mask = KM_NUM_LOCK; break; |
case KC_SCROLL_LOCK: mod_mask = KM_SCROLL_LOCK; break; |
default: mod_mask = 0; break; |
} |
|
if (mod_mask != 0) { |
if (type == KE_PRESS) { |
/* |
* Only change lock state on transition from released |
* to pressed. This prevents autorepeat from messing |
* up the lock state. |
*/ |
mods = mods ^ (mod_mask & ~lock_keys); |
lock_keys = lock_keys | mod_mask; |
} else { |
lock_keys = lock_keys & ~mod_mask; |
} |
} |
/* |
printf("type: %d\n", type); |
printf("mods: 0x%x\n", mods); |
printf("keycode: %u\n", key); |
*/ |
if (type == KE_PRESS && (mods & KM_LCTRL) && |
key == KC_F1) { |
active_layout = 0; |
layout[active_layout]->reset(); |
return; |
} |
|
if (type == KE_PRESS && (mods & KM_LCTRL) && |
key == KC_F2) { |
active_layout = 1; |
layout[active_layout]->reset(); |
return; |
} |
|
if (type == KE_PRESS && (mods & KM_LCTRL) && |
key == KC_F3) { |
active_layout = 2; |
layout[active_layout]->reset(); |
return; |
} |
|
ev.type = type; |
ev.key = key; |
ev.mods = mods; |
|
ev.c = layout[active_layout]->parse_ev(&ev); |
|
async_msg_4(phone2cons, KBD_EVENT, ev.type, ev.key, ev.mods, ev.c); |
} |
|
static void console_connection(ipc_callid_t iid, ipc_call_t *icall) |
111,6 → 193,14 |
phone2cons = IPC_GET_ARG5(call); |
retval = 0; |
break; |
case KBD_YIELD: |
kbd_port_yield(); |
retval = 0; |
break; |
case KBD_RECLAIM: |
kbd_port_reclaim(); |
retval = 0; |
break; |
default: |
retval = EINVAL; |
} |
125,16 → 215,35 |
|
ipcarg_t phonead; |
|
/* Initialize arch dependent parts */ |
if (kbd_arch_init()) |
if (sysinfo_value("kbd.cir.fhc") == 1) |
cir_service = SERVICE_FHC; |
else if (sysinfo_value("kbd.cir.obio") == 1) |
cir_service = SERVICE_OBIO; |
|
if (cir_service) { |
while (cir_phone < 0) { |
cir_phone = ipc_connect_me_to_blocking(PHONE_NS, cir_service, |
0, 0); |
} |
} |
|
/* Initialize port driver. */ |
if (kbd_port_init() != 0) |
return -1; |
|
/* Initialize controller driver. */ |
if (kbd_ctl_init() != 0) |
return -1; |
|
/* Initialize (reset) layout. */ |
layout[active_layout]->reset(); |
|
/* Initialize key buffer */ |
keybuffer_init(&keybuffer); |
|
async_set_client_connection(console_connection); |
async_set_interrupt_received(irq_handler); |
/* Register service at nameserver */ |
|
/* Register service at nameserver. */ |
if (ipc_connect_to_me(PHONE_NS, SERVICE_KEYBOARD, 0, 0, &phonead) != 0) |
return -1; |
|
141,7 → 250,7 |
printf(NAME ": Accepting connections\n"); |
async_manager(); |
|
/* Never reached */ |
/* Not reached. */ |
return 0; |
} |
|