1 //=============================================================================
5 // eCos support for a PS/2 keyboard and mouse.
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.
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.
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
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.
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.
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.
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####
45 // Purpose: Implement basic keyboard and mouse support for microwindows
46 // only, interacting directly with the hardware.
48 //####DESCRIPTIONEND####
49 //=============================================================================
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>
61 # include <cyg/kernel/kapi.h>
64 // ----------------------------------------------------------------------------
65 // Configuration options. For now local to this file.
66 #define CYGDBG_DEVS_PS2KBDMOUSE_VERBOSE 1
68 #ifdef CYGDBG_DEVS_PS2KBDMOUSE_VERBOSE
69 # define DBG(format, args...) diag_printf(format, ## args)
71 # define DBG(format, args...)
74 // ----------------------------------------------------------------------------
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.
83 // Output means keyboard controller -> cpu.
84 // Input means cpu -> keyboard controller.
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...
90 // The following information was extracted from "The Indispensable
91 // PC Hardware Book" by Messmer, third edition, chapter 34.
93 #define KC_OUTPUT 0x060
94 #define KC_INPUT 0x060
95 #define KC_CONTROL 0x064
96 #define KC_STATUS 0x064
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)
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
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)
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)
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)
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
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
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
220 // Data back from the mouse. Some special characters.
221 #define KC_MOUSE_ACK 0x0FA
222 #define KC_MOUSE_RESEND 0x0FE
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.
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.
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
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
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;
253 static unsigned char ps2mou_buffer[PS2MOU_DATA_BUFSIZE];
254 static int ps2mou_buffer_index = 0;
256 // Sending commands. In theory there are a number of variations of
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
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.
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
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.
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;
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.
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
295 static int ps2mou_packet_size = 3;
297 ps2mou_synaptics_translate(void)
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
310 // Byte 0 holds the button flags.
311 if (0 != (ps2mou_buffer[0] & (0x01 << 0))) {
312 new_buttons = MWBUTTON_L;
314 if (0 != (ps2mou_buffer[0] & (0x01 << 1))) {
315 new_buttons |= MWBUTTON_R;
317 ps2mou_buttons = new_buttons;
319 dx = ps2mou_buffer[1];
320 if (0 != (ps2mou_buffer[0] & (0x001 << 4))) {
322 if (0 != (ps2mou_buffer[0] & (0x01 << 6))) {
328 } else if (0 != (ps2mou_buffer[0] & (0x01 << 6))) {
334 dy = ps2mou_buffer[2];
335 if (0 != (ps2mou_buffer[0] & (0x01 << 5))) {
337 if (0 != (ps2mou_buffer[0] & (0x01 << 7))) {
341 // -ve signed, bottom byte only
344 } else if (0 != (ps2mou_buffer[0] & (0x01 << 7))) {
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
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.
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
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.
387 ps2_isr(cyg_vector_t isr_vector, cyg_addrword_t isr_data)
392 CYG_UNUSED_PARAM(cyg_addrword_t, isr_data);
394 HAL_READ_UINT8(KC_STATUS, status);
395 while (status & KC_STATUS_OUTB) {
396 HAL_READ_UINT8(KC_OUTPUT, data);
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.
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.
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))) {
417 if (KC_MOUSE_ACK == data) {
418 // Is there another byte to be sent?
420 if (ps2_command_index < ps2_command_length) {
421 // Send the next byte for the current command
423 HAL_READ_UINT8(KC_STATUS, tmp);
424 } while (tmp & KC_STATUS_INPB);
425 HAL_WRITE_UINT8(KC_CONTROL, KC_CONTROL_WRITE_AUX);
427 HAL_READ_UINT8(KC_STATUS, tmp);
428 } while (tmp & KC_STATUS_INPB);
429 HAL_WRITE_UINT8(KC_INPUT, ps2_command[ps2_command_index]);
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;
437 ps2_command_mouse_waiting_for_ack = 0;
440 // A resend request for the current byte.
442 HAL_READ_UINT8(KC_STATUS, tmp);
443 } while (tmp & KC_STATUS_INPB);
444 HAL_WRITE_UINT8(KC_CONTROL, KC_CONTROL_WRITE_AUX);
446 HAL_READ_UINT8(KC_STATUS, tmp);
447 } while (tmp & KC_STATUS_INPB);
448 HAL_WRITE_UINT8(KC_INPUT, ps2_command[ps2_command_index]);
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
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.
466 if (ps2_command_index < ps2_command_length) {
469 HAL_READ_UINT8(KC_STATUS, tmp);
470 } while (tmp & KC_STATUS_INPB);
471 HAL_WRITE_UINT8(KC_INPUT, ps2_command[ps2_command_index]);
473 ps2_command_index = 0;
474 ps2_command_length = 0;
478 } else if ((KC_KBD_RESEND == data) && (NULL != ps2_command) && !ps2_command_mouse_waiting_for_ack) {
481 HAL_READ_UINT8(KC_STATUS, tmp);
482 } while (tmp & KC_STATUS_INPB);
483 HAL_WRITE_UINT8(KC_INPUT, ps2_command[ps2_command_index]);
485 if (((ps2kbd_scancode_buffer_head + 1) % PS2KBD_SCANCODE_BUFSIZE) == ps2kbd_scancode_buffer_tail) {
486 // Already full. The data has to be discarded.
488 ps2kbd_scancode_buffer[ps2kbd_scancode_buffer_head] = data;
489 ps2kbd_scancode_buffer_head = (ps2kbd_scancode_buffer_head + 1) % PS2KBD_SCANCODE_BUFSIZE;
494 // Just in case the keyboard controller is fast enough to send another byte,
496 HAL_READ_UINT8(KC_STATUS, status);
499 // The interrupt has been fully handled. For now there is no point
501 cyg_drv_interrupt_acknowledge(isr_vector);
502 return CYG_ISR_HANDLED;
505 // For now the DSR does nothing.
507 ps2_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
509 CYG_UNUSED_PARAM(cyg_vector_t, vector);
510 CYG_UNUSED_PARAM(cyg_ucount32, count);
511 CYG_UNUSED_PARAM(cyg_addrword_t, data);
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
520 ps2_send_command(int controller_command, unsigned char* command, int length, int mouse)
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");
528 ps2_command = command;
529 ps2_command_index = 0;
530 ps2_command_length = length;
531 ps2_command_mouse = 0;
534 if (KC_CONTROL_NULL != controller_command) {
536 HAL_READ_UINT8(KC_STATUS, status);
537 } while (status & KC_STATUS_INPB);
538 HAL_WRITE_UINT8(KC_CONTROL, controller_command);
544 HAL_READ_UINT8(KC_STATUS, status);
545 } while (status & KC_STATUS_INPB);
546 HAL_WRITE_UINT8(KC_CONTROL, KC_CONTROL_WRITE_AUX);
549 HAL_READ_UINT8(KC_STATUS, status);
550 } while (status & KC_STATUS_INPB);
551 HAL_WRITE_UINT8(KC_INPUT, command[0]);
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.
562 // ACKs are only generated when there is data to be sent, not for
563 // operations on the control register.
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.
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.
580 ps2_send_command_poll(int controller_command, unsigned char* command, int length, int mouse)
582 if ((NULL != command) && mouse) {
583 ps2_command_mouse_waiting_for_ack = 1;
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);
595 ps2_send_command_wait(int controller_command, unsigned char* command, int length, int mouse)
597 if ((NULL != command) && mouse) {
598 ps2_command_mouse_waiting_for_ack = 1;
600 ps2_send_command(controller_command, command, length, mouse);
601 if (NULL != command) {
602 for ( ; !ps2_command_ack; )
609 // ----------------------------------------------------------------------------
610 // Hardware initialization and the interrupt handling.
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;
620 unsigned char buf[2];
623 // Only perform initialization once, not for both kbd and mouse.
624 static int initialized = 0;
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);
637 // Install my own interrupt handler, overwriting anything that might
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);
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);
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);
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;
663 ps2_send_command_poll(KC_CONTROL_NULL, buf, 2, 0);
664 // The keyboard-specific initialization can now reenable the keyboard
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
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;
677 ps2_send_command_poll(KC_CONTROL_NULL, buf, 2, 1);
679 // WRITE_MODE does not appear to involve an ACK
680 ps2_send_command_poll(KC_CONTROL_WRITE_MODE, NULL, 0, 0);
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);
686 cyg_drv_interrupt_unmask_intunsafe(CYGNUM_HAL_INTERRUPT_KEYBOARD);
687 cyg_drv_interrupt_unmask_intunsafe(CYGNUM_HAL_INTERRUPT_IRQ12);
690 // ----------------------------------------------------------------------------
692 PS2Mouse_Open(MOUSEDEVICE* pmd)
694 unsigned char buf[1];
696 buf[0] = KC_MOUSEC_ENABLE;
697 ps2_send_command_wait(KC_CONTROL_NULL, buf, 1, 1);
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
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;
713 PS2Mouse_GetButtonInfo(void)
715 return MWBUTTON_L | MWBUTTON_R;
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...
721 PS2Mouse_GetDefaultAccel(int* pscale, int* pthresh)
723 if (NULL != pscale) {
726 if (NULL != pthresh) {
732 PS2Mouse_Read(MWCOORD* dx_arg, MWCOORD* dy_arg, MWCOORD* dz_arg, int* bp_arg)
740 if (ps2mou_changed) {
742 dy = 0 - ps2mou_dy; // microwindows directions are the opposite from the hardware
743 buttons = ps2mou_buttons;
749 cyg_drv_isr_unlock();
751 if (NULL != dx_arg) {
754 if (NULL != dy_arg) {
757 if (NULL != dz_arg) {
760 if (NULL != bp_arg) {
770 return 0 != ps2mou_changed;
773 MOUSEDEVICE mousedev = {
776 PS2Mouse_GetButtonInfo,
777 PS2Mouse_GetDefaultAccel,
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
788 // The current keyboard event, if any. This involves processing
789 // the scancodes held in the circular buffer and translating them
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;
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.
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.
805 // There is a complication with PC keyboards in that some keys
806 // generate multi-byte sequences, usually starting with 0xE0
808 typedef struct ps2kbd_keymap_entry {
811 } ps2kbd_keymap_entry;
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.
817 static const ps2kbd_keymap_entry ps2kbd_keymap[] = {
818 { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, // Scancode 0 unused
819 { MWKEY_ESCAPE, MWKEY_ESCAPE },
828 { '9', ')' }, // Scancode 10
832 { MWKEY_BACKSPACE, MWKEY_BACKSPACE },
833 { MWKEY_TAB, MWKEY_TAB },
834 { 'q', 'Q' }, // 0x10
846 { MWKEY_ENTER, MWKEY_ENTER },
847 { MWKEY_LCTRL, MWKEY_LCTRL },
850 { 'd', 'D' }, // 0x20
859 { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, // Japanese-only, top-left below escape
860 { MWKEY_LSHIFT, MWKEY_LSHIFT },
866 { 'b', 'B' }, // 0x30
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 },
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 },
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
966 #define PS2KBD_E0_MIN 0x47
967 static const MWKEY ps2kbd_e0_map[] = {
970 MWKEY_PAGEUP, // 0x49
978 MWKEY_PAGEDOWN, // 0x51
979 MWKEY_INSERT, // 0x52
980 MWKEY_DELETE, // 0x53
992 #define PS2KBD_E0_MAX 0x5D
994 // Modifier translations. All modifiers are supported by
995 // this table, even though the keyboard may not actually
997 typedef struct ps2kbd_modifier_entry {
1001 } ps2kbd_modifier_entry;
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 }
1020 ps2kbd_process_scancodes(void)
1022 static int e0_seen = 0;
1023 static MWKEY pending_up = MWKEY_UNKNOWN;
1024 static int pending_scancode = 0;
1025 static int discard = 0;
1029 CYG_PRECONDITION(MWKEY_UNKNOWN == ps2kbd_current_key, "There should be no pending key");
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;
1039 while (MWKEY_UNKNOWN == ps2kbd_current_key) {
1040 // The ISR will manipulate the scancode buffer directly, so
1041 // interrupts have to be disabled temporarily.
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;
1048 cyg_drv_isr_unlock();
1050 if (scancode == -1) {
1051 // No more data to be processed.
1055 // Are we in one of the special sequences, where bytes should be
1062 // A real scancode has been extracted. Are we in an E0 sequence?
1065 ps2kbd_current_keydown = (0 == (scancode & 0x0080));
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
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
1076 // Is this the start of an E0 sequence?
1077 if (0x00E0 == scancode) {
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;
1094 // Must be an ordinary key.
1095 ps2kbd_current_keydown = (0 == (scancode & 0x0080));
1097 ps2kbd_current_scancode = scancode;
1098 ps2kbd_current_key = ps2kbd_keymap[scancode].normal;
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;
1110 } else if (ps2kbd_current_keydown) {
1111 ps2kbd_current_modifiers |= ps2kbd_modifier_map[i].modifier;
1113 ps2kbd_current_modifiers &= ~ps2kbd_modifier_map[i].modifier;
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;
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;
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';
1143 // If we have found a real key, the loop will exit.
1144 // Otherwise try again.
1149 PS2Kbd_Open(KBDDEVICE* pkbd)
1151 unsigned char buf[1];
1153 buf[0] = KC_KBDC_ENABLE;
1154 ps2_send_command_wait(KC_CONTROL_NULL, buf, 1, 0);
1160 unsigned char buf[1];
1161 buf[0] = KC_KBDC_STANDARD_DISABLE;
1162 ps2_send_command_wait(KC_CONTROL_NULL, buf, 1, 0);
1166 PS2Kbd_GetModifierInfo(MWKEYMOD* modifiers, MWKEYMOD* curmodifiers)
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;
1173 if (NULL != curmodifiers) {
1174 *modifiers = ps2kbd_current_modifiers;
1178 // Note: it is assumed that there are no concurrent calls to
1179 // the poll and read functions.
1183 if (MWKEY_UNKNOWN == ps2kbd_current_key) {
1184 ps2kbd_process_scancodes();
1186 return MWKEY_UNKNOWN != ps2kbd_current_key;
1189 // Return -1 on error, 0 for no data, 1 for a keypress, 2 for a keyrelease.
1191 PS2Kbd_Read(MWKEY* buf, MWKEYMOD* modifiers, MWSCANCODE* scancode)
1193 if (MWKEY_UNKNOWN == ps2kbd_current_key) {
1194 ps2kbd_process_scancodes();
1195 if (MWKEY_UNKNOWN == ps2kbd_current_key) {
1201 *buf = ps2kbd_current_key;
1203 if (NULL != modifiers) {
1204 *modifiers = ps2kbd_current_modifiers;
1206 if (NULL != scancode) {
1207 *scancode = ps2kbd_current_scancode;
1209 ps2kbd_current_key = MWKEY_UNKNOWN;
1210 return ps2kbd_current_keydown ? 1 : 2;
1213 KBDDEVICE kbddev = {
1216 PS2Kbd_GetModifierInfo,
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
1230 main(int argc, char** argv)
1232 PS2Kbd_Open(&kbddev);
1233 PS2Mouse_Open(&mousedev);
1235 while (PS2Mouse_Poll()) {
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);
1241 while (PS2Kbd_Poll()) {
1244 MWSCANCODE scancode;
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);