OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [services/] [gfx/] [mw/] [current/] [src/] [drivers/] [ps2kbdmou_ecos.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//=============================================================================
2
//
3
//      ps2kbdmou_ecos.c
4
//
5
//      eCos support for a PS/2 keyboard and mouse.
6
//
7
//=============================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//=============================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    bartv
43
// Date:         2002-04-04
44
// Purpose:      Implement basic keyboard and mouse support for microwindows
45
//               only, interacting directly with the hardware.
46
//
47
//####DESCRIPTIONEND####
48
//=============================================================================
49
 
50
#include <pkgconf/system.h>
51
#include <cyg/infra/cyg_ass.h>
52
#include <cyg/infra/diag.h>
53
#include <cyg/hal/hal_io.h>
54
#include <cyg/hal/hal_intr.h>
55
#include <cyg/hal/drv_api.h>
56
#include <cyg/kernel/kapi.h>
57
#include <microwin/device.h>
58
 
59
#ifdef CYGPKG_KERNEL
60
# include <cyg/kernel/kapi.h>
61
#endif
62
 
63
// ----------------------------------------------------------------------------
64
// Configuration options. For now local to this file.
65
#define CYGDBG_DEVS_PS2KBDMOUSE_VERBOSE         1
66
 
67
#ifdef CYGDBG_DEVS_PS2KBDMOUSE_VERBOSE
68
# define DBG(format, args...)       diag_printf(format, ## args)
69
#else
70
# define DBG(format, args...)
71
#endif
72
 
73
// ----------------------------------------------------------------------------
74
// The hardware.
75
//
76
// On PC's with PS/2 hardware both the mouse and the keyboard are
77
// handled through a single keyboard controller chip. There are four
78
// registers: status, control, input and output. There are also 8-bit
79
// input and output ports which can be manipulated by writing certain
80
// control messages. The registers are accessed via the I/O bus.
81
//
82
// Output means keyboard controller -> cpu.
83
// Input means cpu -> keyboard controller.
84
//
85
// So you need to do a HAL_READ_UINT() to the output register,
86
// and a HAL_WRITE_UINT8 to the input register. They are actually
87
// at the same address...
88
//
89
// The following information was extracted from "The Indispensable
90
// PC Hardware Book" by Messmer, third edition, chapter 34. 
91
 
92
#define KC_OUTPUT       0x060
93
#define KC_INPUT        0x060
94
#define KC_CONTROL      0x064
95
#define KC_STATUS       0x064
96
 
97
// Bits in the status register.
98
#define KC_STATUS_PARE  (0x01 << 7)
99
#define KC_STATUS_TIM   (0x01 << 6)
100
#define KC_STATUS_AUXB  (0x01 << 5)
101
#define KC_STATUS_KEYL  (0x01 << 4)
102
#define KC_STATUS_CD    (0x01 << 3)
103
#define KC_STATUS_SYSF  (0x01 << 2)
104
#define KC_STATUS_INPB  (0x01 << 1)
105
#define KC_STATUS_OUTB  (0x01 << 0)
106
 
107
// Commands that can be written to the control register,
108
// plus for some the results that would come back.
109
#define KC_CONTROL_NULL                 -1
110
#define KC_CONTROL_DISABLE_AUX          0x00A7
111
#define KC_CONTROL_ENABLE_AUX           0x00A8
112
#define KC_CONTROL_CHECK_AUX            0x00A9
113
#define KC_CONTROL_CHECK_AUX_OK             0x000
114
#define KC_CONTROL_CHECK_AUX_CLOCK_LOW      0x001
115
#define KC_CONTROL_CHECK_AUX_CLOCK_HIGH     0x002
116
#define KC_CONTROL_CHECK_AUX_DATA_LOW       0x003
117
#define KC_CONTROL_CHECK_AUX_DATA_HIGH      0x004
118
#define KC_CONTROL_CHECK_AUX_NONE           0x0FF
119
#define KC_CONTROL_SELF_TEST            0x00AA
120
#define KC_CONTROL_SELF_TEST_OK             0x055
121
#define KC_CONTROL_CHECK_KBD            0x00AB
122
#define KC_CONTROL_CHECK_KBD_OK             0x000
123
#define KC_CONTROL_CHECK_KBD_CLOCK_LOW      0x001
124
#define KC_CONTROL_CHECK_KBD_CLOCK_HIGH     0x002
125
#define KC_CONTROL_CHECK_KBD_DATA_LOW       0x003
126
#define KC_CONTROL_CHECK_KBD_DATA_HIGH      0x004
127
#define KC_CONTROL_CHECK_KBD_ERROR          0x0FF
128
#define KC_CONTROL_DISABLE_KBD          0x00AD
129
#define KC_CONTROL_ENABLE_KBD           0x00AE
130
#define KC_CONTROL_READ_INPUT_PORT      0x00C0
131
#define KC_CONTROL_READ_INPUT_PORT_LOW  0x00C1
132
#define KC_CONTROL_READ_INPUT_PORT_HIGH 0x00C2
133
#define KC_CONTROL_READ_OUTPUT_PORT     0x00D0
134
#define KC_CONTROL_WRITE_OUTPUT_PORT    0x00D1
135
#define KC_CONTROL_WRITE_KBD_OUTPUT     0x00D2
136
#define KC_CONTROL_WRITE_AUX_OUTPUT     0x00D3
137
#define KC_CONTROL_WRITE_AUX            0x00D4
138
#define KC_CONTROL_READ_TEST_INPUT      0x00E0
139
#define KC_CONTROL_PULSE                0x00F0
140
 
141
// Additional commands, not from the book...
142
#define KC_CONTROL_READ_MODE            0x0020
143
#define KC_CONTROL_WRITE_MODE           0x0060
144
#define KC_MODE_KBD_INT                 (0x01 << 0)
145
#define KC_MODE_MOU_INT                 (0x01 << 1)
146
#define KC_MODE_SYS                     (0x01 << 2)
147
#define KC_MODE_NO_KEYLOCK              (0x01 << 3)
148
#define KC_MODE_DISABLE_KBD             (0x01 << 4)
149
#define KC_MODE_ENABLE_KBD              (0x01 << 5)
150
#define KC_MODE_KCC                     (0x01 << 6)
151
#define KC_MODE_RFU                     (0x01 << 7)
152
 
153
// The input port
154
#define KC_INPUT_LOCK       (0x01 << 7)
155
#define KC_INPUT_CM         (0x01 << 6)
156
#define KC_INPUT_CM_MONO    (0x01 << 6)
157
#define KC_INPUT_CM_COLOR   (0x00 << 6)
158
#define KC_INPUT_CM_COLOUR  (0x00 << 6)
159
#define KC_INPUT_AUX        (0x01 << 1)
160
#define KC_INPUT_KBD        (0x01 << 0)
161
 
162
// And the output port
163
#define KC_OUTPUT_KBDO      (0x01 << 7)
164
#define KC_OUTPUT_KCLK      (0x01 << 6)
165
#define KC_OUTPUT_AUXB      (0x01 << 5)
166
#define KC_OUTPUT_OUTB      (0x01 << 4)
167
#define KC_OUTPUT_ACLK      (0x01 << 3)
168
#define KC_OUTPUT_AXDO      (0x01 << 2)
169
#define KC_OUTPUT_GA20      (0x01 << 1)
170
#define KC_OUTPUT_SYSR      (0x01 << 0)
171
 
172
// Data from the keyboard
173
#define KC_KBD_OVERFLOW     0x000
174
#define KC_KBD_KEY_ERROR    0x0FF
175
#define KC_KBD_MFII_ID      0x0041AB
176
#define KC_KBD_BAT_COMPLETE 0x0AA
177
#define KC_KBD_ECHO         0x0EE
178
#define KC_KBD_ACK          0x0FA
179
#define KC_KBD_BAT_ERROR    0x0FC
180
#define KC_KBD_RESEND       0x0FE
181
#define KC_KBD_SCANCODE_MIN 0x001
182
// Likely to be incorrect for some modern keyboards
183
#define KC_KBD_SCANCODE_MAX 0x058
184
 
185
// Commands that can be sent to the keyboard. These
186
// are just written to the input register. Some of
187
// them will be followed by additional data.
188
#define KC_KBDC_LED_ONOFF           0x0ED
189
#define KC_KBDC_ECHO                0x0EE
190
#define KC_KBDC_SETSCAN             0x0F0
191
#define KC_KBDC_IDENTIFY            0x0F2
192
#define KC_KBDC_SETREPEAT           0x0F3
193
#define KC_KBDC_ENABLE              0x0F4
194
#define KC_KBDC_STANDARD_DISABLE    0x0F5
195
#define KC_KBDC_STANDARD_ENABLE     0x0F6
196
#define KC_KBDC_RESEND              0x0FE
197
#define KC_KBDC_RESET               0x0FF
198
 
199
// And commands that can be sent to the mouse. These
200
// involve a controller write followed by another
201
// write to the input register.
202
#define KC_MOUSEC_RESET_SCALING     0x0E6
203
#define KC_MOUSEC_SET_SCALING       0x0E7
204
#define KC_MOUSEC_SET_RESOLUTION    0x0E8
205
#define KC_MOUSEC_STATUS            0x0E9
206
#define KC_MOUSEC_SET_STREAM_MODE   0x0EA
207
#define KC_MOUSEC_READ_DATA         0x0EB
208
#define KC_MOUSEC_RESET_WRAP_MODE   0x0EC
209
#define KC_MOUSEC_SET_WRAP_MODE     0x0EE
210
#define KC_MOUSEC_SET_REMOTE_MODE   0x0F0
211
#define KC_MOUSEC_IDENTIFY          0x0F2
212
#define KC_MOUSEC_SET_SAMPLE_RATE   0x0F3
213
#define KC_MOUSEC_ENABLE            0x0F4
214
#define KC_MOUSEC_DISABLE           0x0F5
215
#define KC_MOUSEC_SET_STANDARD      0x0F6
216
#define KC_MOUSEC_RESEND            0x0FE
217
#define KC_MOUSEC_RESET             0x0FF
218
 
219
// Data back from the mouse. Some special characters.
220
#define KC_MOUSE_ACK                0x0FA
221
#define KC_MOUSE_RESEND             0x0FE
222
 
223
// ----------------------------------------------------------------------------
224
// The low-level stuff. Managing the PS/2 hardware is actually quite
225
// messy if you want a robust implementation because of the various
226
// ack's, resend requests, etc.
227
 
228
// The keyboard device. The interrupt handler is responsible for storing
229
// key press and release events in a circular buffer. The poll and read code
230
// will then try to convert these events into something closer to what
231
// microwindows expects. There is an assumption that the poll() and read()
232
// code will be called often enough that there is no risk of overflow.
233
 
234
// A circular buffer of scancodes.
235
#define PS2KBD_SCANCODE_BUFSIZE    64
236
static unsigned char    ps2kbd_scancode_buffer[PS2KBD_SCANCODE_BUFSIZE];
237
static volatile int     ps2kbd_scancode_buffer_head = 0;    // new data written here
238
static volatile int     ps2kbd_scancode_buffer_tail = 0;    // old data extracted from here
239
 
240
// The current mouse state. Just maintain the current X and Y deltas,
241
// button state,, and a delta flag. The hardware will generate
242
// eight-byte mouse data packets, and when a complete packet has been
243
// received the interrupt handler will update the values and set the
244
// delta flag.
245
 
246
#define PS2MOU_DATA_BUFSIZE 12
247
static MWCOORD          ps2mou_dx       = 0;
248
static MWCOORD          ps2mou_dy       = 0;
249
static int              ps2mou_buttons  = 0;
250
static volatile int     ps2mou_changed  = 0;
251
 
252
static unsigned char    ps2mou_buffer[PS2MOU_DATA_BUFSIZE];
253
static int              ps2mou_buffer_index = 0;
254
 
255
// Sending commands. In theory there are a number of variations of
256
// these.
257
//
258
// 1) commands to be sent directly to the controller. The control byte
259
//    goes to KC_CONTROL, and any additional bytes go to KC_INPUT.
260
//    The hardware will either ACK the additional bytes or request
261
//    a resend.  Any replies can be read from KC_OUTPUT, and errors
262
//    are possible.
263
//
264
//    For replies, it is not clear how to distinguish between keyboard
265
//    events that happen at just the wrong moment and the reply data.
266
//
267
// 2) commands for the keyboard. These just get written directly to
268
//    the input buffer, one character at a time with ACKs or resends
269
//    in between.
270
//
271
// 3) commands for the mouse. These involve a write of 0xD4 to the
272
//    control port followed by a write to the input buffer. The latter
273
//    results in ACKs or resends.
274
 
275
static unsigned char*   ps2_command             = NULL;
276
static int              ps2_command_mouse       = 0;
277
static int              ps2_command_index       = 0;
278
static int              ps2_command_length      = 0;
279
static volatile int     ps2_command_ack         = 0;
280
static int              ps2_command_mouse_waiting_for_ack   = 0;
281
 
282
// ----------------------------------------------------------------------------
283
// Decoding of mouse packets. There are lots of different rodent or
284
// rodent-like devices out there, all implementing subtly different
285
// protocols. A general-purpose solution would try to cope with all
286
// of them. The eCos approach would be to allow just one to be
287
// configured statically.
288
 
289
// Support for Synaptics touchpads and compatible. This assumes
290
// default relative format. Byte 0 contains various flags and
291
// the button state. Byte 1 contains X-offset, byte 2 contains
292
// the y-offset.
293
 
294
static int              ps2mou_packet_size  = 3;
295
static void
296
ps2mou_synaptics_translate(void)
297
{
298
    int new_buttons = 0;
299
    int dx, dy;
300
 
301
    // The packet consists of six bytes. Bit 3 of the first packet
302
    // should be set. If that condition is not satisfied then we
303
    // are in trouble and we may need to perform some sort of reset.
304
    if (0 == (ps2mou_buffer[0] & 0x08)) {
305
        // FIXME: perform some sort of reset to get the world
306
        // back in sync.
307
        return;
308
    }
309
    // Byte 0 holds the button flags.
310
    if (0 != (ps2mou_buffer[0] & (0x01 << 0))) {
311
        new_buttons = MWBUTTON_L;
312
    }
313
    if (0 != (ps2mou_buffer[0] & (0x01 << 1))) {
314
        new_buttons |= MWBUTTON_R;
315
    }
316
    ps2mou_buttons  = new_buttons;
317
 
318
    dx = ps2mou_buffer[1];
319
    if (0 != (ps2mou_buffer[0] & (0x001 << 4))) {
320
        // Negative number.
321
        if (0 != (ps2mou_buffer[0] & (0x01 << 6))) {
322
            // -ve overflow
323
            dx = -256;
324
        } else {
325
            dx = 0 - (256 - dx);
326
        }
327
    } else if (0 != (ps2mou_buffer[0] & (0x01 << 6))) {
328
        // +ve overflow
329
        dx = 256;
330
    }
331
    ps2mou_dx += dx;
332
 
333
    dy = ps2mou_buffer[2];
334
    if (0 != (ps2mou_buffer[0] & (0x01 << 5))) {
335
        // Negative number.
336
        if (0 != (ps2mou_buffer[0] & (0x01 << 7))) {
337
            // -ve overflow
338
            dy = -256;
339
        } else {
340
            // -ve signed, bottom byte only
341
            dy = 0 - (256 - dy);
342
        }
343
    } else if (0 != (ps2mou_buffer[0] & (0x01 << 7))) {
344
        // +ve overflow
345
        dy = 256;
346
    }
347
    ps2mou_dy += dy;
348
 
349
    ps2mou_changed      = 1;
350
}
351
 
352
// Mouse data. A PS/2 mouse sends events in the form of
353
// eight-byte packets. Some of the fields are officially
354
// reserved and ignored for now.
355
#define KC_MOUSE_DATA_FLAGS         0x00
356
#define KC_MOUSE_DATA_FLAGS_YOV     (0x01 << 7)
357
#define KC_MOUSE_DATA_FLAGS_XOV     (0x01 << 6)
358
#define KC_MOUSE_DATA_FLAGS_YNG     (0x01 << 5)
359
#define KC_MOUSE_DATA_FLAGS_XNG     (0x01 << 4)
360
#define KC_MOUSE_DATA_FLAGS_RIG     (0x01 << 1)
361
#define KC_MOUSE_DATA_FLAGS_LEF     (0x01 << 0)
362
#define KC_MOUSE_DATA_X             0x02
363
#define KC_MOUSE_DATA_Y             0x04
364
#define KC_MOUSE_DATA_SIZE          0x08
365
 
366
// ----------------------------------------------------------------------------
367
// An interrupt has occurred. Usually this means that there is data
368
// in the output register, although errors are possible as well. The
369
// data can be keyboard scancodes, parts of a mouse packet, or
370
// replies to control messages.
371
//
372
// For now errors are ignored, including parity and timeout errors. In
373
// theory these are supposed to be handled by requesting a resend. In
374
// practice that seems to cause as many complications as it might
375
// solve. For example what should happen if there is already a command
376
// being sent?
377
//
378
// The controller interrupts at two separate vectors, one for keyboard
379
// and another for mouse. If nested interrupts are enabled this could
380
// cause problems with nested calls to ps2_isr() updating the global
381
// data in the wrong order. It may be necessary to have a volatile flag
382
// to detect nesting, accompanied by an early acknowledge and return to
383
// the interrupted interrupt handler.
384
 
385
static cyg_uint32
386
ps2_isr(cyg_vector_t isr_vector, cyg_addrword_t isr_data)
387
{
388
    int             status;
389
    unsigned char   data;
390
 
391
    CYG_UNUSED_PARAM(cyg_addrword_t, isr_data);
392
 
393
    HAL_READ_UINT8(KC_STATUS, status);
394
    while (status & KC_STATUS_OUTB) {
395
        HAL_READ_UINT8(KC_OUTPUT, data);
396
 
397
        if (status & KC_STATUS_AUXB) {
398
            // Data from the mouse. This will be either an ACK for a
399
            // command, a resend request, or a byte for the current
400
            // packet. When a complete 8-byte packet has been received
401
            // it can be processed. When an ACK is received the next
402
            // byte for the current command should get sent, or on
403
            // completion the sending code can be woken up.
404
            //
405
            // The mouse can also send back other data, e.g. in response
406
            // to a determine-status request. These are disallowed
407
            // because there is no obvious way of separating out such
408
            // data from a current mouse packet being transferred.
409
            //
410
            // There may also be special bytes sent for disconnect and
411
            // reconnect. It is not clear how to distinguish those
412
            // from packet data either.
413
            if (ps2_command_mouse_waiting_for_ack && ((KC_MOUSE_ACK == data) || (KC_MOUSE_RESEND == data))) {
414
                int tmp;
415
 
416
                if (KC_MOUSE_ACK == data) {
417
                    // Is there another byte to be sent?
418
                    ps2_command_index++;
419
                    if (ps2_command_index < ps2_command_length) {
420
                        // Send the next byte for the current command
421
                        do {
422
                            HAL_READ_UINT8(KC_STATUS, tmp);
423
                        } while (tmp & KC_STATUS_INPB);
424
                        HAL_WRITE_UINT8(KC_CONTROL, KC_CONTROL_WRITE_AUX);
425
                        do {
426
                            HAL_READ_UINT8(KC_STATUS, tmp);
427
                        } while (tmp & KC_STATUS_INPB);
428
                        HAL_WRITE_UINT8(KC_INPUT, ps2_command[ps2_command_index]);
429
                    } else {
430
                        // The whole command has been sent and acknowledged.
431
                        // Allow the polling thread to resume.
432
                        ps2_command_index   = 0;
433
                        ps2_command_length  = 0;
434
                        ps2_command         = NULL;
435
                        ps2_command_ack     = 1;
436
                        ps2_command_mouse_waiting_for_ack = 0;
437
                    }
438
                } else {
439
                    // A resend request for the current byte.
440
                    do {
441
                        HAL_READ_UINT8(KC_STATUS, tmp);
442
                    } while (tmp & KC_STATUS_INPB);
443
                    HAL_WRITE_UINT8(KC_CONTROL, KC_CONTROL_WRITE_AUX);
444
                    do {
445
                        HAL_READ_UINT8(KC_STATUS, tmp);
446
                    } while (tmp & KC_STATUS_INPB);
447
                    HAL_WRITE_UINT8(KC_INPUT, ps2_command[ps2_command_index]);
448
                }
449
            } else {
450
                ps2mou_buffer[ps2mou_buffer_index++] = data;
451
                if (ps2mou_packet_size == ps2mou_buffer_index) {
452
                    // A complete packet has been received.
453
                    ps2mou_synaptics_translate();
454
                    ps2mou_buffer_index = 0;    // Ready for the next packet
455
                }
456
            }
457
        } else {
458
            // Data from the keyboard. Usually this will be a scancode.
459
            // There are a number of other possibilities such as
460
            // echo replies, resend requests, and acks.
461
            if ((KC_KBD_ACK == data) && (NULL != ps2_command) && !ps2_command_mouse_waiting_for_ack) {
462
                // Send the next byte for the current command, or
463
                // else we have completed.
464
                ps2_command_index++;
465
                if (ps2_command_index < ps2_command_length) {
466
                    int tmp;
467
                    do {
468
                        HAL_READ_UINT8(KC_STATUS, tmp);
469
                    } while (tmp & KC_STATUS_INPB);
470
                    HAL_WRITE_UINT8(KC_INPUT, ps2_command[ps2_command_index]);
471
                } else {
472
                    ps2_command_index   = 0;
473
                    ps2_command_length  = 0;
474
                    ps2_command         = NULL;
475
                    ps2_command_ack     = 1;
476
                }
477
            } else if ((KC_KBD_RESEND == data) && (NULL != ps2_command) && !ps2_command_mouse_waiting_for_ack) {
478
                int tmp;
479
                do {
480
                    HAL_READ_UINT8(KC_STATUS, tmp);
481
                } while (tmp & KC_STATUS_INPB);
482
                HAL_WRITE_UINT8(KC_INPUT, ps2_command[ps2_command_index]);
483
            } else {
484
                if (((ps2kbd_scancode_buffer_head + 1) % PS2KBD_SCANCODE_BUFSIZE) == ps2kbd_scancode_buffer_tail) {
485
                    // Already full. The data has to be discarded.
486
                } else {
487
                    ps2kbd_scancode_buffer[ps2kbd_scancode_buffer_head] = data;
488
                    ps2kbd_scancode_buffer_head = (ps2kbd_scancode_buffer_head + 1) % PS2KBD_SCANCODE_BUFSIZE;
489
                }
490
            }
491
        }
492
 
493
        // Just in case the keyboard controller is fast enough to send another byte,
494
        // go around again.
495
        HAL_READ_UINT8(KC_STATUS, status);
496
    }
497
 
498
    // The interrupt has been fully handled. For now there is no point
499
    // in running a DSR.
500
    cyg_drv_interrupt_acknowledge(isr_vector);
501
    return CYG_ISR_HANDLED;
502
}
503
 
504
// For now the DSR does nothing. 
505
static void
506
ps2_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
507
{
508
    CYG_UNUSED_PARAM(cyg_vector_t, vector);
509
    CYG_UNUSED_PARAM(cyg_ucount32, count);
510
    CYG_UNUSED_PARAM(cyg_addrword_t, data);
511
}
512
 
513
 
514
// Sending out a command. The controller command, if any, gets sent here.
515
// This is followed by the first byte for the keyboard or mouse. The
516
// remaining bytes and any retransmits will be handled by the interrupt
517
// handler.
518
static void
519
ps2_send_command(int controller_command, unsigned char* command, int length, int mouse)
520
{
521
    int     status;
522
 
523
    CYG_PRECONDITION(NULL == ps2_command, "Only one send command is allowed at a time");
524
    CYG_PRECONDITION((KC_CONTROL_NULL != controller_command) || (NULL != command), "no-op");
525
    CYG_PRECONDITION(!mouse || (KC_CONTROL_NULL == controller_command), "cannot combine controller and mouse commands");
526
 
527
    ps2_command         = command;
528
    ps2_command_index   = 0;
529
    ps2_command_length  = length;
530
    ps2_command_mouse   = 0;
531
    ps2_command_ack     = 0;
532
 
533
    if (KC_CONTROL_NULL != controller_command) {
534
        do {
535
            HAL_READ_UINT8(KC_STATUS, status);
536
        } while (status & KC_STATUS_INPB);
537
        HAL_WRITE_UINT8(KC_CONTROL, controller_command);
538
    }
539
 
540
    if (length > 0) {
541
        if (mouse) {
542
            do {
543
                HAL_READ_UINT8(KC_STATUS, status);
544
            } while (status & KC_STATUS_INPB);
545
            HAL_WRITE_UINT8(KC_CONTROL, KC_CONTROL_WRITE_AUX);
546
        }
547
        do {
548
            HAL_READ_UINT8(KC_STATUS, status);
549
        } while (status & KC_STATUS_INPB);
550
        HAL_WRITE_UINT8(KC_INPUT, command[0]);
551
    }
552
}
553
 
554
// For now there is little difference between polled and non-polled
555
// mode, they both just spin until the ACK byte is received. The
556
// polled version just calls the interrupt handler as well. This is
557
// probably acceptable for now because commands only get sent during
558
// initialization, but eventually the non-polled version should be
559
// using a synch primitive signalled by the dsr.
560
//
561
// ACKs are only generated when there is data to be sent, not for
562
// operations on the control register.
563
//
564
// For keyboard commands there is no real problem because the ACK
565
// character 0xFA does not match a valid scancode. For the mouse
566
// things are more difficult because 0xFA could be present in the
567
// data, e.g. as a fairly large movement. Therefore the interrupt
568
// handler needs to know whether or not a mouse ACK is expected.
569
// It is assumed that the ACK and any actual 0xFA data get sent
570
// within a byte of each other so that the 0xFA still ends up in
571
// the right place in the buffer.
572
//
573
// A couple of commands do not result in an ACK. For the mouse this
574
// includes reset-wrap-mode and reset. For the keyboard this includes
575
// echo. These commands are not currently used, so there is no need
576
// to worry about the special cases.
577
 
578
static void
579
ps2_send_command_poll(int controller_command, unsigned char* command, int length, int mouse)
580
{
581
    if ((NULL != command) && mouse) {
582
        ps2_command_mouse_waiting_for_ack = 1;
583
    }
584
    ps2_send_command(controller_command, command, length, mouse);
585
    if (NULL != command) {
586
        for ( ; !ps2_command_ack; ) {
587
            ps2_isr( CYGNUM_HAL_INTERRUPT_KEYBOARD, 0);
588
        }
589
        ps2_command_ack = 0;
590
    }
591
}
592
 
593
static void
594
ps2_send_command_wait(int controller_command, unsigned char* command, int length, int mouse)
595
{
596
    if ((NULL != command) && mouse) {
597
        ps2_command_mouse_waiting_for_ack = 1;
598
    }
599
    ps2_send_command(controller_command, command, length, mouse);
600
    if (NULL != command) {
601
        for ( ; !ps2_command_ack; )
602
            ;
603
        ps2_command_ack = 0;
604
    }
605
}
606
 
607
 
608
// ----------------------------------------------------------------------------
609
// Hardware initialization and the interrupt handling.
610
 
611
static cyg_handle_t     ps2kbd_interrupt_handle;
612
static cyg_interrupt    ps2kbd_interrupt_data;
613
static cyg_handle_t     ps2mouse_interrupt_handle;
614
static cyg_interrupt    ps2mouse_interrupt_data;
615
 
616
static void
617
ps2_initialize(void)
618
{
619
    unsigned char   buf[2];
620
    int             status, data;
621
 
622
    // Only perform initialization once, not for both kbd and mouse.
623
    static int  initialized = 0;
624
    if (initialized) {
625
        return;
626
    }
627
    initialized++;
628
 
629
    // Start by masking out the interrupts. Other code such as the HAL
630
    // or RedBoot may think it currently owns the keyboard, and I do
631
    // not want any interference from them while setting up the
632
    // interrupt handlers.
633
    cyg_drv_interrupt_mask_intunsafe(CYGNUM_HAL_INTERRUPT_KEYBOARD);
634
    cyg_drv_interrupt_mask_intunsafe(CYGNUM_HAL_INTERRUPT_IRQ12);
635
 
636
    // Install my own interrupt handler, overwriting anything that might
637
    // be there already.
638
    cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_KEYBOARD, 0, 0,
639
                             &ps2_isr, &ps2_dsr, &ps2kbd_interrupt_handle, &ps2kbd_interrupt_data);
640
    cyg_drv_interrupt_attach(ps2kbd_interrupt_handle);
641
    cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_IRQ12, 0, 0,
642
                             &ps2_isr, &ps2_dsr, &ps2mouse_interrupt_handle, &ps2mouse_interrupt_data);
643
    cyg_drv_interrupt_attach(ps2mouse_interrupt_handle);
644
 
645
    // Get the device into a known state.
646
    ps2_send_command(KC_CONTROL_DISABLE_AUX, NULL, 0, 0);
647
    ps2_send_command(KC_CONTROL_DISABLE_KBD, NULL, 0, 0);
648
 
649
    // Discard any current data.
650
    HAL_READ_UINT8(KC_STATUS, status);
651
    while (status & KC_STATUS_OUTB) {
652
        HAL_READ_UINT8(KC_OUTPUT, data);
653
        HAL_READ_UINT8(KC_STATUS, status);
654
    }
655
 
656
    // Now restart and reset the keyboard.
657
    ps2_send_command(KC_CONTROL_ENABLE_KBD, NULL, 0, 0);
658
    buf[0] = KC_KBDC_STANDARD_DISABLE;
659
    ps2_send_command_poll(KC_CONTROL_NULL, buf, 1, 0);
660
    buf[0] = KC_KBDC_LED_ONOFF;
661
    buf[1] = 0;
662
    ps2_send_command_poll(KC_CONTROL_NULL, buf, 2, 0);
663
    // The keyboard-specific initialization can now reenable the keyboard
664
    // using enable
665
 
666
    // Similarly for a mouse
667
    // Standard mode means 100 samples/s, 1:1 scaling, stream mode, 4 counts/mm resolution,
668
    // and transferdisabled. Stream mode is important, that means mouse data will
669
    // be immediately available rather than requiring separate control messages to
670
    // read a packet.
671
    ps2_send_command(KC_CONTROL_ENABLE_AUX, NULL, 0, 0);
672
    buf[0] = KC_MOUSEC_SET_STANDARD;
673
    ps2_send_command_poll(KC_CONTROL_NULL, buf, 1, 1);
674
    buf[0] = KC_MOUSEC_SET_SAMPLE_RATE;
675
    buf[1] = 0x0A;
676
    ps2_send_command_poll(KC_CONTROL_NULL, buf, 2, 1);
677
 
678
    // WRITE_MODE does not appear to involve an ACK
679
    ps2_send_command_poll(KC_CONTROL_WRITE_MODE, NULL, 0, 0);
680
    do {
681
        HAL_READ_UINT8(KC_STATUS, status);
682
    } while (status & KC_STATUS_INPB);
683
    HAL_WRITE_UINT8(KC_INPUT, KC_MODE_KBD_INT | KC_MODE_MOU_INT | KC_MODE_SYS | KC_MODE_KCC);
684
 
685
    cyg_drv_interrupt_unmask_intunsafe(CYGNUM_HAL_INTERRUPT_KEYBOARD);
686
    cyg_drv_interrupt_unmask_intunsafe(CYGNUM_HAL_INTERRUPT_IRQ12);
687
}
688
 
689
// ----------------------------------------------------------------------------
690
static int
691
PS2Mouse_Open(MOUSEDEVICE* pmd)
692
{
693
    unsigned char buf[1];
694
    ps2_initialize();
695
    buf[0] = KC_MOUSEC_ENABLE;
696
    ps2_send_command_wait(KC_CONTROL_NULL, buf, 1, 1);
697
}
698
 
699
// Closing the mouse is equivalent to disabling. It is assumed that we
700
// are not in the middle of a packet transfer, which could really
701
// confuse things.
702
static void
703
PS2Mouse_Close(void)
704
{
705
    unsigned char buf[1];
706
    buf[0] = KC_MOUSEC_SET_STANDARD;
707
    ps2_send_command_wait(KC_CONTROL_NULL, buf, 1, 1);
708
    ps2mou_buffer_index = 0;
709
}
710
 
711
static int
712
PS2Mouse_GetButtonInfo(void)
713
{
714
    return MWBUTTON_L | MWBUTTON_R;
715
}
716
 
717
// The mouse is used in its default setup, which means 1:1 scaling.
718
// Setting the threshold to 5 seems to match most other drivers...
719
static void
720
PS2Mouse_GetDefaultAccel(int* pscale, int* pthresh)
721
{
722
    if (NULL != pscale) {
723
        *pscale = 1;
724
    }
725
    if (NULL != pthresh) {
726
        *pthresh = 5;
727
    }
728
}
729
 
730
static int
731
PS2Mouse_Read(MWCOORD* dx_arg, MWCOORD* dy_arg, MWCOORD* dz_arg, int* bp_arg)
732
{
733
    int         result  = 0;
734
    MWCOORD     dx      = 0;
735
    MWCOORD     dy      = 0;
736
    int         buttons = 0;
737
 
738
    cyg_drv_isr_lock();
739
    if (ps2mou_changed) {
740
        dx              = ps2mou_dx;
741
        dy              = 0 - ps2mou_dy;    // microwindows directions are the opposite from the hardware
742
        buttons         = ps2mou_buttons;
743
        ps2mou_dx       = 0;
744
        ps2mou_dy       = 0;
745
        ps2mou_changed  = 0;
746
        result = 1;
747
    }
748
    cyg_drv_isr_unlock();
749
    if (result) {
750
        if (NULL != dx_arg) {
751
            *dx_arg = dx;
752
        }
753
        if (NULL != dy_arg) {
754
            *dy_arg = dy;
755
        }
756
        if (NULL != dz_arg) {
757
            *dz_arg = 0;
758
        }
759
        if (NULL != bp_arg) {
760
            *bp_arg = buttons;
761
        }
762
    }
763
    return result;
764
}
765
 
766
static int
767
PS2Mouse_Poll(void)
768
{
769
    return 0 != ps2mou_changed;
770
}
771
 
772
MOUSEDEVICE mousedev = {
773
    PS2Mouse_Open,
774
    PS2Mouse_Close,
775
    PS2Mouse_GetButtonInfo,
776
    PS2Mouse_GetDefaultAccel,
777
    PS2Mouse_Read,
778
    PS2Mouse_Poll
779
};
780
 
781
// ----------------------------------------------------------------------------
782
// Extracting data from the scancode buffer and turning it into
783
// ASCII. This is only called from thread context by the poll() and
784
// read() routines, although the scancode buffer is updated in ISR
785
// context.
786
 
787
// The current keyboard event, if any. This involves processing
788
// the scancodes held in the circular buffer and translating them
789
// to ASCII.
790
static MWKEY        ps2kbd_current_key          = MWKEY_UNKNOWN;
791
static MWKEYMOD     ps2kbd_current_modifiers    = 0;
792
static MWSCANCODE   ps2kbd_current_scancode     = 0;
793
static int          ps2kbd_current_keydown      = 0;
794
 
795
// Translation between scancodes and characters, i.e. keymaps.
796
// For now a relatively simple approach is used. The keymaps
797
// only cope with shifted vs. unshifted. The control key
798
// is handled specially. Anything cleverer is left to microwindows.
799
//
800
// Microwindows excepts key events in the form of MWKEY's, which
801
// are unsigned shorts. Special keys such as the function keys
802
// have suitable #define's in mwtypes.h.
803
//
804
// There is a complication with PC keyboards in that some keys
805
// generate multi-byte sequences, usually starting with 0xE0
806
 
807
typedef struct ps2kbd_keymap_entry {
808
    MWKEY       normal;
809
    MWKEY       shifted;
810
} ps2kbd_keymap_entry;
811
 
812
// This keymap is for a Dell Inspiron laptop with a Japanese
813
// keyboard. It may not match exactly with other keyboards,
814
// but is probably good enough for now.
815
 
816
static const ps2kbd_keymap_entry ps2kbd_keymap[] = {
817
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },            // Scancode 0 unused
818
    { MWKEY_ESCAPE,     MWKEY_ESCAPE },
819
    { '1',              '!' },
820
    { '2',              '"' },
821
    { '3',              '#' },
822
    { '4',              '$' },
823
    { '5',              '%' },
824
    { '6',              '&' },
825
    { '7',              '\'' },
826
    { '8',              '(' },
827
    { '9',              ')' },                      // Scancode 10
828
    { '0',              '~' },
829
    { '-',              '=' },
830
    { '^',              '_' },
831
    { MWKEY_BACKSPACE,  MWKEY_BACKSPACE },
832
    { MWKEY_TAB,        MWKEY_TAB },
833
    { 'q',              'Q' },                      // 0x10
834
    { 'w',              'W' },
835
    { 'e',              'E' },
836
    { 'r',              'R' },
837
    { 't',              'T' },                      // 20
838
    { 'y',              'Y' },
839
    { 'u',              'U' },
840
    { 'i',              'I' },
841
    { 'o',              'O' },
842
    { 'p',              'P' },
843
    { '@',              '`' },
844
    { '[',              '{' },
845
    { MWKEY_ENTER,      MWKEY_ENTER },
846
    { MWKEY_LCTRL,      MWKEY_LCTRL },
847
    { 'a',              'A' },                      // 30
848
    { 's',              'S' },
849
    { 'd',              'D' },                      // 0x20
850
    { 'f',              'F' },
851
    { 'g',              'G' },
852
    { 'h',              'H' },
853
    { 'j',              'J' },
854
    { 'k',              'K' },
855
    { 'l',              'L' },
856
    { ';',              '+' },
857
    { ':',              '*' },                      // 40
858
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },            // Japanese-only, top-left below escape
859
    { MWKEY_LSHIFT,     MWKEY_LSHIFT },
860
    { ']',              '}' },
861
    { 'z',              'Z' },
862
    { 'x',              'X' },
863
    { 'c',              'C' },
864
    { 'v',              'V' },
865
    { 'b',              'B' },                      // 0x30
866
    { 'n',              'N' },
867
    { 'm',              'M' },                      // 50
868
    { ',',              '<' },
869
    { '.',              '>' },
870
    { '/',              '?' },
871
    { MWKEY_RSHIFT,     MWKEY_RSHIFT },
872
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },            // unused ?
873
    { MWKEY_LALT,       MWKEY_LALT },
874
    { ' ',              ' ' },                      // space bar
875
    { MWKEY_CAPSLOCK,   MWKEY_CAPSLOCK },
876
    { MWKEY_F1,         MWKEY_F1 },
877
    { MWKEY_F2,         MWKEY_F2 },                 // 60
878
    { MWKEY_F3,         MWKEY_F3 },
879
    { MWKEY_F4,         MWKEY_F4 },
880
    { MWKEY_F5,         MWKEY_F5 },
881
    { MWKEY_F6,         MWKEY_F6 },                 // 0x40
882
    { MWKEY_F7,         MWKEY_F7 },
883
    { MWKEY_F8,         MWKEY_F8 },
884
    { MWKEY_F9,         MWKEY_F9 },
885
    { MWKEY_F10,        MWKEY_F10 },
886
    { MWKEY_NUMLOCK,    MWKEY_NUMLOCK },
887
    { MWKEY_SCROLLOCK,  MWKEY_SCROLLOCK },          // 70
888
    { MWKEY_KP7,        MWKEY_KP7 },                // Keypad, not actually present on laptop
889
    { MWKEY_KP8,        MWKEY_KP8 },                // But accessible via Fn and some centre keys
890
    { MWKEY_KP9,        MWKEY_KP9 },
891
    { MWKEY_KP_MINUS,   MWKEY_KP_MINUS },
892
    { MWKEY_KP4,        MWKEY_KP4 },
893
    { MWKEY_KP5,        MWKEY_KP5 },
894
    { MWKEY_KP6,        MWKEY_KP6 },
895
    { MWKEY_KP_PLUS,    MWKEY_KP_PLUS },
896
    { MWKEY_KP1,        MWKEY_KP1 },
897
    { MWKEY_KP2,        MWKEY_KP2 },                // 80, 0x50
898
    { MWKEY_KP3,        MWKEY_KP3 },
899
    { MWKEY_KP0,        MWKEY_KP0 },
900
    { MWKEY_KP_PERIOD,  MWKEY_KP_PERIOD },
901
    // There are now big gaps 
902
    // F11 and F12 are 0x57 and 0x58
903
    // 0x70, 0x79 and 0x7b are Japanese compose keys.
904
    // 0x73 is backslash and another _
905
    // 0x7d is yen and pipe.
906
    // These could be handled by special-case code in the scancode
907
    // translation routine, but at 4 bytes per table entry
908
    // it is probably just as efficient to extend the table.
909
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },            // 84, 0x53
910
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
911
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
912
    { MWKEY_F11,        MWKEY_F11 },
913
    { MWKEY_F12,        MWKEY_F12 },
914
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
915
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },            // 90
916
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
917
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
918
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
919
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
920
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
921
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },            // 0x60
922
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
923
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
924
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
925
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },            // 100
926
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
927
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
928
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
929
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
930
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
931
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
932
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
933
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
934
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
935
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },            // 110
936
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
937
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },            // 0x70
938
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
939
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
940
    { '\\',             '_' },
941
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
942
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
943
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
944
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
945
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },            // 120
946
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
947
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
948
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
949
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
950
    { MWKEY_UNKNOWN,    '|' },                      // 125
951
    // In theory there could also be 126 and 127, but those are unused.
952
    // But putting them into the table avoids a special case test in the code,
953
    // for a cost of only eight bytes.
954
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
955
    { MWKEY_UNKNOWN,    MWKEY_UNKNOWN },
956
};
957
 
958
// Now for the E0 sequences. The standard ones are in the range 0x47 to 0x53
959
// 0xE0, 0x5B is the Left Windows key. 0x5C would normally be the right one.
960
// 0xE0, 0x5D is the Menu key. The 
961
// The Dell has some additional ones for the dvd player, ignored.
962
// PrintScreen generates a simple sequence 0xE0, 0x2A, 0xE0, 0x37, 0xE0, 0xB7, 0xE0, 0xAA
963
// Break generates 0xE1, 0x1D, 0x45, 0xE1, 0x9D, 0xC5
964
 
965
#define PS2KBD_E0_MIN   0x47
966
static const MWKEY ps2kbd_e0_map[] = {
967
    MWKEY_HOME,         // 0x47
968
    MWKEY_UP,           // 0x48
969
    MWKEY_PAGEUP,       // 0x49
970
    MWKEY_UNKNOWN,
971
    MWKEY_LEFT,         // 0x4B
972
    MWKEY_UNKNOWN,
973
    MWKEY_RIGHT,        // 0x4D
974
    MWKEY_UNKNOWN,
975
    MWKEY_END,          // 0x4F
976
    MWKEY_DOWN,         // 0x50
977
    MWKEY_PAGEDOWN,     // 0x51
978
    MWKEY_INSERT,       // 0x52
979
    MWKEY_DELETE,       // 0x53
980
    MWKEY_UNKNOWN,
981
    MWKEY_UNKNOWN,
982
    MWKEY_UNKNOWN,
983
    MWKEY_UNKNOWN,
984
    MWKEY_UNKNOWN,
985
    MWKEY_UNKNOWN,
986
    MWKEY_UNKNOWN,
987
    MWKEY_LMETA,        // 0x5B
988
    MWKEY_RMETA,        // 0x5C
989
    MWKEY_MENU          // 0x5D
990
};
991
#define PS2KBD_E0_MAX   0x5D
992
 
993
// Modifier translations. All modifiers are supported by
994
// this table, even though the keyboard may not actually
995
// have all of them.
996
typedef struct ps2kbd_modifier_entry {
997
    MWKEY       key;
998
    MWKEYMOD    modifier;
999
    int         toggle;
1000
} ps2kbd_modifier_entry;
1001
 
1002
static const ps2kbd_modifier_entry ps2kbd_modifier_map[] = {
1003
    { MWKEY_LSHIFT,     MWKMOD_LSHIFT,  0 },
1004
    { MWKEY_RSHIFT,     MWKMOD_RSHIFT,  0 },
1005
    { MWKEY_LCTRL,      MWKMOD_LCTRL,   0 },
1006
    { MWKEY_RCTRL,      MWKMOD_RCTRL,   0 },
1007
    { MWKEY_LALT,       MWKMOD_LALT,    0 },
1008
    { MWKEY_RALT,       MWKMOD_RALT,    0 },
1009
    { MWKEY_LMETA,      MWKMOD_LMETA,   0 },
1010
    { MWKEY_RMETA,      MWKMOD_RMETA,   0 },
1011
    { MWKEY_NUMLOCK,    MWKMOD_NUM,     1 },
1012
    { MWKEY_CAPSLOCK,   MWKMOD_CAPS,    1 },
1013
    { MWKEY_ALTGR,      MWKMOD_ALTGR,   0 },
1014
    { MWKEY_SCROLLOCK,  MWKMOD_SCR,     1 },
1015
    { MWKEY_UNKNOWN,    MWKMOD_NONE }
1016
};
1017
 
1018
static void
1019
ps2kbd_process_scancodes(void)
1020
{
1021
    static int      e0_seen             = 0;
1022
    static MWKEY    pending_up          = MWKEY_UNKNOWN;
1023
    static int      pending_scancode    = 0;
1024
    static int      discard             = 0;
1025
    int scancode;
1026
    int i;
1027
 
1028
    CYG_PRECONDITION(MWKEY_UNKNOWN == ps2kbd_current_key, "There should be no pending key");
1029
 
1030
    if (MWKEY_UNKNOWN != pending_up) {
1031
        ps2kbd_current_key          = pending_up;
1032
        ps2kbd_current_scancode     = pending_scancode;
1033
        ps2kbd_current_keydown      = 0;
1034
        pending_up                  = MWKEY_UNKNOWN;
1035
        return;
1036
    }
1037
 
1038
    while (MWKEY_UNKNOWN == ps2kbd_current_key) {
1039
        // The ISR will manipulate the scancode buffer directly, so
1040
        // interrupts have to be disabled temporarily.
1041
        scancode = -1;
1042
        cyg_drv_isr_lock();
1043
        if (ps2kbd_scancode_buffer_head != ps2kbd_scancode_buffer_tail) {
1044
            scancode = ps2kbd_scancode_buffer[ps2kbd_scancode_buffer_tail];
1045
            ps2kbd_scancode_buffer_tail = (ps2kbd_scancode_buffer_tail + 1) % PS2KBD_SCANCODE_BUFSIZE;
1046
        }
1047
        cyg_drv_isr_unlock();
1048
 
1049
        if (scancode == -1) {
1050
            // No more data to be processed.
1051
            break;
1052
        }
1053
 
1054
        // Are we in one of the special sequences, where bytes should be
1055
        // discarded?
1056
        if (discard > 0) {
1057
            discard -= 1;
1058
            continue;
1059
        }
1060
 
1061
        // A real scancode has been extracted. Are we in an E0 sequence?
1062
        if (e0_seen) {
1063
            e0_seen = 0;
1064
            ps2kbd_current_keydown = (0 == (scancode & 0x0080));
1065
            scancode &= 0x007F;
1066
            if ((scancode >= PS2KBD_E0_MIN) && (scancode <= PS2KBD_E0_MAX)) {
1067
                ps2kbd_current_key = ps2kbd_e0_map[scancode - PS2KBD_E0_MIN];
1068
                ps2kbd_current_scancode = 0x80 + scancode - PS2KBD_E0_MIN;  // Invent a key scancode
1069
            }
1070
            // We may or may not have a valid keycode at this time, so go
1071
            // around the loop again to check for MWKEY_UNKNOWN
1072
            continue;
1073
        }
1074
 
1075
        // Is this the start of an E0 sequence?
1076
        if (0x00E0 == scancode) {
1077
            e0_seen = 1;
1078
            continue;
1079
        }
1080
 
1081
        // How about E1?
1082
        if (0x00E1 == scancode) {
1083
            // For now there is only one key which generates E1 sequences
1084
            ps2kbd_current_key      = MWKEY_BREAK;
1085
            ps2kbd_current_keydown  = 1;
1086
            ps2kbd_current_scancode = 0x00E1;   // Invent another key scancode
1087
            pending_up              = MWKEY_BREAK;
1088
            pending_scancode        = 0x00E1;
1089
            discard = 5;
1090
            return;
1091
        }
1092
 
1093
        // Must be an ordinary key.
1094
        ps2kbd_current_keydown  = (0 == (scancode & 0x0080));
1095
        scancode &= 0x007F;
1096
        ps2kbd_current_scancode = scancode;
1097
        ps2kbd_current_key      = ps2kbd_keymap[scancode].normal;
1098
 
1099
        // Detect the modifier keys.
1100
        for (i = 0; MWKEY_UNKNOWN != ps2kbd_modifier_map[i].key; i++) {
1101
            if (ps2kbd_current_key == ps2kbd_modifier_map[i].key) {
1102
                // capslock etc. behave differently. Toggle the current
1103
                // status on the keyup event, ignore key down (because
1104
                // of hardware autorepeat).
1105
                if (ps2kbd_modifier_map[i].toggle) {
1106
                    if (!ps2kbd_current_keydown) {
1107
                        ps2kbd_current_modifiers ^= ps2kbd_modifier_map[i].modifier;
1108
                    }
1109
                } else if (ps2kbd_current_keydown) {
1110
                    ps2kbd_current_modifiers |= ps2kbd_modifier_map[i].modifier;
1111
                } else {
1112
                    ps2kbd_current_modifiers &= ~ps2kbd_modifier_map[i].modifier;
1113
                }
1114
                break;
1115
            }
1116
        }
1117
 
1118
        // Cope with some of the modifiers.
1119
        if (0 != (ps2kbd_current_modifiers & (MWKMOD_LCTRL | MWKMOD_RCTRL))) {
1120
            // Control key. a-z and A-Z go to ctrl-A - ctrl-Z, i.e. 1 to 26
1121
            // Other characters in the range 64 to 96, e.g. [ and ], also
1122
            // get translated. This includes the A-Z range.
1123
            if ((64 <= ps2kbd_current_key) && (ps2kbd_current_key < 96)) {
1124
                ps2kbd_current_key -= 64;
1125
            } else if (('a' <= ps2kbd_current_key) && (ps2kbd_current_key <= 'z')) {
1126
                ps2kbd_current_key -= 96;
1127
            }
1128
        } else if (ps2kbd_current_modifiers & (MWKMOD_LSHIFT | MWKMOD_RSHIFT)) {
1129
            // Pick up the shift entry from the keymap
1130
            ps2kbd_current_key = ps2kbd_keymap[scancode].shifted;
1131
        }
1132
 
1133
        if (ps2kbd_current_modifiers & MWKMOD_CAPS) {
1134
            // Capslock only affects a-z and A-z
1135
            if ( ('a' <= ps2kbd_current_key) && (ps2kbd_current_key <= 'z')) {
1136
                ps2kbd_current_key = (ps2kbd_current_key -'a') + 'A';
1137
            } else if (('A' <= ps2kbd_current_key) && (ps2kbd_current_key <= 'Z')) {
1138
                ps2kbd_current_key = (ps2kbd_current_key -'A') + 'a';
1139
            }
1140
        }
1141
 
1142
        // If we have found a real key, the loop will exit.
1143
        // Otherwise try again.
1144
    }
1145
}
1146
 
1147
static int
1148
PS2Kbd_Open(KBDDEVICE* pkbd)
1149
{
1150
    unsigned char buf[1];
1151
    ps2_initialize();
1152
    buf[0] = KC_KBDC_ENABLE;
1153
    ps2_send_command_wait(KC_CONTROL_NULL, buf, 1, 0);
1154
}
1155
 
1156
static void
1157
PS2Kbd_Close(void)
1158
{
1159
    unsigned char buf[1];
1160
    buf[0] = KC_KBDC_STANDARD_DISABLE;
1161
    ps2_send_command_wait(KC_CONTROL_NULL, buf, 1, 0);
1162
}
1163
 
1164
static void
1165
PS2Kbd_GetModifierInfo(MWKEYMOD* modifiers, MWKEYMOD* curmodifiers)
1166
{
1167
    if (NULL != modifiers) {
1168
        *modifiers = MWKMOD_LSHIFT | MWKMOD_RSHIFT | MWKMOD_LCTRL | MWKMOD_RCTRL |
1169
            MWKMOD_LALT | MWKMOD_RALT | MWKMOD_LMETA | MWKMOD_RMETA |
1170
            MWKMOD_NUM | MWKMOD_CAPS | MWKMOD_ALTGR | MWKMOD_SCR;
1171
    }
1172
    if (NULL != curmodifiers) {
1173
        *modifiers = ps2kbd_current_modifiers;
1174
    }
1175
}
1176
 
1177
// Note: it is assumed that there are no concurrent calls to
1178
// the poll and read functions.
1179
static int
1180
PS2Kbd_Poll(void)
1181
{
1182
    if (MWKEY_UNKNOWN == ps2kbd_current_key) {
1183
        ps2kbd_process_scancodes();
1184
    }
1185
    return MWKEY_UNKNOWN != ps2kbd_current_key;
1186
}
1187
 
1188
// Return -1 on error, 0 for no data, 1 for a keypress, 2 for a keyrelease.
1189
static int
1190
PS2Kbd_Read(MWKEY* buf, MWKEYMOD* modifiers, MWSCANCODE* scancode)
1191
{
1192
    if (MWKEY_UNKNOWN == ps2kbd_current_key) {
1193
        ps2kbd_process_scancodes();
1194
        if (MWKEY_UNKNOWN == ps2kbd_current_key) {
1195
            return 0;
1196
        }
1197
    }
1198
 
1199
    if (NULL != buf) {
1200
        *buf = ps2kbd_current_key;
1201
    }
1202
    if (NULL != modifiers) {
1203
        *modifiers = ps2kbd_current_modifiers;
1204
    }
1205
    if (NULL != scancode) {
1206
        *scancode = ps2kbd_current_scancode;
1207
    }
1208
    ps2kbd_current_key = MWKEY_UNKNOWN;
1209
    return ps2kbd_current_keydown ? 1 : 2;
1210
}
1211
 
1212
KBDDEVICE kbddev = {
1213
    PS2Kbd_Open,
1214
    PS2Kbd_Close,
1215
    PS2Kbd_GetModifierInfo,
1216
    PS2Kbd_Read,
1217
    PS2Kbd_Poll
1218
};
1219
 
1220
#if 0
1221
// ----------------------------------------------------------------------------
1222
// This code can be used for testing the mouse and keyboard without all
1223
// of microwindows present (although the microwindows headers must still be
1224
// visible).
1225
 
1226
#include <stdio.h>
1227
#include <ctype.h>
1228
int
1229
main(int argc, char** argv)
1230
{
1231
    PS2Kbd_Open(&kbddev);
1232
    PS2Mouse_Open(&mousedev);
1233
    for ( ; ; ) {
1234
        while (PS2Mouse_Poll()) {
1235
            MWCOORD dx, dy, dz;
1236
            int     buttons;
1237
            PS2Mouse_Read(&dx, &dy, &dz, &buttons);
1238
            printf("Mouse movement: dx %d, dy %d, dz %d, buttons 0x%02x\n", dx, dy, dz, buttons);
1239
        }
1240
        while (PS2Kbd_Poll()) {
1241
            MWKEY       key;
1242
            MWKEYMOD    modifiers;
1243
            MWSCANCODE  scancode;
1244
            int         which;
1245
            which = PS2Kbd_Read(&key, &modifiers, &scancode);
1246
            printf("Keyboard event: %s, key %c (%d) (0x%02x), modifiers 0x%02x, scancode %d (0x%02x)\n",
1247
                   (1 == which) ? "press" : "release", isprint(key) ? key : '?', key, key, modifiers, scancode, scancode);
1248
        }
1249
    }
1250
}
1251
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.