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