00001
00002
00003
00004
00005
00006
00007
00008 #include <const.h>
00009
00010 #include <arch/i386.h>
00011 #include <arch/interrupt.h>
00012
00013 #include <kernel/console.h>
00014 #include <kernel/kernel.h>
00015 #include <kernel/queue.h>
00016 #include <kernel/semaphore.h>
00017 #include <kernel/speaker.h>
00018 #include <kernel/task.h>
00019
00020 #include <kernel/keyboard.h>
00021
00022
00023
00024
00025
00026
00027
00028
00029 static
00030 word regular[128] = {
00031 0x0000,0x011B,0x0231,0x0332,0x0433,0x0534,0x0635,0x0736,0x0837,0x0938,0x0A39,0x0B30,0x0C2D,0x0D3D,0x0E08,0x0F09,
00032 0x1071,0x1177,0x1265,0x1372,0x1474,0x1579,0x1675,0x1769,0x186F,0x1970,0x1A5B,0x1B5D,0x1C0D,0x1D00,0x1E61,0x1F73,
00033 0x2064,0x2166,0x2267,0x2368,0x246A,0x256B,0x266C,0x273B,0x2827,0x2960,0x2A00,0x2B5C,0x2C7A,0x2D78,0x2E63,0x2F76,
00034 0x3062,0x316E,0x326D,0x332C,0x342E,0x352F,0x3600,0x372A,0x3800,0x3920,0x3A00,0x3B00,0x3C00,0x3D00,0x3E00,0x3F00,
00035 0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700,0x4800,0x4900,0x4A2D,0x4B00,0x4C00,0x4D00,0x4E2B,0x4F00,
00036 0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,0x8500,0x8600,0x0000,0x0000,0x5B00,0x5C00,0x5D00
00037 };
00038
00039
00040 static
00041 word with_shift[128] = {
00042 0x0000,0x011B,0x0221,0x0340,0x0423,0x0524,0x0625,0x075E,0x0826,0x092A,0x0A28,0x0B29,0x0C5F,0x0D2B,0x0E08,0x0F00,
00043 0x1051,0x1157,0x1245,0x1352,0x1454,0x1559,0x1655,0x1749,0x184F,0x1950,0x1A7B,0x1B7D,0x1C0D,0x1D00,0x1E41,0x1F53,
00044 0x2044,0x2146,0x2247,0x2348,0x244A,0x254B,0x264C,0x273A,0x2822,0x297E,0x2A00,0x2B7C,0x2C5A,0x2D58,0x2E43,0x2F56,
00045 0x3042,0x314E,0x324D,0x333C,0x343E,0x353F,0x3600,0x372A,0x3800,0x3920,0x3A00,0x5400,0x5500,0x5600,0x5700,0x5800,
00046 0x5900,0x5A00,0x5B00,0x5C00,0x5D00,0x4500,0x4600,0x4700,0x4800,0x4900,0x4A2D,0x4B00,0x4C00,0x4D00,0x4E2B,0x4F00,
00047 0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,0x8700,0x8800,0x0000,0x0000,0x5B00,0x5C00,0x5D00
00048 };
00049
00050
00051 static
00052 word with_alt[128] = {
00053 0x0000,0x0100,0x7800,0x7900,0x7A00,0x7B00,0x7C00,0x7D00,0x7E00,0x7F00,0x8000,0x8100,0x8200,0x8300,0x0E00,0xA500,
00054 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700,0x1800,0x1900,0x1A00,0x1B00,0x1C00,0x1D00,0x1E00,0x1F00,
00055 0x2000,0x2100,0x2200,0x2300,0x2400,0x2500,0x2600,0x2700,0x2800,0x2900,0x2A00,0x2B00,0x2C00,0x2D00,0x2E00,0x2F00,
00056 0x3000,0x3100,0x3200,0x3300,0x3400,0x3500,0x3600,0x3700,0x3800,0x3900,0x3A00,0x6800,0x6900,0x6A00,0x6B00,0x6C00,
00057 0x6D00,0x6E00,0x6F00,0x7000,0x7100,0x4500,0x4600,0x9700,0x9800,0x9900,0x4A00,0x9B00,0x9C00,0x9D00,0x4E00,0x9F00,
00058 0xA000,0xA100,0xA200,0xA300,0x5400,0x5500,0x5600,0x8B00,0x8C00
00059 };
00060
00061
00062 static
00063 word with_control[128] = {
00064 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x9400,
00065 0x1011,0x1117,0x1205,0x1312,0x1414,0x1519,0x1615,0x1709,0x180F,0x1910,0x0000,0x0000,0x1C0A,0x1D00,0x1E01,0x1F13,
00066 0x2004,0x2106,0x2207,0x2308,0x240A,0x250B,0x260C,0x0000,0x0000,0x0000,0x2A00,0x0000,0x2C1A,0x2D18,0x2E03,0x2F16,
00067 0x3002,0x310E,0x320D,0x0000,0x0000,0x9500,0x3600,0x9600,0x3800,0x3920,0x3A00,0x5E00,0x5F00,0x6000,0x6100,0x6200,
00068 0x6300,0x6400,0x6500,0x6600,0x6700,0x4500,0x4600,0x7700,0x8D00,0x8400,0x8E00,0x7300,0x8F00,0x7400,0x9000,0x7500,
00069 0x9100,0x7600,0x9200,0x9300,0x5400,0x5500,0x5600,0x8900,0x8A00
00070 };
00071
00072
00073 static
00074 byte keypad_char[] = {'7','8','9','-','4','5','6','+','1','2','3','0','.'};
00075
00076
00077 static byte shift=0;
00078
00079 static byte ctrl=0;
00080
00081 static byte alt=0;
00082
00083
00084 queue_t *keyb_queue=NULL;
00085
00086
00087
00088
00089
00090 void keyb_wait()
00091 {
00092 uint32_t retries=500000L;
00093
00094 while (((inportb(KEYB_STATUS) & KEYB_BUSY) == KEYB_BUSY) && retries!=0)
00095 {
00096 retries--;
00097 }
00098 }
00099
00100
00101 void update_leds()
00102 {
00103 int leds;
00104 console_t *curr_cons = get_console_addr( get_curr_console() );
00105 dword IF = GET_IF();
00106
00107 leds = (curr_cons->scroll_lock) |
00108 (curr_cons->num_lock << 1) |
00109 (curr_cons->caps_lock << 2);
00110
00111 disable();
00112
00113 keyb_wait();
00114 outportb(KEYB_PORT, KEYB_LED_CODE);
00115 keyb_wait();
00116 outportb(KEYB_PORT, leds);
00117
00118 SET_IF(IF);
00119 }
00120
00121
00122
00123 word scan_key()
00124 {
00125 static int code, val;
00126 dword IF = GET_IF();
00127
00128 disable();
00129
00130 code = inportb(KEYB_PORT);
00131 val = inportb(KEYB_ACK);
00132 outportb(KEYB_ACK, val | 0x80);
00133 outportb(KEYB_ACK, val);
00134
00135 SET_IF(IF);
00136
00137 return code;
00138 }
00139
00140
00141
00142
00143
00144
00145 void keyboard_handler()
00146 {
00147 task_t *p;
00148 int console, count;
00149
00150 console_t *curr_cons = get_console_addr( get_curr_console() );
00151
00152 word code;
00153
00154 word keypressed = scan_key();
00155
00156
00157 if (ctrl==1 && alt==1 && keypressed==DEL_SCAN) reboot();
00158
00159 if (alt==1) code = with_alt[keypressed];
00160 else if (ctrl==1) code = with_control[keypressed];
00161 else
00162 {
00163 if (curr_cons->caps_lock==0 && shift==0) code = regular[keypressed];
00164 else if (curr_cons->caps_lock==0 && shift==1) code = with_shift[keypressed];
00165 else if (curr_cons->caps_lock==1 && shift==0)
00166 {
00167 code = regular[keypressed];
00168 if (((code&0xFF)>='a') && ((code&0xFF)<='z')) code-='a'-'A';
00169 }
00170 else
00171 {
00172 code = with_shift[keypressed];
00173 if (((code&0xFF)>='A') && ((code&0xFF)<='Z')) code+='a'-'A';
00174 }
00175 if ((curr_cons->num_lock!=shift) && (keypressed>=71 && keypressed<=83))
00176 code = keypad_char[keypressed-71];
00177 }
00178
00179
00180 switch (keypressed)
00181 {
00182 case 42:
00183 shift=1;
00184 break;
00185
00186 case (42+128):
00187 shift=0;
00188 break;
00189
00190 case 54:
00191 shift=1;
00192 break;
00193
00194 case (54+128):
00195 shift=0;
00196 break;
00197
00198 case 56:
00199 alt=1;
00200 break;
00201
00202 case (56+128):
00203 alt=0;
00204 break;
00205
00206 case 29:
00207 ctrl=1;
00208 break;
00209
00210 case (29+128):
00211 ctrl=0;
00212 break;
00213
00214 case 58:
00215 curr_cons->caps_lock ^= 1;
00216 update_leds();
00217 break;
00218
00219 case 69:
00220 curr_cons->num_lock ^= 1;
00221 update_leds();
00222 break;
00223
00224 case 70:
00225 curr_cons->scroll_lock ^= 1;
00226 update_leds();
00227 break;
00228
00229 case 0xE1:
00230
00231 while (scan_key() != 0xC5);
00232 break;
00233
00234 default:
00235
00236
00237
00238
00239 if (!(keypressed & 0x80))
00240 {
00241 if ( (code>=ALT_F1) && (code<=ALT_F10) )
00242 {
00243
00244 console = ((code-ALT_F1) >> 8) + 1;
00245 switch_to_console( console );
00246
00247
00248
00249 count = count_queue( &keyb_queue );
00250 for ( ; count; --count )
00251 {
00252 p = pick_queue( &keyb_queue );
00253 if ( p->console==console )
00254 {
00255 wakeup_task( p );
00256 rem_queue( &keyb_queue, p );
00257 }
00258 }
00259 return;
00260 }
00261
00262 if ( (curr_cons->keyb_buf_count) < KEYB_BUF_DIM )
00263 {
00264 (curr_cons->keyb_buf_count)++;
00265 if ( ++(curr_cons->keyb_buf_write) >= KEYB_BUF_DIM )
00266 curr_cons->keyb_buf_write = 0;
00267 curr_cons->keyb_buffer[curr_cons->keyb_buf_write] = code;
00268 }
00269 else
00270 {
00271
00272 beep();
00273 }
00274 }
00275 break;
00276 }
00277 }
00278
00279
00280 void init_keyboard()
00281 {
00282
00283 install_irq_handler( KEYBOARD_IRQ, (void *)&keyboard_handler );
00284
00285
00286 outportb(KEYB_PORT, KEYB_SET_TYPEMATIC);
00287 keyb_wait();
00288
00289 outportb(KEYB_PORT, 0);
00290
00291
00292 update_leds();
00293 }
00294
00295
00296
00297
00298 int kgetchar()
00299 {
00300 task_t *ct = get_curr_task();
00301 console_t *cons = get_console_addr( ct->console );
00302 word key;
00303 uint32_t IF = GET_IF();
00304
00305 repeat:
00306 disable();
00307
00308 if ( ct->console != get_curr_console() )
00309 {
00310 add_queue( &keyb_queue, ct );
00311 sleep_task( ct );
00312 enable();
00313 idle();
00314 goto repeat;
00315 }
00316
00317 if ( cons->keyb_buf_count==0 )
00318 {
00319 enable();
00320 idle();
00321 goto repeat;
00322 }
00323
00324
00325 (cons->keyb_buf_count)--;
00326 if ( ++(cons->keyb_buf_read) >= KEYB_BUF_DIM )
00327 cons->keyb_buf_read = 0;
00328 key = cons->keyb_buffer[cons->keyb_buf_read];
00329
00330 SET_IF(IF);
00331
00332 return( key );
00333 }
00334
00335
00336
00337
00338
00339
00340
00341 int keyb_read()
00342 {
00343 console_t *cons = get_console_addr( get_curr_task()->console );
00344 word key;
00345 dword IF = GET_IF();
00346
00347
00348 while ( get_curr_task()->console != get_curr_console() )
00349 return(NULL);
00350
00351
00352 if (cons->keyb_buf_count==0) return(NULL);
00353
00354 disable();
00355
00356
00357 (cons->keyb_buf_count)--;
00358 if ( ++(cons->keyb_buf_read) >= KEYB_BUF_DIM )
00359 cons->keyb_buf_read = 0;
00360 key = cons->keyb_buffer[cons->keyb_buf_read];
00361
00362 SET_IF(IF);
00363
00364 return(key);
00365 }
00366
00367