00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00038 #include <ipc/services.h>
00039 #include <ipc/kbd.h>
00040 #include <sysinfo.h>
00041 #include <stdio.h>
00042 #include <unistd.h>
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045 #include <ipc/ns.h>
00046 #include <async.h>
00047 #include <errno.h>
00048 #include <adt/fifo.h>
00049 #include <io/console.h>
00050 #include <io/keycode.h>
00051 #include <devmap.h>
00052
00053 #include <kbd.h>
00054 #include <kbd_port.h>
00055 #include <kbd_ctl.h>
00056 #include <layout.h>
00057
00058 #define NAME "kbd"
00059 #define NAMESPACE "hid_in"
00060
00061 int client_phone = -1;
00062
00064 static unsigned mods = KM_NUM_LOCK;
00065
00067 static unsigned lock_keys;
00068
00069 bool irc_service = false;
00070 int irc_phone = -1;
00071
00072 #define NUM_LAYOUTS 3
00073
00074 static layout_op_t *layout[NUM_LAYOUTS] = {
00075 &us_qwerty_op,
00076 &us_dvorak_op,
00077 &cz_op
00078 };
00079
00080 static int active_layout = 0;
00081
00082 void kbd_push_scancode(int scancode)
00083 {
00084
00085 kbd_ctl_parse_scancode(scancode);
00086 }
00087
00088 void kbd_push_ev(int type, unsigned int key)
00089 {
00090 console_event_t ev;
00091 unsigned mod_mask;
00092
00093 switch (key) {
00094 case KC_LCTRL: mod_mask = KM_LCTRL; break;
00095 case KC_RCTRL: mod_mask = KM_RCTRL; break;
00096 case KC_LSHIFT: mod_mask = KM_LSHIFT; break;
00097 case KC_RSHIFT: mod_mask = KM_RSHIFT; break;
00098 case KC_LALT: mod_mask = KM_LALT; break;
00099 case KC_RALT: mod_mask = KM_RALT; break;
00100 default: mod_mask = 0; break;
00101 }
00102
00103 if (mod_mask != 0) {
00104 if (type == KEY_PRESS)
00105 mods = mods | mod_mask;
00106 else
00107 mods = mods & ~mod_mask;
00108 }
00109
00110 switch (key) {
00111 case KC_CAPS_LOCK: mod_mask = KM_CAPS_LOCK; break;
00112 case KC_NUM_LOCK: mod_mask = KM_NUM_LOCK; break;
00113 case KC_SCROLL_LOCK: mod_mask = KM_SCROLL_LOCK; break;
00114 default: mod_mask = 0; break;
00115 }
00116
00117 if (mod_mask != 0) {
00118 if (type == KEY_PRESS) {
00119
00120
00121
00122
00123
00124 mods = mods ^ (mod_mask & ~lock_keys);
00125 lock_keys = lock_keys | mod_mask;
00126
00127
00128 kbd_ctl_set_ind(mods);
00129 } else {
00130 lock_keys = lock_keys & ~mod_mask;
00131 }
00132 }
00133
00134
00135
00136
00137
00138 if (type == KEY_PRESS && (mods & KM_LCTRL) &&
00139 key == KC_F1) {
00140 active_layout = 0;
00141 layout[active_layout]->reset();
00142 return;
00143 }
00144
00145 if (type == KEY_PRESS && (mods & KM_LCTRL) &&
00146 key == KC_F2) {
00147 active_layout = 1;
00148 layout[active_layout]->reset();
00149 return;
00150 }
00151
00152 if (type == KEY_PRESS && (mods & KM_LCTRL) &&
00153 key == KC_F3) {
00154 active_layout = 2;
00155 layout[active_layout]->reset();
00156 return;
00157 }
00158
00159 ev.type = type;
00160 ev.key = key;
00161 ev.mods = mods;
00162
00163 ev.c = layout[active_layout]->parse_ev(&ev);
00164
00165 async_msg_4(client_phone, KBD_EVENT, ev.type, ev.key, ev.mods, ev.c);
00166 }
00167
00168 static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
00169 {
00170 ipc_callid_t callid;
00171 ipc_call_t call;
00172 int retval;
00173
00174 async_answer_0(iid, EOK);
00175
00176 while (1) {
00177 callid = async_get_call(&call);
00178 switch (IPC_GET_IMETHOD(call)) {
00179 case IPC_M_PHONE_HUNGUP:
00180 if (client_phone != -1) {
00181 async_hangup(client_phone);
00182 client_phone = -1;
00183 }
00184
00185 async_answer_0(callid, EOK);
00186 return;
00187 case IPC_M_CONNECT_TO_ME:
00188 if (client_phone != -1) {
00189 retval = ELIMIT;
00190 break;
00191 }
00192 client_phone = IPC_GET_ARG5(call);
00193 retval = 0;
00194 break;
00195 case KBD_YIELD:
00196 kbd_port_yield();
00197 retval = 0;
00198 break;
00199 case KBD_RECLAIM:
00200 kbd_port_reclaim();
00201 retval = 0;
00202 break;
00203 default:
00204 retval = EINVAL;
00205 }
00206 async_answer_0(callid, retval);
00207 }
00208 }
00209
00210
00211 int main(int argc, char **argv)
00212 {
00213 printf("%s: HelenOS Keyboard service\n", NAME);
00214
00215 sysarg_t fhc;
00216 sysarg_t obio;
00217
00218 if (((sysinfo_get_value("kbd.cir.fhc", &fhc) == EOK) && (fhc))
00219 || ((sysinfo_get_value("kbd.cir.obio", &obio) == EOK) && (obio)))
00220 irc_service = true;
00221
00222 if (irc_service) {
00223 while (irc_phone < 0)
00224 irc_phone = service_connect_blocking(SERVICE_IRC, 0, 0);
00225 }
00226
00227
00228 if (kbd_port_init() != 0)
00229 return -1;
00230
00231
00232 if (kbd_ctl_init() != 0)
00233 return -1;
00234
00235
00236 layout[active_layout]->reset();
00237
00238
00239 int rc = devmap_driver_register(NAME, client_connection);
00240 if (rc < 0) {
00241 printf("%s: Unable to register driver (%d)\n", NAME, rc);
00242 return -1;
00243 }
00244
00245 char kbd[DEVMAP_NAME_MAXLEN + 1];
00246 snprintf(kbd, DEVMAP_NAME_MAXLEN, "%s/%s", NAMESPACE, NAME);
00247
00248 devmap_handle_t devmap_handle;
00249 if (devmap_device_register(kbd, &devmap_handle) != EOK) {
00250 printf("%s: Unable to register device %s\n", NAME, kbd);
00251 return -1;
00252 }
00253
00254 printf(NAME ": Accepting connections\n");
00255 async_manager();
00256
00257
00258 return 0;
00259 }
00260