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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [services/] [gfx/] [mw/] [v2_0/] [src/] [drivers/] [ps2kbdmou_ecos.c] - Blame information for rev 174

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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