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