2 * Copyright 2004-2010 Haiku, Inc.
3 * Distributed under the terms of the MIT License.
5 * Authors (in chronological order):
6 * Stefano Ceccherini (burton666@libero.it)
7 * Axel Dörfler, axeld@pinc-software.de
8 * Marcus Overhagen <marcus@overhagen.de>
12 /*! PS/2 keyboard device driver */
20 #include <debugger_keymaps.h>
22 #include <util/AutoLock.h>
25 #include "ps2_service.h"
26 #include "keyboard_mouse_driver.h"
27 #include "packet_buffer.h"
30 #define KEY_BUFFER_SIZE 100
31 // we will buffer 100 key strokes before we start dropping them
48 struct keyboard_cookie
{
54 static mutex sInitializeLock
= MUTEX_INITIALIZER("keyboard init");
55 static int32 sKeyboardOpenCount
= 0;
56 static bool sHasKeyboardReader
= false;
57 static bool sHasDebugReader
= false;
58 static sem_id sKeyboardSem
;
59 static struct packet_buffer
*sKeyBuffer
;
60 static bool sIsExtended
= false;
62 static int32 sKeyboardRepeatRate
;
63 static bigtime_t sKeyboardRepeatDelay
;
64 static uint8 sKeyboardIds
[2];
68 set_leds(led_info
*ledInfo
)
72 TRACE("ps2: set keyboard LEDs\n");
74 if (ledInfo
->scroll_lock
)
76 if (ledInfo
->num_lock
)
78 if (ledInfo
->caps_lock
)
81 return ps2_dev_command(&ps2_device
[PS2_DEVICE_KEYB
],
82 PS2_CMD_KEYBOARD_SET_LEDS
, &leds
, 1, NULL
, 0);
87 set_typematic(int32 rate
, bigtime_t delay
)
91 TRACE("ps2: set_typematic rate %" B_PRId32
", delay %" B_PRId64
"\n",
94 // input server and keyboard preferences *seem* to use a range of 20-300
100 // map this into range 0-31
101 rate
= ((rate
- 20) * 31) / (300 - 20);
103 // keyboard uses 0 == fast, 31 == slow
108 else if (delay
>= 625000)
110 else if (delay
>= 375000)
115 return ps2_dev_command(&ps2_device
[PS2_DEVICE_KEYB
],
116 PS2_CMD_SET_TYPEMATIC
, &value
, 1, NULL
, 0);
121 keyboard_handle_int(ps2_dev
*dev
)
123 enum emergency_keys
{
124 EMERGENCY_LEFT_ALT
= 0x01,
125 EMERGENCY_RIGHT_ALT
= 0x02,
126 EMERGENCY_SYS_REQ
= 0x04,
128 static int emergencyKeyStatus
= 0;
129 raw_key_info keyInfo
;
130 uint8 scancode
= dev
->history
[0].data
;
132 if (atomic_get(&sKeyboardOpenCount
) == 0)
133 return B_HANDLED_INTERRUPT
;
135 // TODO: Handle braindead "pause" key special case
137 if (scancode
== EXTENDED_KEY
) {
139 // TRACE("Extended key\n");
140 return B_HANDLED_INTERRUPT
;
143 // TRACE("scancode: %x\n", scancode);
145 if ((scancode
& 0x80) != 0) {
146 keyInfo
.is_keydown
= false;
149 keyInfo
.is_keydown
= true;
156 // Handle emergency keys
157 if (scancode
== LEFT_ALT_KEY
|| scancode
== RIGHT_ALT_KEY
) {
158 // left or right alt-key pressed
159 if (keyInfo
.is_keydown
) {
160 emergencyKeyStatus
|= scancode
== LEFT_ALT_KEY
161 ? EMERGENCY_LEFT_ALT
: EMERGENCY_RIGHT_ALT
;
163 emergencyKeyStatus
&= ~(scancode
== LEFT_ALT_KEY
164 ? EMERGENCY_LEFT_ALT
: EMERGENCY_RIGHT_ALT
);
166 } else if (scancode
== SYS_REQ_KEY
) {
167 if (keyInfo
.is_keydown
)
168 emergencyKeyStatus
|= EMERGENCY_SYS_REQ
;
170 emergencyKeyStatus
&= EMERGENCY_SYS_REQ
;
171 } else if (emergencyKeyStatus
> EMERGENCY_SYS_REQ
172 && debug_emergency_key_pressed(kUnshiftedKeymap
[scancode
])) {
173 static const int kKeys
[] = {LEFT_ALT_KEY
, RIGHT_ALT_KEY
, SYS_REQ_KEY
};
175 // we probably have lost some keys, so reset our key states
176 emergencyKeyStatus
= 0;
178 // send key ups for alt-sysreq
179 keyInfo
.timestamp
= system_time();
180 keyInfo
.is_keydown
= false;
181 for (size_t i
= 0; i
< sizeof(kKeys
) / sizeof(kKeys
[0]); i
++) {
182 keyInfo
.keycode
= kATKeycodeMap
[kKeys
[i
] - 1];
183 if (packet_buffer_write(sKeyBuffer
, (uint8
*)&keyInfo
,
184 sizeof(keyInfo
)) != 0)
185 release_sem_etc(sKeyboardSem
, 1, B_DO_NOT_RESCHEDULE
);
188 return B_HANDLED_INTERRUPT
;
191 keyInfo
.timestamp
= dev
->history
[0].time
;
192 keyInfo
.keycode
= kATKeycodeMap
[scancode
- 1];
194 if (packet_buffer_write(sKeyBuffer
, (uint8
*)&keyInfo
,
195 sizeof(keyInfo
)) == 0) {
196 // If there is no space left in the buffer, we drop this key stroke. We
197 // avoid dropping old key strokes, to not destroy what already was
199 return B_HANDLED_INTERRUPT
;
202 release_sem_etc(sKeyboardSem
, 1, B_DO_NOT_RESCHEDULE
);
204 return B_INVOKE_SCHEDULER
;
209 read_keyboard_packet(raw_key_info
*packet
, bool isDebugger
)
213 TRACE("ps2: read_keyboard_packet: enter\n");
216 status
= acquire_sem_etc(sKeyboardSem
, 1, B_CAN_INTERRUPT
, 0);
220 if (!ps2_device
[PS2_DEVICE_KEYB
].active
) {
221 TRACE("ps2: read_keyboard_packet, Error device no longer active\n");
225 if (isDebugger
|| !sHasDebugReader
)
228 // Give the debugger a chance to read this packet
229 release_sem(sKeyboardSem
);
233 if (packet_buffer_read(sKeyBuffer
, (uint8
*)packet
, sizeof(*packet
)) == 0) {
234 TRACE("ps2: read_keyboard_packet, Error reading packet: %s\n",
239 TRACE("ps2: read_keyboard_packet: keycode: %" B_PRIx32
", keydown: %s\n",
240 packet
->keycode
, packet
->is_keydown
? "true" : "false");
247 ps2_keyboard_disconnect(ps2_dev
*dev
)
249 // the keyboard might not be opened at this point
250 INFO("ps2: ps2_keyboard_disconnect %s\n", dev
->name
);
251 if (atomic_get(&sKeyboardOpenCount
) != 0)
252 release_sem(sKeyboardSem
);
265 // This test doesn't work relyable on some notebooks (it reports 0x03)
266 // status = ps2_command(PS2_CTRL_KEYBOARD_TEST, NULL, 0, &data, 1);
267 // if (status != B_OK || data != 0x00) {
268 // INFO("ps2: keyboard test failed, status 0x%08lx, data 0x%02x\n", status, data);
272 status
= ps2_dev_command(&ps2_device
[PS2_DEVICE_KEYB
], PS2_CMD_RESET
, NULL
,
274 if (status
!= B_OK
|| data
!= 0xaa) {
275 INFO("ps2: keyboard reset failed, status 0x%08" B_PRIx32
", data 0x%02x"
280 // default settings after keyboard reset: delay = 0x01 (500 ms),
281 // rate = 0x0b (10.9 chr/sec)
282 sKeyboardRepeatRate
= ((31 - 0x0b) * 280) / 31 + 20;
283 sKeyboardRepeatDelay
= 500000;
285 // status = ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], PS2_ENABLE_KEYBOARD, NULL, 0, NULL, 0);
287 // On my notebook, the keyboard controller does NACK the echo command.
288 // status = ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], PS2_CMD_ECHO, NULL, 0, &data, 1);
289 // if (status != B_OK || data != 0xee) {
290 // INFO("ps2: keyboard echo test failed, status 0x%08lx, data 0x%02x\n", status, data);
294 // Some controllers set the disble keyboard command bit to "on" after resetting
295 // the keyboard device. Read #7973 #6313 for more details.
296 // So check the command byte now and re-enable the keyboard if it is the case.
298 status
= ps2_command(PS2_CTRL_READ_CMD
, NULL
, 0, &cmdbyte
, 1);
300 if (status
!= B_OK
) {
301 INFO("ps2: cannot read CMD byte on kbd probe:%#08" B_PRIx32
"\n",
304 if ((cmdbyte
& PS2_BITS_KEYBOARD_DISABLED
) == PS2_BITS_KEYBOARD_DISABLED
) {
305 cmdbyte
&= ~PS2_BITS_KEYBOARD_DISABLED
;
306 status
= ps2_command(PS2_CTRL_WRITE_CMD
, &cmdbyte
, 1, NULL
, 0);
307 if (status
!= B_OK
) {
308 INFO("ps2: cannot write 0x%02x to CMD byte on kbd probe:%#08"
309 B_PRIx32
"\n", cmdbyte
, status
);
313 status
= ps2_dev_command(&ps2_device
[PS2_DEVICE_KEYB
],
314 PS2_CMD_GET_DEVICE_ID
, NULL
, 0, sKeyboardIds
, sizeof(sKeyboardIds
));
316 if (status
!= B_OK
) {
317 INFO("ps2: cannot read keyboard device id:%#08" B_PRIx32
"\n", status
);
328 keyboard_open(const char *name
, uint32 flags
, void **_cookie
)
330 TRACE("ps2: keyboard_open %s\n", name
);
332 keyboard_cookie
* cookie
= new(std::nothrow
) keyboard_cookie();
336 cookie
->is_reader
= false;
337 cookie
->is_debugger
= false;
339 MutexLocker
locker(sInitializeLock
);
341 if (atomic_get(&sKeyboardOpenCount
) == 0) {
342 status_t status
= probe_keyboard();
343 if (status
!= B_OK
) {
344 INFO("ps2: keyboard probing failed\n");
345 ps2_service_notify_device_removed(&ps2_device
[PS2_DEVICE_KEYB
]);
350 INFO("ps2: keyboard found\n");
352 sKeyboardSem
= create_sem(0, "keyboard_sem");
353 if (sKeyboardSem
< 0) {
359 = create_packet_buffer(KEY_BUFFER_SIZE
* sizeof(raw_key_info
));
360 if (sKeyBuffer
== NULL
) {
361 delete_sem(sKeyboardSem
);
366 ps2_device
[PS2_DEVICE_KEYB
].disconnect
= &ps2_keyboard_disconnect
;
367 ps2_device
[PS2_DEVICE_KEYB
].handle_int
= &keyboard_handle_int
;
369 atomic_or(&ps2_device
[PS2_DEVICE_KEYB
].flags
, PS2_FLAG_ENABLED
);
372 atomic_add(&sKeyboardOpenCount
, 1);
375 TRACE("ps2: keyboard_open %s success\n", name
);
381 keyboard_close(void *_cookie
)
383 keyboard_cookie
*cookie
= (keyboard_cookie
*)_cookie
;
385 TRACE("ps2: keyboard_close enter\n");
387 if (atomic_add(&sKeyboardOpenCount
, -1) == 1) {
388 delete_packet_buffer(sKeyBuffer
);
389 delete_sem(sKeyboardSem
);
391 atomic_and(&ps2_device
[PS2_DEVICE_KEYB
].flags
, ~PS2_FLAG_ENABLED
);
393 sKeyboardIds
[0] = sKeyboardIds
[1] = 0;
396 if (cookie
->is_reader
)
397 sHasKeyboardReader
= false;
398 if (cookie
->is_debugger
)
399 sHasDebugReader
= false;
401 TRACE("ps2: keyboard_close done\n");
407 keyboard_freecookie(void *cookie
)
409 delete (keyboard_cookie
*)cookie
;
415 keyboard_read(void *cookie
, off_t pos
, void *buffer
, size_t *_length
)
417 TRACE("ps2: keyboard read\n");
419 return B_NOT_ALLOWED
;
424 keyboard_write(void *cookie
, off_t pos
, const void *buffer
, size_t *_length
)
426 TRACE("ps2: keyboard write\n");
428 return B_NOT_ALLOWED
;
433 keyboard_ioctl(void *_cookie
, uint32 op
, void *buffer
, size_t length
)
435 keyboard_cookie
*cookie
= (keyboard_cookie
*)_cookie
;
440 if (!sHasKeyboardReader
&& !cookie
->is_debugger
) {
441 cookie
->is_reader
= true;
442 sHasKeyboardReader
= true;
443 } else if (!cookie
->is_debugger
&& !cookie
->is_reader
)
447 status_t status
= read_keyboard_packet(&packet
,
448 cookie
->is_debugger
);
449 TRACE("ps2: ioctl KB_READ: %s\n", strerror(status
));
453 return user_memcpy(buffer
, &packet
, sizeof(packet
));
459 TRACE("ps2: ioctl KB_SET_LEDS\n");
460 if (user_memcpy(&info
, buffer
, sizeof(led_info
)) < B_OK
)
461 return B_BAD_ADDRESS
;
462 return set_leds(&info
);
465 case KB_SET_KEY_REPEATING
:
467 TRACE("ps2: ioctl KB_SET_KEY_REPEATING\n");
468 // 0xFA (Set All Keys Typematic/Make/Break) - Keyboard responds
469 // with "ack" (0xFA).
470 return ps2_dev_command(&ps2_device
[PS2_DEVICE_KEYB
], 0xfa, NULL
, 0,
474 case KB_SET_KEY_NONREPEATING
:
476 TRACE("ps2: ioctl KB_SET_KEY_NONREPEATING\n");
477 // 0xF8 (Set All Keys Make/Break) - Keyboard responds with "ack"
479 return ps2_dev_command(&ps2_device
[PS2_DEVICE_KEYB
], 0xf8, NULL
, 0,
483 case KB_SET_KEY_REPEAT_RATE
:
485 int32 key_repeat_rate
;
486 TRACE("ps2: ioctl KB_SET_KEY_REPEAT_RATE\n");
487 if (user_memcpy(&key_repeat_rate
, buffer
, sizeof(key_repeat_rate
))
489 return B_BAD_ADDRESS
;
490 if (set_typematic(key_repeat_rate
, sKeyboardRepeatDelay
) != B_OK
)
492 sKeyboardRepeatRate
= key_repeat_rate
;
496 case KB_GET_KEY_REPEAT_RATE
:
498 TRACE("ps2: ioctl KB_GET_KEY_REPEAT_RATE\n");
499 return user_memcpy(buffer
, &sKeyboardRepeatRate
,
500 sizeof(sKeyboardRepeatRate
));
503 case KB_SET_KEY_REPEAT_DELAY
:
505 bigtime_t key_repeat_delay
;
506 TRACE("ps2: ioctl KB_SET_KEY_REPEAT_DELAY\n");
507 if (user_memcpy(&key_repeat_delay
, buffer
, sizeof(key_repeat_delay
))
509 return B_BAD_ADDRESS
;
510 if (set_typematic(sKeyboardRepeatRate
, key_repeat_delay
) != B_OK
)
512 sKeyboardRepeatDelay
= key_repeat_delay
;
517 case KB_GET_KEY_REPEAT_DELAY
:
519 TRACE("ps2: ioctl KB_GET_KEY_REPEAT_DELAY\n");
520 return user_memcpy(buffer
, &sKeyboardRepeatDelay
,
521 sizeof(sKeyboardRepeatDelay
));
524 case KB_GET_KEYBOARD_ID
:
526 TRACE("ps2: ioctl KB_GET_KEYBOARD_ID\n");
527 uint16 keyboardId
= sKeyboardIds
[1] << 8 | sKeyboardIds
[0];
528 return user_memcpy(buffer
, &keyboardId
, sizeof(keyboardId
));
531 case KB_SET_CONTROL_ALT_DEL_TIMEOUT
:
532 case KB_CANCEL_CONTROL_ALT_DEL
:
533 case KB_DELAY_CONTROL_ALT_DEL
:
534 INFO("ps2: ioctl 0x%" B_PRIx32
" not implemented yet, returning "
538 case KB_SET_DEBUG_READER
:
542 cookie
->is_debugger
= true;
543 sHasDebugReader
= true;
547 INFO("ps2: invalid ioctl 0x%" B_PRIx32
"\n", op
);
548 return B_DEV_INVALID_IOCTL
;
553 device_hooks gKeyboardDeviceHooks
= {