Changeset e69f10b in mainline for uspace/drv/usbhid/kbddev.c
- Timestamp:
- 2011-03-10T19:07:11Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- a8def7d
- Parents:
- 7351dc3 (diff), 45dd8bf (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/usbhid/kbddev.c
r7351dc3 re69f10b 37 37 #include <errno.h> 38 38 #include <str_error.h> 39 #include <fibril.h>40 39 #include <stdio.h> 41 40 … … 43 42 #include <ipc/kbd.h> 44 43 #include <async.h> 44 #include <fibril.h> 45 #include <fibril_synch.h> 45 46 46 47 #include <usb/usb.h> … … 56 57 #include "layout.h" 57 58 #include "conv.h" 58 59 /*----------------------------------------------------------------------------*/ 60 59 #include "kbdrepeat.h" 60 61 /*----------------------------------------------------------------------------*/ 62 /** Default modifiers when the keyboard is initialized. */ 61 63 static const unsigned DEFAULT_ACTIVE_MODS = KM_NUM_LOCK; 64 65 /** Boot protocol report size (key part). */ 62 66 static const size_t BOOTP_REPORT_SIZE = 6; 67 68 /** Boot protocol total report size. */ 63 69 static const size_t BOOTP_BUFFER_SIZE = 8; 70 71 /** Boot protocol output report size. */ 64 72 static const size_t BOOTP_BUFFER_OUT_SIZE = 1; 73 74 /** Boot protocol error key code. */ 65 75 static const uint8_t BOOTP_ERROR_ROLLOVER = 1; 76 77 /** Default idle rate for keyboards. */ 66 78 static const uint8_t IDLE_RATE = 0; 79 80 /** Delay before a pressed key starts auto-repeating. */ 81 static const unsigned int DEFAULT_DELAY_BEFORE_FIRST_REPEAT = 500 * 1000; 82 83 /** Delay between two repeats of a pressed key when auto-repeating. */ 84 static const unsigned int DEFAULT_REPEAT_DELAY = 50 * 1000; 67 85 68 86 /** Keyboard polling endpoint description for boot protocol class. */ … … 82 100 #define NUM_LAYOUTS 3 83 101 102 /** Keyboard layout map. */ 84 103 static layout_op_t *layout[NUM_LAYOUTS] = { 85 104 &us_qwerty_op, … … 93 112 /* Modifier constants */ 94 113 /*----------------------------------------------------------------------------*/ 95 114 /** Mapping of USB modifier key codes to generic modifier key codes. */ 96 115 static const keycode_t usbhid_modifiers_keycodes[USB_HID_MOD_COUNT] = { 97 116 KC_LCTRL, /* USB_HID_MOD_LCTRL */ … … 114 133 }; 115 134 116 /** Default handler for IPC methods not handled by DDF. 117 * 118 * @param dev Device handling the call. 135 /** 136 * Default handler for IPC methods not handled by DDF. 137 * 138 * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it 139 * assumes the caller is the console and thus it stores IPC phone to it for 140 * later use by the driver to notify about key events. 141 * 142 * @param fun Device function handling the call. 119 143 * @param icallid Call id. 120 144 * @param icall Call data. … … 147 171 /* Key processing functions */ 148 172 /*----------------------------------------------------------------------------*/ 149 173 /** 174 * Handles turning of LED lights on and off. 175 * 176 * In case of USB keyboards, the LEDs are handled in the driver, not in the 177 * device. When there should be a change (lock key was pressed), the driver 178 * uses a Set_Report request sent to the device to set the state of the LEDs. 179 * 180 * This functions sets the LED lights according to current settings of modifiers 181 * kept in the keyboard device structure. 182 * 183 * @param kbd_dev Keyboard device structure. 184 */ 150 185 static void usbhid_kbd_set_led(usbhid_kbd_t *kbd_dev) 151 186 { … … 189 224 190 225 /*----------------------------------------------------------------------------*/ 191 192 static void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, 193 unsigned int key) 226 /** 227 * Processes key events. 228 * 229 * @note This function was copied from AT keyboard driver and modified to suit 230 * USB keyboard. 231 * 232 * @note Lock keys are not sent to the console, as they are completely handled 233 * in the driver. It may, however, be required later that the driver 234 * sends also these keys to application (otherwise it cannot use those 235 * keys at all). 236 * 237 * @param kbd_dev Keyboard device structure. 238 * @param type Type of the event (press / release). Recognized values: 239 * KEY_PRESS, KEY_RELEASE 240 * @param key Key code of the key according to HID Usage Tables. 241 */ 242 void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key) 194 243 { 195 244 console_event_t ev; 196 245 unsigned mod_mask; 197 246 198 // TODO: replace by our own parsing?? or are the key codes identical?? 247 /* 248 * These parts are copy-pasted from the AT keyboard driver. 249 * 250 * They definitely require some refactoring, but will keep it for later 251 * when the console and keyboard system is changed in HelenOS. 252 */ 199 253 switch (key) { 200 254 case KC_LCTRL: mod_mask = KM_LCTRL; break; … … 228 282 * up the lock state. 229 283 */ 284 unsigned int locks_old = kbd_dev->lock_keys; 285 230 286 kbd_dev->mods = 231 287 kbd_dev->mods ^ (mod_mask & ~kbd_dev->lock_keys); … … 233 289 234 290 /* Update keyboard lock indicator lights. */ 235 usbhid_kbd_set_led(kbd_dev); 291 if (kbd_dev->lock_keys != locks_old) { 292 usbhid_kbd_set_led(kbd_dev); 293 } 236 294 } else { 237 295 kbd_dev->lock_keys = kbd_dev->lock_keys & ~mod_mask; … … 280 338 281 339 /*----------------------------------------------------------------------------*/ 282 340 /** 341 * Checks if modifiers were pressed or released and generates key events. 342 * 343 * @param kbd_dev Keyboard device structure. 344 * @param modifiers Bitmap of modifiers. 345 * 346 * @sa usbhid_kbd_push_ev() 347 */ 283 348 static void usbhid_kbd_check_modifier_changes(usbhid_kbd_t *kbd_dev, 284 349 uint8_t modifiers) … … 316 381 317 382 /*----------------------------------------------------------------------------*/ 318 383 /** 384 * Checks if some keys were pressed or released and generates key events. 385 * 386 * An event is created only when key is pressed or released. Besides handling 387 * the events (usbhid_kbd_push_ev()), the auto-repeat fibril is notified about 388 * key presses and releases (see usbhid_kbd_repeat_start() and 389 * usbhid_kbd_repeat_stop()). 390 * 391 * @param kbd_dev Keyboard device structure. 392 * @param key_codes Parsed keyboard report - codes of currently pressed keys 393 * according to HID Usage Tables. 394 * @param count Number of key codes in report (size of the report). 395 * 396 * @sa usbhid_kbd_push_ev(), usbhid_kbd_repeat_start(), usbhid_kbd_repeat_stop() 397 */ 319 398 static void usbhid_kbd_check_key_changes(usbhid_kbd_t *kbd_dev, 320 const uint8_t *key_codes )399 const uint8_t *key_codes, size_t count) 321 400 { 322 401 unsigned int key; … … 328 407 i = 0; 329 408 // all fields should report Error Rollover 330 while (i < kbd_dev->keycode_count &&409 while (i < count && 331 410 key_codes[i] == BOOTP_ERROR_ROLLOVER) { 332 411 ++i; 333 412 } 334 if (i == kbd_dev->keycode_count) {413 if (i == count) { 335 414 usb_log_debug("Phantom state occured.\n"); 336 415 // phantom state, do nothing … … 338 417 } 339 418 340 // TODO: quite dummy right now, think of better implementation 419 /* TODO: quite dummy right now, think of better implementation */ 420 assert(count == kbd_dev->key_count); 341 421 342 422 /* 343 423 * 1) Key releases 344 424 */ 345 for (j = 0; j < kbd_dev->keycode_count; ++j) {425 for (j = 0; j < count; ++j) { 346 426 // try to find the old key in the new key list 347 427 i = 0; 348 while (i < kbd_dev->key code_count349 && key_codes[i] != kbd_dev->key codes[j]) {428 while (i < kbd_dev->key_count 429 && key_codes[i] != kbd_dev->keys[j]) { 350 430 ++i; 351 431 } 352 432 353 if (i == kbd_dev->keycode_count) {433 if (i == count) { 354 434 // not found, i.e. the key was released 355 key = usbhid_parse_scancode(kbd_dev->keycodes[j]); 435 key = usbhid_parse_scancode(kbd_dev->keys[j]); 436 usbhid_kbd_repeat_stop(kbd_dev, key); 356 437 usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, key); 357 438 usb_log_debug2("Key released: %d\n", key); … … 364 445 * 1) Key presses 365 446 */ 366 for (i = 0; i < kbd_dev->key code_count; ++i) {447 for (i = 0; i < kbd_dev->key_count; ++i) { 367 448 // try to find the new key in the old key list 368 449 j = 0; 369 while (j < kbd_dev->keycode_count 370 && kbd_dev->keycodes[j] != key_codes[i]) { 450 while (j < count && kbd_dev->keys[j] != key_codes[i]) { 371 451 ++j; 372 452 } 373 453 374 if (j == kbd_dev->keycode_count) {454 if (j == count) { 375 455 // not found, i.e. new key pressed 376 456 key = usbhid_parse_scancode(key_codes[i]); … … 378 458 key_codes[i]); 379 459 usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, key); 380 } else { 460 usbhid_kbd_repeat_start(kbd_dev, key); 461 } else {size_t 381 462 // found, nothing happens 382 463 } 383 464 } 384 // // report all currently pressed keys 385 // for (i = 0; i < kbd_dev->keycode_count; ++i) { 386 // if (key_codes[i] != 0) { 387 // key = usbhid_parse_scancode(key_codes[i]); 388 // usb_log_debug2("Key pressed: %d (keycode: %d)\n", key, 389 // key_codes[i]); 390 // usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, key); 391 // } 392 // } 393 394 memcpy(kbd_dev->keycodes, key_codes, kbd_dev->keycode_count); 465 466 memcpy(kbd_dev->keys, key_codes, count); 395 467 396 468 usb_log_debug("New stored keycodes: %s\n", 397 usb_debug_str_buffer(kbd_dev->key codes, kbd_dev->keycode_count, 0));469 usb_debug_str_buffer(kbd_dev->keys, kbd_dev->key_count, 0)); 398 470 } 399 471 … … 401 473 /* Callbacks for parser */ 402 474 /*----------------------------------------------------------------------------*/ 403 475 /** 476 * Callback function for the HID report parser. 477 * 478 * This function is called by the HID report parser with the parsed report. 479 * The parsed report is used to check if any events occured (key was pressed or 480 * released, modifier was pressed or released). 481 * 482 * @param key_codes Parsed keyboard report - codes of currently pressed keys 483 * according to HID Usage Tables. 484 * @param count Number of key codes in report (size of the report). 485 * @param modifiers Bitmap of modifiers (Ctrl, Alt, Shift, GUI). 486 * @param arg User-specified argument. Expects pointer to the keyboard device 487 * structure representing the keyboard. 488 * 489 * @sa usbhid_kbd_check_key_changes(), usbhid_kbd_check_modifier_changes() 490 */ 404 491 static void usbhid_kbd_process_keycodes(const uint8_t *key_codes, size_t count, 405 492 uint8_t modifiers, void *arg) … … 415 502 416 503 usb_log_debug("Got keys from parser: %s\n", 417 usb_debug_str_buffer(key_codes, kbd_dev->key code_count, 0));418 419 if (count != kbd_dev->key code_count) {504 usb_debug_str_buffer(key_codes, kbd_dev->key_count, 0)); 505 506 if (count != kbd_dev->key_count) { 420 507 usb_log_warning("Number of received keycodes (%d) differs from" 421 " expected number (%d).\n", count, kbd_dev->key code_count);508 " expected number (%d).\n", count, kbd_dev->key_count); 422 509 return; 423 510 } 424 511 425 512 usbhid_kbd_check_modifier_changes(kbd_dev, modifiers); 426 usbhid_kbd_check_key_changes(kbd_dev, key_codes );513 usbhid_kbd_check_key_changes(kbd_dev, key_codes, count); 427 514 } 428 515 … … 430 517 /* General kbd functions */ 431 518 /*----------------------------------------------------------------------------*/ 432 519 /** 520 * Processes data received from the device in form of report. 521 * 522 * This function uses the HID report parser to translate the data received from 523 * the device into generic USB HID key codes and into generic modifiers bitmap. 524 * The parser then calls the given callback (usbhid_kbd_process_keycodes()). 525 * 526 * @note Currently, only the boot protocol is supported. 527 * 528 * @param kbd_dev Keyboard device structure (must be initialized). 529 * @param buffer Data from the keyboard (i.e. the report). 530 * @param actual_size Size of the data from keyboard (report size) in bytes. 531 * 532 * @sa usbhid_kbd_process_keycodes(), usb_hid_boot_keyboard_input_report(). 533 */ 433 534 static void usbhid_kbd_process_data(usbhid_kbd_t *kbd_dev, 434 535 uint8_t *buffer, size_t actual_size) … … 457 558 /* HID/KBD structure manipulation */ 458 559 /*----------------------------------------------------------------------------*/ 459 560 /** 561 * Creates a new USB/HID keyboard structure. 562 * 563 * The structure returned by this function is not initialized. Use 564 * usbhid_kbd_init() to initialize it prior to polling. 565 * 566 * @return New uninitialized structure for representing a USB/HID keyboard or 567 * NULL if not successful (memory error). 568 */ 460 569 static usbhid_kbd_t *usbhid_kbd_new(void) 461 570 { … … 483 592 484 593 /*----------------------------------------------------------------------------*/ 485 594 /** 595 * Properly destroys the USB/HID keyboard structure. 596 * 597 * @param kbd_dev Pointer to the structure to be destroyed. 598 */ 486 599 static void usbhid_kbd_free(usbhid_kbd_t **kbd_dev) 487 600 { … … 498 611 } 499 612 613 if ((*kbd_dev)->repeat_mtx != NULL) { 614 /* TODO: replace by some check and wait */ 615 assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx)); 616 free((*kbd_dev)->repeat_mtx); 617 } 618 500 619 usb_hid_free_report_parser((*kbd_dev)->parser); 501 620 … … 505 624 506 625 /*----------------------------------------------------------------------------*/ 507 626 /** 627 * Initialization of the USB/HID keyboard structure. 628 * 629 * This functions initializes required structures from the device's descriptors. 630 * 631 * During initialization, the keyboard is switched into boot protocol, the idle 632 * rate is set to 0 (infinity), resulting in the keyboard only reporting event 633 * when a key is pressed or released. Finally, the LED lights are turned on 634 * according to the default setup of lock keys. 635 * 636 * @note By default, the keyboards is initialized with Num Lock turned on and 637 * other locks turned off. 638 * 639 * @param kbd_dev Keyboard device structure to be initialized. 640 * @param dev DDF device structure of the keyboard. 641 * 642 * @retval EOK if successful. 643 * @retval EINVAL if some parameter is not given. 644 * @return Other value inherited from function usbhid_dev_init(). 645 */ 508 646 static int usbhid_kbd_init(usbhid_kbd_t *kbd_dev, ddf_dev_t *dev) 509 647 { … … 540 678 541 679 // save the size of the report (boot protocol report by default) 542 kbd_dev->key code_count = BOOTP_REPORT_SIZE;543 kbd_dev->key codes = (uint8_t *)calloc(544 kbd_dev->key code_count, sizeof(uint8_t));545 546 if (kbd_dev->key codes == NULL) {680 kbd_dev->key_count = BOOTP_REPORT_SIZE; 681 kbd_dev->keys = (uint8_t *)calloc( 682 kbd_dev->key_count, sizeof(uint8_t)); 683 684 if (kbd_dev->keys == NULL) { 547 685 usb_log_fatal("No memory!\n"); 548 return rc;686 return ENOMEM; 549 687 } 550 688 … … 553 691 kbd_dev->lock_keys = 0; 554 692 693 kbd_dev->repeat.key_new = 0; 694 kbd_dev->repeat.key_repeated = 0; 695 kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT; 696 kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY; 697 698 kbd_dev->repeat_mtx = (fibril_mutex_t *)( 699 malloc(sizeof(fibril_mutex_t))); 700 if (kbd_dev->repeat_mtx == NULL) { 701 usb_log_fatal("No memory!\n"); 702 free(kbd_dev->keys); 703 return ENOMEM; 704 } 705 706 fibril_mutex_initialize(kbd_dev->repeat_mtx); 707 555 708 /* 556 709 * Set boot protocol. … … 575 728 /* HID/KBD polling */ 576 729 /*----------------------------------------------------------------------------*/ 577 730 /** 731 * Main keyboard polling function. 732 * 733 * This function uses the Interrupt In pipe of the keyboard to poll for events. 734 * The keyboard is initialized in a way that it reports only when a key is 735 * pressed or released, so there is no actual need for any sleeping between 736 * polls (see usbhid_kbd_try_add_device() or usbhid_kbd_init()). 737 * 738 * @param kbd_dev Initialized keyboard structure representing the device to 739 * poll. 740 * 741 * @sa usbhid_kbd_process_data() 742 */ 578 743 static void usbhid_kbd_poll(usbhid_kbd_t *kbd_dev) 579 744 { … … 598 763 usb_log_warning("Failed to start a session: %s.\n", 599 764 str_error(sess_rc)); 600 continue;765 break; 601 766 } 602 767 … … 610 775 usb_log_warning("Error polling the keyboard: %s.\n", 611 776 str_error(rc)); 612 continue;777 break; 613 778 } 614 779 … … 616 781 usb_log_warning("Error closing session: %s.\n", 617 782 str_error(sess_rc)); 618 continue;783 break; 619 784 } 620 785 … … 637 802 //async_usleep(kbd_dev->hid_dev->poll_interval); 638 803 } 639 640 // not reached 641 assert(0); 642 } 643 644 /*----------------------------------------------------------------------------*/ 645 804 } 805 806 /*----------------------------------------------------------------------------*/ 807 /** 808 * Function executed by the main driver fibril. 809 * 810 * Just starts polling the keyboard for events. 811 * 812 * @param arg Initialized keyboard device structure (of type usbhid_kbd_t) 813 * representing the device. 814 * 815 * @retval EOK if the fibril finished polling the device. 816 * @retval EINVAL if no device was given in the argument. 817 * 818 * @sa usbhid_kbd_poll() 819 * 820 * @todo Change return value - only case when the fibril finishes is in case 821 * of some error, so the error should probably be propagated from function 822 * usbhid_kbd_poll() to here and up. 823 */ 646 824 static int usbhid_kbd_fibril(void *arg) 647 825 { … … 665 843 /* API functions */ 666 844 /*----------------------------------------------------------------------------*/ 667 845 /** 846 * Function for adding a new device of type USB/HID/keyboard. 847 * 848 * This functions initializes required structures from the device's descriptors 849 * and starts new fibril for polling the keyboard for events and another one for 850 * handling auto-repeat of keys. 851 * 852 * During initialization, the keyboard is switched into boot protocol, the idle 853 * rate is set to 0 (infinity), resulting in the keyboard only reporting event 854 * when a key is pressed or released. Finally, the LED lights are turned on 855 * according to the default setup of lock keys. 856 * 857 * @note By default, the keyboards is initialized with Num Lock turned on and 858 * other locks turned off. 859 * @note Currently supports only boot-protocol keyboards. 860 * 861 * @param dev Device to add. 862 * 863 * @retval EOK if successful. 864 * @retval ENOMEM if there 865 * @return Other error code inherited from one of functions usbhid_kbd_init(), 866 * ddf_fun_bind() and ddf_fun_add_to_class(). 867 * 868 * @sa usbhid_kbd_fibril(), usbhid_kbd_repeat_fibril() 869 */ 668 870 int usbhid_kbd_try_add_device(ddf_dev_t *dev) 669 871 { … … 687 889 "structure.\n"); 688 890 ddf_fun_destroy(kbd_fun); 689 return E INVAL; // TODO: some other code??891 return ENOMEM; // TODO: some other code?? 690 892 } 691 893 … … 736 938 } 737 939 fibril_add_ready(fid); 940 941 /* 942 * Create new fibril for auto-repeat 943 */ 944 fid = fibril_create(usbhid_kbd_repeat_fibril, kbd_dev); 945 if (fid == 0) { 946 usb_log_error("Failed to start fibril for KBD auto-repeat"); 947 return ENOMEM; 948 } 949 fibril_add_ready(fid); 738 950 739 951 (void)keyboard_ops;
Note:
See TracChangeset
for help on using the changeset viewer.