xref: /haiku/src/add-ons/kernel/bus_managers/ps2/ps2_keyboard.cpp (revision f73f5d4c42a01ece688cbb57b5d332cc0f68b2c6)
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 %" B_PRId32 ", delay %" B_PRId64 "\n",
92 		rate, delay);
93 
94 	// input server and keyboard preferences *seem* to use a range of 20-300
95 	if (rate < 20)
96 		rate = 20;
97 	if (rate > 300)
98 		rate = 300;
99 
100 	// map this into range 0-31
101 	rate = ((rate - 20) * 31) / (300 - 20);
102 
103 	// keyboard uses 0 == fast, 31 == slow
104 	value = 31 - rate;
105 
106 	if (delay >= 875000)
107 		value |= 3 << 5;
108 	else if (delay >= 625000)
109 		value |= 2 << 5;
110 	else if (delay >= 375000)
111 		value |= 1 << 5;
112 	else
113 		value |= 0 << 5;
114 
115 	return ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB],
116 		PS2_CMD_KEYBOARD_SET_TYPEMATIC, &value, 1, NULL, 0);
117 }
118 
119 
120 static int32
121 keyboard_handle_int(ps2_dev *dev)
122 {
123 	enum emergency_keys {
124 		EMERGENCY_LEFT_ALT	= 0x01,
125 		EMERGENCY_RIGHT_ALT	= 0x02,
126 		EMERGENCY_SYS_REQ	= 0x04,
127 	};
128 	static int emergencyKeyStatus = 0;
129 	raw_key_info keyInfo;
130 	uint8 scancode = dev->history[0].data;
131 
132 	if (atomic_get(&sKeyboardOpenCount) == 0)
133 		return B_HANDLED_INTERRUPT;
134 
135 	// TODO: Handle braindead "pause" key special case
136 
137 	if (scancode == EXTENDED_KEY) {
138 		sIsExtended = true;
139 //		TRACE("Extended key\n");
140 		return B_HANDLED_INTERRUPT;
141 	}
142 
143 //	TRACE("scancode: %x\n", scancode);
144 
145 	if ((scancode & 0x80) != 0) {
146 		keyInfo.is_keydown = false;
147 		scancode &= 0x7f;
148 	} else
149 		keyInfo.is_keydown = true;
150 
151 	if (sIsExtended) {
152 		scancode |= 0x80;
153 		sIsExtended = false;
154 	}
155 
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;
162 		} else {
163 			emergencyKeyStatus &= ~(scancode == LEFT_ALT_KEY
164 				? EMERGENCY_LEFT_ALT : EMERGENCY_RIGHT_ALT);
165 		}
166 	} else if (scancode == SYS_REQ_KEY) {
167 		if (keyInfo.is_keydown)
168 			emergencyKeyStatus |= EMERGENCY_SYS_REQ;
169 		else
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};
174 
175 		// we probably have lost some keys, so reset our key states
176 		emergencyKeyStatus = 0;
177 
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);
186 		}
187 
188 		return B_HANDLED_INTERRUPT;
189 	}
190 
191 	keyInfo.timestamp = dev->history[0].time;
192 	keyInfo.keycode = kATKeycodeMap[scancode - 1];
193 
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
198 		// typed.
199 		return B_HANDLED_INTERRUPT;
200 	}
201 
202 	release_sem_etc(sKeyboardSem, 1, B_DO_NOT_RESCHEDULE);
203 
204 	return B_INVOKE_SCHEDULER;
205 }
206 
207 
208 static status_t
209 read_keyboard_packet(raw_key_info *packet, bool isDebugger)
210 {
211 	status_t status;
212 
213 	TRACE("ps2: read_keyboard_packet: enter\n");
214 
215 	while (true) {
216 		status = acquire_sem_etc(sKeyboardSem, 1, B_CAN_INTERRUPT, 0);
217 		if (status != B_OK)
218 			return status;
219 
220 		if (!ps2_device[PS2_DEVICE_KEYB].active) {
221 			TRACE("ps2: read_keyboard_packet, Error device no longer active\n");
222 			return B_ERROR;
223 		}
224 
225 		if (isDebugger || !sHasDebugReader)
226 			break;
227 
228 		// Give the debugger a chance to read this packet
229 		release_sem(sKeyboardSem);
230 		snooze(100000);
231 	}
232 
233 	if (packet_buffer_read(sKeyBuffer, (uint8 *)packet, sizeof(*packet)) == 0) {
234 		TRACE("ps2: read_keyboard_packet, Error reading packet: %s\n",
235 			strerror(status));
236 		return B_ERROR;
237 	}
238 
239 	TRACE("ps2: read_keyboard_packet: keycode: %" B_PRIx32 ", keydown: %s\n",
240 		packet->keycode, packet->is_keydown ? "true" : "false");
241 
242 	return B_OK;
243 }
244 
245 
246 static void
247 ps2_keyboard_disconnect(ps2_dev *dev)
248 {
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);
253 }
254 
255 
256 //	#pragma mark -
257 
258 
259 status_t
260 probe_keyboard(void)
261 {
262 	uint8 data;
263 	status_t status;
264 
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);
269 //		return B_ERROR;
270 //	}
271 
272 	status = ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], PS2_CMD_RESET, NULL,
273 		0, &data, 1);
274 	if (status != B_OK || data != 0xaa) {
275 		INFO("ps2: keyboard reset failed, status 0x%08" B_PRIx32 ", data 0x%02x"
276 			"\n", status, data);
277 		return B_ERROR;
278 	}
279 
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;
284 
285 //	status = ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], PS2_ENABLE_KEYBOARD, NULL, 0, NULL, 0);
286 
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);
291 //		return B_ERROR;
292 //	}
293 
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.
297 	uint8 cmdbyte = 0;
298 	status = ps2_command(PS2_CTRL_READ_CMD, NULL, 0, &cmdbyte, 1);
299 
300 	if (status != B_OK) {
301 		INFO("ps2: cannot read CMD byte on kbd probe:%#08" B_PRIx32 "\n",
302 			status);
303 	} else
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);
310 		}
311 	}
312 
313 	status = ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB],
314 			PS2_CMD_GET_DEVICE_ID, NULL, 0, sKeyboardIds, sizeof(sKeyboardIds));
315 
316 	if (status != B_OK) {
317 		INFO("ps2: cannot read keyboard device id:%#08" B_PRIx32 "\n", status);
318 	}
319 
320 	return B_OK;
321 }
322 
323 
324 //	#pragma mark -
325 
326 
327 static status_t
328 keyboard_open(const char *name, uint32 flags, void **_cookie)
329 {
330 	TRACE("ps2: keyboard_open %s\n", name);
331 
332 	keyboard_cookie* cookie = new(std::nothrow) keyboard_cookie();
333 	if (cookie == NULL)
334 		return B_NO_MEMORY;
335 
336 	cookie->is_reader = false;
337 	cookie->is_debugger = false;
338 
339 	MutexLocker locker(sInitializeLock);
340 
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]);
346 			delete cookie;
347 			return status;
348 		}
349 
350 		INFO("ps2: keyboard found\n");
351 
352 		sKeyboardSem = create_sem(0, "keyboard_sem");
353 		if (sKeyboardSem < 0) {
354 			delete cookie;
355 			return sKeyboardSem;
356 		}
357 
358 		sKeyBuffer
359 			= create_packet_buffer(KEY_BUFFER_SIZE * sizeof(raw_key_info));
360 		if (sKeyBuffer == NULL) {
361 			delete_sem(sKeyboardSem);
362 			delete cookie;
363 			return B_NO_MEMORY;
364 		}
365 
366 		ps2_device[PS2_DEVICE_KEYB].disconnect = &ps2_keyboard_disconnect;
367 		ps2_device[PS2_DEVICE_KEYB].handle_int = &keyboard_handle_int;
368 
369 		atomic_or(&ps2_device[PS2_DEVICE_KEYB].flags, PS2_FLAG_ENABLED);
370 	}
371 
372 	atomic_add(&sKeyboardOpenCount, 1);
373 	*_cookie = cookie;
374 
375 	TRACE("ps2: keyboard_open %s success\n", name);
376 	return B_OK;
377 }
378 
379 
380 static status_t
381 keyboard_close(void *_cookie)
382 {
383 	keyboard_cookie *cookie = (keyboard_cookie *)_cookie;
384 
385 	TRACE("ps2: keyboard_close enter\n");
386 
387 	if (atomic_add(&sKeyboardOpenCount, -1) == 1) {
388 		delete_packet_buffer(sKeyBuffer);
389 		delete_sem(sKeyboardSem);
390 
391 		atomic_and(&ps2_device[PS2_DEVICE_KEYB].flags, ~PS2_FLAG_ENABLED);
392 
393 		sKeyboardIds[0] = sKeyboardIds[1] = 0;
394 	}
395 
396 	if (cookie->is_reader)
397 		sHasKeyboardReader = false;
398 	if (cookie->is_debugger)
399 		sHasDebugReader = false;
400 
401 	TRACE("ps2: keyboard_close done\n");
402 	return B_OK;
403 }
404 
405 
406 static status_t
407 keyboard_freecookie(void *cookie)
408 {
409 	delete (keyboard_cookie*)cookie;
410 	return B_OK;
411 }
412 
413 
414 static status_t
415 keyboard_read(void *cookie, off_t pos, void *buffer, size_t *_length)
416 {
417 	TRACE("ps2: keyboard read\n");
418 	*_length = 0;
419 	return B_NOT_ALLOWED;
420 }
421 
422 
423 static status_t
424 keyboard_write(void *cookie, off_t pos, const void *buffer,  size_t *_length)
425 {
426 	TRACE("ps2: keyboard write\n");
427 	*_length = 0;
428 	return B_NOT_ALLOWED;
429 }
430 
431 
432 static status_t
433 keyboard_ioctl(void *_cookie, uint32 op, void *buffer, size_t length)
434 {
435 	keyboard_cookie *cookie = (keyboard_cookie *)_cookie;
436 
437 	switch (op) {
438 		case KB_READ:
439 		{
440 			if (!sHasKeyboardReader && !cookie->is_debugger) {
441 				cookie->is_reader = true;
442 				sHasKeyboardReader = true;
443 			} else if (!cookie->is_debugger && !cookie->is_reader)
444 				return B_BUSY;
445 
446 			raw_key_info packet;
447 			status_t status = read_keyboard_packet(&packet,
448 				cookie->is_debugger);
449 			TRACE("ps2: ioctl KB_READ: %s\n", strerror(status));
450 			if (status != B_OK)
451 				return status;
452 
453 			return user_memcpy(buffer, &packet, sizeof(packet));
454 		}
455 
456 		case KB_SET_LEDS:
457 		{
458 			led_info info;
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);
463 		}
464 
465 		case KB_SET_KEY_REPEATING:
466 		{
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,
471 				NULL, 0);
472 		}
473 
474 		case KB_SET_KEY_NONREPEATING:
475 		{
476 			TRACE("ps2: ioctl KB_SET_KEY_NONREPEATING\n");
477 			// 0xF8 (Set All Keys Make/Break) - Keyboard responds with "ack"
478 			// (0xFA).
479 			return ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], 0xf8, NULL, 0,
480 				NULL, 0);
481 		}
482 
483 		case KB_SET_KEY_REPEAT_RATE:
484 		{
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))
488 					!= B_OK)
489 				return B_BAD_ADDRESS;
490 			if (set_typematic(key_repeat_rate, sKeyboardRepeatDelay) != B_OK)
491 				return B_ERROR;
492 			sKeyboardRepeatRate = key_repeat_rate;
493 			return B_OK;
494 		}
495 
496 		case KB_GET_KEY_REPEAT_RATE:
497 		{
498 			TRACE("ps2: ioctl KB_GET_KEY_REPEAT_RATE\n");
499 			return user_memcpy(buffer, &sKeyboardRepeatRate,
500 				sizeof(sKeyboardRepeatRate));
501 		}
502 
503 		case KB_SET_KEY_REPEAT_DELAY:
504 		{
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))
508 					!= B_OK)
509 				return B_BAD_ADDRESS;
510 			if (set_typematic(sKeyboardRepeatRate, key_repeat_delay) != B_OK)
511 				return B_ERROR;
512 			sKeyboardRepeatDelay = key_repeat_delay;
513 			return B_OK;
514 
515 		}
516 
517 		case KB_GET_KEY_REPEAT_DELAY:
518 		{
519 			TRACE("ps2: ioctl KB_GET_KEY_REPEAT_DELAY\n");
520 			return user_memcpy(buffer, &sKeyboardRepeatDelay,
521 				sizeof(sKeyboardRepeatDelay));
522 		}
523 
524 		case KB_GET_KEYBOARD_ID:
525 		{
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));
529 		}
530 
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 "
535 				"B_OK\n", op);
536 			return B_OK;
537 
538 		case KB_SET_DEBUG_READER:
539 			if (sHasDebugReader)
540 				return B_BUSY;
541 
542 			cookie->is_debugger = true;
543 			sHasDebugReader = true;
544 			return B_OK;
545 
546 		default:
547 			INFO("ps2: invalid ioctl 0x%" B_PRIx32 "\n", op);
548 			return B_DEV_INVALID_IOCTL;
549 	}
550 }
551 
552 
553 device_hooks gKeyboardDeviceHooks = {
554 	keyboard_open,
555 	keyboard_close,
556 	keyboard_freecookie,
557 	keyboard_ioctl,
558 	keyboard_read,
559 	keyboard_write,
560 };
561