kbd.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2006 Josef Cejka
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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 /*      printf("scancode: 0x%x\n", scancode);*/
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                          * Only change lock state on transition from released
00121                          * to pressed. This prevents autorepeat from messing
00122                          * up the lock state.
00123                          */
00124                         mods = mods ^ (mod_mask & ~lock_keys);
00125                         lock_keys = lock_keys | mod_mask;
00126 
00127                         /* Update keyboard lock indicator lights. */
00128                         kbd_ctl_set_ind(mods);
00129                 } else {
00130                         lock_keys = lock_keys & ~mod_mask;
00131                 }
00132         }
00133 /*
00134         printf("type: %d\n", type);
00135         printf("mods: 0x%x\n", mods);
00136         printf("keycode: %u\n", key);
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         /* Initialize port driver. */
00228         if (kbd_port_init() != 0)
00229                 return -1;
00230 
00231         /* Initialize controller driver. */
00232         if (kbd_ctl_init() != 0)
00233                 return -1;
00234 
00235         /* Initialize (reset) layout. */
00236         layout[active_layout]->reset();
00237         
00238         /* Register driver */
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         /* Not reached. */
00258         return 0;
00259 }
00260 

Generated on Thu Jun 2 07:45:49 2011 for HelenOS/USB by  doxygen 1.4.7