xref: /haiku/src/add-ons/kernel/bus_managers/ps2/ps2_keyboard.cpp (revision 7a74a5df454197933bc6e80a542102362ee98703)
1 /*
2  * Copyright 2004-2010 Haiku, Inc.
3  * Distributed under the terms of the MIT License.
4  *
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>
9  */
10 
11 
12 /*! PS/2 keyboard device driver */
13 
14 
15 #include <string.h>
16 
17 #include <new>
18 
19 #include <debug.h>
20 #include <debugger_keymaps.h>
21 #include <lock.h>
22 #include <util/AutoLock.h>
23 
24 #include "ATKeymap.h"
25 #include "ps2_service.h"
26 #include "keyboard_mouse_driver.h"
27 #include "packet_buffer.h"
28 
29 
30 #define KEY_BUFFER_SIZE 100
31 	// we will buffer 100 key strokes before we start dropping them
32 
33 enum {
34 	LED_SCROLL 	= 1,
35 	LED_NUM 	= 2,
36 	LED_CAPS	= 4
37 };
38 
39 enum {
40 	EXTENDED_KEY	= 0xe0,
41 
42 	LEFT_ALT_KEY	= 0x38,
43 	RIGHT_ALT_KEY	= 0xb8,
44 	SYS_REQ_KEY		= 0x54
45 };
46 
47 
48 struct keyboard_cookie {
49 	bool is_reader;
50 	bool is_debugger;
51 };
52 
53 
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;
61 
62 static int32 sKeyboardRepeatRate;
63 static bigtime_t sKeyboardRepeatDelay;
64 static uint8 sKeyboardIds[2];
65 
66 
67 static status_t
68 set_leds(led_info *ledInfo)
69 {
70 	uint8 leds = 0;
71 
72 	TRACE("ps2: set keyboard LEDs\n");
73 
74 	if (ledInfo->scroll_lock)
75 		leds |= LED_SCROLL;
76 	if (ledInfo->num_lock)
77 		leds |= LED_NUM;
78 	if (ledInfo->caps_lock)
79 		leds |= LED_CAPS;
80 
81 	return ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB],
82 		PS2_CMD_KEYBOARD_SET_LEDS, &leds, 1, NULL, 0);
83 }
84 
85 
86 static status_t
87 set_typematic(int32 rate, bigtime_t delay)
88 {
89 	uint8 value;
90 
91 	TRACE("ps2: set_typematic rate %ld, delay %Ld\n", rate, delay);
92 
93 	// input server and keyboard preferences *seem* to use a range of 20-300
94 	if (rate < 20)
95 		rate = 20;
96 	if (rate > 300)
97 		rate = 300;
98 
99 	// map this into range 0-31
100 	rate = ((rate - 20) * 31) / (300 - 20);
101 
102 	// keyboard uses 0 == fast, 31 == slow
103 	value = 31 - rate;
104 
105 	if (delay >= 875000)
106 		value |= 3 << 5;
107 	else if (delay >= 625000)
108 		value |= 2 << 5;
109 	else if (delay >= 375000)
110 		value |= 1 << 5;
111 	else
112 		value |= 0 << 5;
113 
114 	return ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB],
115 		PS2_CMD_KEYBOARD_SET_TYPEMATIC, &value, 1, NULL, 0);
116 }
117 
118 
119 static int32
120 keyboard_handle_int(ps2_dev *dev)
121 {
122 	enum emergency_keys {
123 		EMERGENCY_LEFT_ALT	= 0x01,
124 		EMERGENCY_RIGHT_ALT	= 0x02,
125 		EMERGENCY_SYS_REQ	= 0x04,
126 	};
127 	static int emergencyKeyStatus = 0;
128 	raw_key_info keyInfo;
129 	uint8 scancode = dev->history[0].data;
130 
131 	if (atomic_get(&sKeyboardOpenCount) == 0)
132 		return B_HANDLED_INTERRUPT;
133 
134 	// TODO: Handle braindead "pause" key special case
135 
136 	if (scancode == EXTENDED_KEY) {
137 		sIsExtended = true;
138 //		TRACE("Extended key\n");
139 		return B_HANDLED_INTERRUPT;
140 	}
141 
142 //	TRACE("scancode: %x\n", scancode);
143 
144 	if ((scancode & 0x80) != 0) {
145 		keyInfo.is_keydown = false;
146 		scancode &= 0x7f;
147 	} else
148 		keyInfo.is_keydown = true;
149 
150 	if (sIsExtended) {
151 		scancode |= 0x80;
152 		sIsExtended = false;
153 	}
154 
155 	// Handle emergency keys
156 	if (scancode == LEFT_ALT_KEY || scancode == RIGHT_ALT_KEY) {
157 		// left or right alt-key pressed
158 		if (keyInfo.is_keydown) {
159 			emergencyKeyStatus |= scancode == LEFT_ALT_KEY
160 				? EMERGENCY_LEFT_ALT : EMERGENCY_RIGHT_ALT;
161 		} else {
162 			emergencyKeyStatus &= ~(scancode == LEFT_ALT_KEY
163 				? EMERGENCY_LEFT_ALT : EMERGENCY_RIGHT_ALT);
164 		}
165 	} else if (scancode == SYS_REQ_KEY) {
166 		if (keyInfo.is_keydown)
167 			emergencyKeyStatus |= EMERGENCY_SYS_REQ;
168 		else
169 			emergencyKeyStatus &= EMERGENCY_SYS_REQ;
170 	} else if (emergencyKeyStatus > EMERGENCY_SYS_REQ
171 		&& debug_emergency_key_pressed(kUnshiftedKeymap[scancode])) {
172 		static const int kKeys[] = {LEFT_ALT_KEY, RIGHT_ALT_KEY, SYS_REQ_KEY};
173 
174 		// we probably have lost some keys, so reset our key states
175 		emergencyKeyStatus = 0;
176 
177 		// send key ups for alt-sysreq
178 		keyInfo.timestamp = system_time();
179 		keyInfo.is_keydown = false;
180 		for (size_t i = 0; i < sizeof(kKeys) / sizeof(kKeys[0]); i++) {
181 			keyInfo.keycode = kATKeycodeMap[kKeys[i] - 1];
182 			if (packet_buffer_write(sKeyBuffer, (uint8 *)&keyInfo,
183 					sizeof(keyInfo)) != 0)
184 				release_sem_etc(sKeyboardSem, 1, B_DO_NOT_RESCHEDULE);
185 		}
186 
187 		return B_HANDLED_INTERRUPT;
188 	}
189 
190 	keyInfo.timestamp = dev->history[0].time;
191 	keyInfo.keycode = kATKeycodeMap[scancode - 1];
192 
193 	if (packet_buffer_write(sKeyBuffer, (uint8 *)&keyInfo,
194 			sizeof(keyInfo)) == 0) {
195 		// If there is no space left in the buffer, we drop this key stroke. We
196 		// avoid dropping old key strokes, to not destroy what already was
197 		// typed.
198 		return B_HANDLED_INTERRUPT;
199 	}
200 
201 	release_sem_etc(sKeyboardSem, 1, B_DO_NOT_RESCHEDULE);
202 
203 	return B_INVOKE_SCHEDULER;
204 }
205 
206 
207 static status_t
208 read_keyboard_packet(raw_key_info *packet, bool isDebugger)
209 {
210 	status_t status;
211 
212 	TRACE("ps2: read_keyboard_packet: enter\n");
213 
214 	while (true) {
215 		status = acquire_sem_etc(sKeyboardSem, 1, B_CAN_INTERRUPT, 0);
216 		if (status != B_OK)
217 			return status;
218 
219 		if (!ps2_device[PS2_DEVICE_KEYB].active) {
220 			TRACE("ps2: read_keyboard_packet, Error device no longer active\n");
221 			return B_ERROR;
222 		}
223 
224 		if (isDebugger || !sHasDebugReader)
225 			break;
226 
227 		// Give the debugger a chance to read this packet
228 		release_sem(sKeyboardSem);
229 		snooze(100000);
230 	}
231 
232 	if (packet_buffer_read(sKeyBuffer, (uint8 *)packet, sizeof(*packet)) == 0) {
233 		TRACE("ps2: read_keyboard_packet, Error reading packet: %s\n",
234 			strerror(status));
235 		return B_ERROR;
236 	}
237 
238 	TRACE("ps2: read_keyboard_packet: keycode: %" B_PRIx32 ", keydown: %s\n",
239 		packet->keycode, packet->is_keydown ? "true" : "false");
240 
241 	return B_OK;
242 }
243 
244 
245 static void
246 ps2_keyboard_disconnect(ps2_dev *dev)
247 {
248 	// the keyboard might not be opened at this point
249 	INFO("ps2: ps2_keyboard_disconnect %s\n", dev->name);
250 	if (atomic_get(&sKeyboardOpenCount) != 0)
251 		release_sem(sKeyboardSem);
252 }
253 
254 
255 //	#pragma mark -
256 
257 
258 status_t
259 probe_keyboard(void)
260 {
261 	uint8 data;
262 	status_t status;
263 
264 //  This test doesn't work relyable on some notebooks (it reports 0x03)
265 //	status = ps2_command(PS2_CTRL_KEYBOARD_TEST, NULL, 0, &data, 1);
266 //	if (status != B_OK || data != 0x00) {
267 //		INFO("ps2: keyboard test failed, status 0x%08lx, data 0x%02x\n", status, data);
268 //		return B_ERROR;
269 //	}
270 
271 	status = ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], PS2_CMD_RESET, NULL,
272 		0, &data, 1);
273 	if (status != B_OK || data != 0xaa) {
274 		INFO("ps2: keyboard reset failed, status 0x%08lx, data 0x%02x\n",
275 			status, data);
276 		return B_ERROR;
277 	}
278 
279 	// default settings after keyboard reset: delay = 0x01 (500 ms),
280 	// rate = 0x0b (10.9 chr/sec)
281 	sKeyboardRepeatRate = ((31 - 0x0b) * 280) / 31 + 20;
282 	sKeyboardRepeatDelay = 500000;
283 
284 //	status = ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], PS2_ENABLE_KEYBOARD, NULL, 0, NULL, 0);
285 
286 //  On my notebook, the keyboard controller does NACK the echo command.
287 //	status = ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], PS2_CMD_ECHO, NULL, 0, &data, 1);
288 //	if (status != B_OK || data != 0xee) {
289 //		INFO("ps2: keyboard echo test failed, status 0x%08lx, data 0x%02x\n", status, data);
290 //		return B_ERROR;
291 //	}
292 
293 // Some controllers set the disble keyboard command bit to "on" after resetting
294 // the keyboard device. Read #7973 #6313 for more details.
295 // So check the command byte now and re-enable the keyboard if it is the case.
296 	uint8 cmdbyte = 0;
297 	status = ps2_command(PS2_CTRL_READ_CMD, NULL, 0, &cmdbyte, 1);
298 
299 	if (status != B_OK) {
300 		INFO("ps2: cannot read CMD byte on kbd probe:0x%#08lx\n", status);
301 	} else
302 	if ((cmdbyte & PS2_BITS_KEYBOARD_DISABLED) == PS2_BITS_KEYBOARD_DISABLED) {
303 		cmdbyte &= ~PS2_BITS_KEYBOARD_DISABLED;
304 		status = ps2_command(PS2_CTRL_WRITE_CMD, &cmdbyte, 1, NULL, 0);
305 		if (status != B_OK) {
306 			INFO("ps2: cannot write 0x%02x to CMD byte on kbd probe:0x%08lx\n",
307 					cmdbyte, status);
308 		}
309 	}
310 
311 	status = ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB],
312 			PS2_CMD_GET_DEVICE_ID, NULL, 0, sKeyboardIds, sizeof(sKeyboardIds));
313 
314 	if (status != B_OK) {
315 		INFO("ps2: cannot read keyboard device id:0x%#08lx\n", status);
316 	}
317 
318 	return B_OK;
319 }
320 
321 
322 //	#pragma mark -
323 
324 
325 static status_t
326 keyboard_open(const char *name, uint32 flags, void **_cookie)
327 {
328 	TRACE("ps2: keyboard_open %s\n", name);
329 
330 	keyboard_cookie* cookie = new(std::nothrow) keyboard_cookie();
331 	if (cookie == NULL)
332 		return B_NO_MEMORY;
333 
334 	cookie->is_reader = false;
335 	cookie->is_debugger = false;
336 
337 	MutexLocker locker(sInitializeLock);
338 
339 	if (atomic_get(&sKeyboardOpenCount) == 0) {
340 		status_t status = probe_keyboard();
341 		if (status != B_OK) {
342 			INFO("ps2: keyboard probing failed\n");
343 			ps2_service_notify_device_removed(&ps2_device[PS2_DEVICE_KEYB]);
344 			delete cookie;
345 			return status;
346 		}
347 
348 		INFO("ps2: keyboard found\n");
349 
350 		sKeyboardSem = create_sem(0, "keyboard_sem");
351 		if (sKeyboardSem < 0) {
352 			delete cookie;
353 			return sKeyboardSem;
354 		}
355 
356 		sKeyBuffer
357 			= create_packet_buffer(KEY_BUFFER_SIZE * sizeof(raw_key_info));
358 		if (sKeyBuffer == NULL) {
359 			delete_sem(sKeyboardSem);
360 			delete cookie;
361 			return B_NO_MEMORY;
362 		}
363 
364 		ps2_device[PS2_DEVICE_KEYB].disconnect = &ps2_keyboard_disconnect;
365 		ps2_device[PS2_DEVICE_KEYB].handle_int = &keyboard_handle_int;
366 
367 		atomic_or(&ps2_device[PS2_DEVICE_KEYB].flags, PS2_FLAG_ENABLED);
368 	}
369 
370 	atomic_add(&sKeyboardOpenCount, 1);
371 	*_cookie = cookie;
372 
373 	TRACE("ps2: keyboard_open %s success\n", name);
374 	return B_OK;
375 }
376 
377 
378 static status_t
379 keyboard_close(void *_cookie)
380 {
381 	keyboard_cookie *cookie = (keyboard_cookie *)_cookie;
382 
383 	TRACE("ps2: keyboard_close enter\n");
384 
385 	if (atomic_add(&sKeyboardOpenCount, -1) == 1) {
386 		delete_packet_buffer(sKeyBuffer);
387 		delete_sem(sKeyboardSem);
388 
389 		atomic_and(&ps2_device[PS2_DEVICE_KEYB].flags, ~PS2_FLAG_ENABLED);
390 
391 		sKeyboardIds[0] = sKeyboardIds[1] = 0;
392 	}
393 
394 	if (cookie->is_reader)
395 		sHasKeyboardReader = false;
396 	if (cookie->is_debugger)
397 		sHasDebugReader = false;
398 
399 	TRACE("ps2: keyboard_close done\n");
400 	return B_OK;
401 }
402 
403 
404 static status_t
405 keyboard_freecookie(void *cookie)
406 {
407 	delete (keyboard_cookie*)cookie;
408 	return B_OK;
409 }
410 
411 
412 static status_t
413 keyboard_read(void *cookie, off_t pos, void *buffer, size_t *_length)
414 {
415 	TRACE("ps2: keyboard read\n");
416 	*_length = 0;
417 	return B_NOT_ALLOWED;
418 }
419 
420 
421 static status_t
422 keyboard_write(void *cookie, off_t pos, const void *buffer,  size_t *_length)
423 {
424 	TRACE("ps2: keyboard write\n");
425 	*_length = 0;
426 	return B_NOT_ALLOWED;
427 }
428 
429 
430 static status_t
431 keyboard_ioctl(void *_cookie, uint32 op, void *buffer, size_t length)
432 {
433 	keyboard_cookie *cookie = (keyboard_cookie *)_cookie;
434 
435 	switch (op) {
436 		case KB_READ:
437 		{
438 			if (!sHasKeyboardReader && !cookie->is_debugger) {
439 				cookie->is_reader = true;
440 				sHasKeyboardReader = true;
441 			} else if (!cookie->is_debugger && !cookie->is_reader)
442 				return B_BUSY;
443 
444 			raw_key_info packet;
445 			status_t status = read_keyboard_packet(&packet,
446 				cookie->is_debugger);
447 			TRACE("ps2: ioctl KB_READ: %s\n", strerror(status));
448 			if (status != B_OK)
449 				return status;
450 
451 			return user_memcpy(buffer, &packet, sizeof(packet));
452 		}
453 
454 		case KB_SET_LEDS:
455 		{
456 			led_info info;
457 			TRACE("ps2: ioctl KB_SET_LEDS\n");
458 			if (user_memcpy(&info, buffer, sizeof(led_info)) < B_OK)
459 				return B_BAD_ADDRESS;
460 			return set_leds(&info);
461 		}
462 
463 		case KB_SET_KEY_REPEATING:
464 		{
465 			TRACE("ps2: ioctl KB_SET_KEY_REPEATING\n");
466 			// 0xFA (Set All Keys Typematic/Make/Break) - Keyboard responds
467 			// with "ack" (0xFA).
468 			return ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], 0xfa, NULL, 0,
469 				NULL, 0);
470 		}
471 
472 		case KB_SET_KEY_NONREPEATING:
473 		{
474 			TRACE("ps2: ioctl KB_SET_KEY_NONREPEATING\n");
475 			// 0xF8 (Set All Keys Make/Break) - Keyboard responds with "ack"
476 			// (0xFA).
477 			return ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], 0xf8, NULL, 0,
478 				NULL, 0);
479 		}
480 
481 		case KB_SET_KEY_REPEAT_RATE:
482 		{
483 			int32 key_repeat_rate;
484 			TRACE("ps2: ioctl KB_SET_KEY_REPEAT_RATE\n");
485 			if (user_memcpy(&key_repeat_rate, buffer, sizeof(key_repeat_rate))
486 					!= B_OK)
487 				return B_BAD_ADDRESS;
488 			if (set_typematic(key_repeat_rate, sKeyboardRepeatDelay) != B_OK)
489 				return B_ERROR;
490 			sKeyboardRepeatRate = key_repeat_rate;
491 			return B_OK;
492 		}
493 
494 		case KB_GET_KEY_REPEAT_RATE:
495 		{
496 			TRACE("ps2: ioctl KB_GET_KEY_REPEAT_RATE\n");
497 			return user_memcpy(buffer, &sKeyboardRepeatRate,
498 				sizeof(sKeyboardRepeatRate));
499 		}
500 
501 		case KB_SET_KEY_REPEAT_DELAY:
502 		{
503 			bigtime_t key_repeat_delay;
504 			TRACE("ps2: ioctl KB_SET_KEY_REPEAT_DELAY\n");
505 			if (user_memcpy(&key_repeat_delay, buffer, sizeof(key_repeat_delay))
506 					!= B_OK)
507 				return B_BAD_ADDRESS;
508 			if (set_typematic(sKeyboardRepeatRate, key_repeat_delay) != B_OK)
509 				return B_ERROR;
510 			sKeyboardRepeatDelay = key_repeat_delay;
511 			return B_OK;
512 
513 		}
514 
515 		case KB_GET_KEY_REPEAT_DELAY:
516 		{
517 			TRACE("ps2: ioctl KB_GET_KEY_REPEAT_DELAY\n");
518 			return user_memcpy(buffer, &sKeyboardRepeatDelay,
519 				sizeof(sKeyboardRepeatDelay));
520 		}
521 
522 		case KB_GET_KEYBOARD_ID:
523 		{
524 			TRACE("ps2: ioctl KB_GET_KEYBOARD_ID\n");
525 			uint16 keyboardId = sKeyboardIds[1] << 8 | sKeyboardIds[0];
526 			return user_memcpy(buffer, &keyboardId, sizeof(keyboardId));
527 		}
528 
529 		case KB_SET_CONTROL_ALT_DEL_TIMEOUT:
530 		case KB_CANCEL_CONTROL_ALT_DEL:
531 		case KB_DELAY_CONTROL_ALT_DEL:
532 			INFO("ps2: ioctl 0x%lx not implemented yet, returning B_OK\n", op);
533 			return B_OK;
534 
535 		case KB_SET_DEBUG_READER:
536 			if (sHasDebugReader)
537 				return B_BUSY;
538 
539 			cookie->is_debugger = true;
540 			sHasDebugReader = true;
541 			return B_OK;
542 
543 		default:
544 			INFO("ps2: invalid ioctl 0x%lx\n", op);
545 			return B_DEV_INVALID_IOCTL;
546 	}
547 }
548 
549 
550 device_hooks gKeyboardDeviceHooks = {
551 	keyboard_open,
552 	keyboard_close,
553 	keyboard_freecookie,
554 	keyboard_ioctl,
555 	keyboard_read,
556 	keyboard_write,
557 };
558