Changeset 095b2017 in mainline for uspace/drv/usbkbd/kbddev.c
- Timestamp:
- 2011-03-25T17:13:02Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- b8d453ec, fa3de85
- Parents:
- da88eb82 (diff), da3dafc (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 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/usbkbd/kbddev.c
rda88eb82 r095b2017 46 46 47 47 #include <usb/usb.h> 48 #include <usb/dp.h> 49 #include <usb/request.h> 48 50 #include <usb/classes/hid.h> 49 51 #include <usb/pipes.h> … … 52 54 #include <usb/classes/classes.h> 53 55 #include <usb/classes/hidut.h> 56 #include <usb/classes/hidreq.h> 57 #include <usb/classes/hidreport.h> 58 59 #include <usb/devdrv.h> 54 60 55 61 #include "kbddev.h" 56 #include "hiddev.h" 57 #include "hidreq.h" 62 58 63 #include "layout.h" 59 64 #include "conv.h" … … 85 90 static const unsigned int DEFAULT_REPEAT_DELAY = 50 * 1000; 86 91 92 /*----------------------------------------------------------------------------*/ 93 87 94 /** Keyboard polling endpoint description for boot protocol class. */ 88 static usb_endpoint_description_t poll_endpoint_description = {95 static usb_endpoint_description_t boot_poll_endpoint_description = { 89 96 .transfer_type = USB_TRANSFER_INTERRUPT, 90 97 .direction = USB_DIRECTION_IN, … … 95 102 }; 96 103 97 typedef enum usbhid_kbd_flags { 98 USBHID_KBD_STATUS_UNINITIALIZED = 0, 99 USBHID_KBD_STATUS_INITIALIZED = 1, 100 USBHID_KBD_STATUS_TO_DESTROY = -1 101 } usbhid_kbd_flags; 104 /* Array of endpoints expected on the device, NULL terminated. */ 105 usb_endpoint_description_t 106 *usb_kbd_endpoints[USB_KBD_POLL_EP_COUNT + 1] = { 107 &boot_poll_endpoint_description, 108 NULL 109 }; 110 111 /*----------------------------------------------------------------------------*/ 112 113 enum { 114 BOOT_REPORT_DESCRIPTOR_SIZE = 63 115 }; 116 117 static const uint8_t BOOT_REPORT_DESCRIPTOR[BOOT_REPORT_DESCRIPTOR_SIZE] = { 118 0x05, 0x01, // Usage Page (Generic Desktop), 119 0x09, 0x06, // Usage (Keyboard), 120 0xA1, 0x01, // Collection (Application), 121 0x75, 0x01, // Report Size (1), 122 0x95, 0x08, // Report Count (8), 123 0x05, 0x07, // Usage Page (Key Codes); 124 0x19, 0xE0, // Usage Minimum (224), 125 0x29, 0xE7, // Usage Maximum (231), 126 0x15, 0x00, // Logical Minimum (0), 127 0x25, 0x01, // Logical Maximum (1), 128 0x81, 0x02, // Input (Data, Variable, Absolute), ; Modifier byte 129 0x95, 0x01, // Report Count (1), 130 0x75, 0x08, // Report Size (8), 131 0x81, 0x01, // Input (Constant), ; Reserved byte 132 0x95, 0x05, // Report Count (5), 133 0x75, 0x01, // Report Size (1), 134 0x05, 0x08, // Usage Page (Page# for LEDs), 135 0x19, 0x01, // Usage Minimum (1), 136 0x29, 0x05, // Usage Maxmimum (5), 137 0x91, 0x02, // Output (Data, Variable, Absolute), ; LED report 138 0x95, 0x01, // Report Count (1), 139 0x75, 0x03, // Report Size (3), 140 0x91, 0x01, // Output (Constant), ; LED report padding 141 0x95, 0x06, // Report Count (6), 142 0x75, 0x08, // Report Size (8), 143 0x15, 0x00, // Logical Minimum (0), 144 0x25, 0xff, // Logical Maximum (255), 145 0x05, 0x07, // Usage Page (Key Codes), 146 0x19, 0x00, // Usage Minimum (0), 147 0x29, 0xff, // Usage Maximum (255), 148 0x81, 0x00, // Input (Data, Array), ; Key arrays (6 bytes) 149 0xC0 // End Collection 150 151 }; 152 153 /*----------------------------------------------------------------------------*/ 154 155 typedef enum usb_kbd_flags { 156 USB_KBD_STATUS_UNINITIALIZED = 0, 157 USB_KBD_STATUS_INITIALIZED = 1, 158 USB_KBD_STATUS_TO_DESTROY = -1 159 } usb_kbd_flags; 102 160 103 161 /*----------------------------------------------------------------------------*/ … … 132 190 133 191 typedef enum usbhid_lock_code { 134 USB HID_LOCK_NUM = 0x53,135 USB HID_LOCK_CAPS = 0x39,136 USB HID_LOCK_SCROLL = 0x47,137 USB HID_LOCK_COUNT = 3192 USB_KBD_LOCK_NUM = 0x53, 193 USB_KBD_LOCK_CAPS = 0x39, 194 USB_KBD_LOCK_SCROLL = 0x47, 195 USB_KBD_LOCK_COUNT = 3 138 196 } usbhid_lock_code; 139 197 140 static const usbhid_lock_code usbhid_lock_codes[USB HID_LOCK_COUNT] = {141 USB HID_LOCK_NUM,142 USB HID_LOCK_CAPS,143 USB HID_LOCK_SCROLL198 static const usbhid_lock_code usbhid_lock_codes[USB_KBD_LOCK_COUNT] = { 199 USB_KBD_LOCK_NUM, 200 USB_KBD_LOCK_CAPS, 201 USB_KBD_LOCK_SCROLL 144 202 }; 145 203 … … 149 207 150 208 static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *); 151 staticddf_dev_ops_t keyboard_ops = {209 ddf_dev_ops_t keyboard_ops = { 152 210 .default_handler = default_connection_handler 153 211 }; … … 169 227 sysarg_t method = IPC_GET_IMETHOD(*icall); 170 228 171 usb hid_kbd_t *kbd_dev = (usbhid_kbd_t *)fun->driver_data;229 usb_kbd_t *kbd_dev = (usb_kbd_t *)fun->driver_data; 172 230 assert(kbd_dev != NULL); 173 231 … … 203 261 * @param kbd_dev Keyboard device structure. 204 262 */ 205 static void usb hid_kbd_set_led(usbhid_kbd_t *kbd_dev)263 static void usb_kbd_set_led(usb_kbd_t *kbd_dev) 206 264 { 207 265 uint8_t buffer[BOOTP_BUFFER_OUT_SIZE]; … … 237 295 usb_debug_str_buffer(buffer, BOOTP_BUFFER_OUT_SIZE, 0)); 238 296 239 assert(kbd_dev->hid_dev != NULL); 240 assert(kbd_dev->hid_dev->initialized == USBHID_KBD_STATUS_INITIALIZED); 241 usbhid_req_set_report(kbd_dev->hid_dev, USB_HID_REPORT_TYPE_OUTPUT, 297 assert(kbd_dev->usb_dev != NULL); 298 299 usbhid_req_set_report(&kbd_dev->usb_dev->ctrl_pipe, 300 kbd_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT, 242 301 buffer, BOOTP_BUFFER_OUT_SIZE); 243 302 } … … 260 319 * @param key Key code of the key according to HID Usage Tables. 261 320 */ 262 void usb hid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key)321 void usb_kbd_push_ev(usb_kbd_t *kbd_dev, int type, unsigned int key) 263 322 { 264 323 console_event_t ev; … … 310 369 /* Update keyboard lock indicator lights. */ 311 370 if (kbd_dev->lock_keys != locks_old) { 312 usb hid_kbd_set_led(kbd_dev);371 usb_kbd_set_led(kbd_dev); 313 372 } 314 373 } else { … … 358 417 359 418 /*----------------------------------------------------------------------------*/ 360 /** 361 * Checks if modifiers were pressed or released and generates key events. 362 * 363 * @param kbd_dev Keyboard device structure. 364 * @param modifiers Bitmap of modifiers. 365 * 366 * @sa usbhid_kbd_push_ev() 367 */ 368 //static void usbhid_kbd_check_modifier_changes(usbhid_kbd_t *kbd_dev, 369 // const uint8_t *key_codes, size_t count) 370 //{ 371 // /* 372 // * TODO: why the USB keyboard has NUM_, SCROLL_ and CAPS_LOCK 373 // * both as modifiers and as keyUSB_HID_LOCK_COUNTs with their own scancodes??? 374 // * 375 // * modifiers should be sent as normal keys to usbhid_parse_scancode()!! 376 // * so maybe it would be better if I received it from report parser in 377 // * that way 378 // */ 379 380 // int i; 381 // for (i = 0; i < count; ++i) { 382 // if ((modifiers & usb_hid_modifiers_consts[i]) && 383 // !(kbd_dev->modifiers & usb_hid_modifiers_consts[i])) { 384 // // modifier pressed 385 // if (usbhid_modifiers_keycodes[i] != 0) { 386 // usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, 387 // usbhid_modifiers_keycodes[i]); 388 // } 389 // } else if (!(modifiers & usb_hid_modifiers_consts[i]) && 390 // (kbd_dev->modifiers & usb_hid_modifiers_consts[i])) { 391 // // modifier released 392 // if (usbhid_modifiers_keycodes[i] != 0) { 393 // usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, 394 // usbhid_modifiers_keycodes[i]); 395 // } 396 // } // no change 397 // } 398 399 // kbd_dev->modifiers = modifiers; 400 //} 401 402 /*----------------------------------------------------------------------------*/ 403 404 static inline int usbhid_kbd_is_lock(unsigned int key_code) 419 420 static inline int usb_kbd_is_lock(unsigned int key_code) 405 421 { 406 422 return (key_code == KC_NUM_LOCK … … 414 430 * 415 431 * An event is created only when key is pressed or released. Besides handling 416 * the events (usb hid_kbd_push_ev()), the auto-repeat fibril is notified about417 * key presses and releases (see usb hid_kbd_repeat_start() and418 * usb hid_kbd_repeat_stop()).432 * the events (usb_kbd_push_ev()), the auto-repeat fibril is notified about 433 * key presses and releases (see usb_kbd_repeat_start() and 434 * usb_kbd_repeat_stop()). 419 435 * 420 436 * @param kbd_dev Keyboard device structure. … … 423 439 * @param count Number of key codes in report (size of the report). 424 440 * 425 * @sa usb hid_kbd_push_ev(), usbhid_kbd_repeat_start(), usbhid_kbd_repeat_stop()426 */ 427 static void usb hid_kbd_check_key_changes(usbhid_kbd_t *kbd_dev,441 * @sa usb_kbd_push_ev(), usb_kbd_repeat_start(), usb_kbd_repeat_stop() 442 */ 443 static void usb_kbd_check_key_changes(usb_kbd_t *kbd_dev, 428 444 const uint8_t *key_codes, size_t count) 429 445 { … … 434 450 * First of all, check if the kbd have reported phantom state. 435 451 * 436 * TODO:this must be changed as we don't know which keys are modifiers452 * this must be changed as we don't know which keys are modifiers 437 453 * and which are regular keys. 438 454 */ … … 466 482 // not found, i.e. the key was released 467 483 key = usbhid_parse_scancode(kbd_dev->keys[j]); 468 if (!usb hid_kbd_is_lock(key)) {469 usb hid_kbd_repeat_stop(kbd_dev, key);484 if (!usb_kbd_is_lock(key)) { 485 usb_kbd_repeat_stop(kbd_dev, key); 470 486 } 471 usb hid_kbd_push_ev(kbd_dev, KEY_RELEASE, key);487 usb_kbd_push_ev(kbd_dev, KEY_RELEASE, key); 472 488 usb_log_debug2("Key released: %d\n", key); 473 489 } else { … … 491 507 usb_log_debug2("Key pressed: %d (keycode: %d)\n", key, 492 508 key_codes[i]); 493 usb hid_kbd_push_ev(kbd_dev, KEY_PRESS, key);494 if (!usb hid_kbd_is_lock(key)) {495 usb hid_kbd_repeat_start(kbd_dev, key);509 usb_kbd_push_ev(kbd_dev, KEY_PRESS, key); 510 if (!usb_kbd_is_lock(key)) { 511 usb_kbd_repeat_start(kbd_dev, key); 496 512 } 497 513 } else { … … 523 539 * structure representing the keyboard. 524 540 * 525 * @sa usb hid_kbd_check_key_changes(), usbhid_kbd_check_modifier_changes()526 */ 527 static void usb hid_kbd_process_keycodes(const uint8_t *key_codes, size_t count,541 * @sa usb_kbd_check_key_changes(), usb_kbd_check_modifier_changes() 542 */ 543 static void usb_kbd_process_keycodes(const uint8_t *key_codes, size_t count, 528 544 uint8_t modifiers, void *arg) 529 545 { … … 534 550 } 535 551 536 usb hid_kbd_t *kbd_dev = (usbhid_kbd_t *)arg;552 usb_kbd_t *kbd_dev = (usb_kbd_t *)arg; 537 553 assert(kbd_dev != NULL); 538 554 … … 546 562 } 547 563 548 ///usb hid_kbd_check_modifier_changes(kbd_dev, key_codes, count);549 usb hid_kbd_check_key_changes(kbd_dev, key_codes, count);564 ///usb_kbd_check_modifier_changes(kbd_dev, key_codes, count); 565 usb_kbd_check_key_changes(kbd_dev, key_codes, count); 550 566 } 551 567 … … 558 574 * This function uses the HID report parser to translate the data received from 559 575 * the device into generic USB HID key codes and into generic modifiers bitmap. 560 * The parser then calls the given callback (usb hid_kbd_process_keycodes()).576 * The parser then calls the given callback (usb_kbd_process_keycodes()). 561 577 * 562 578 * @note Currently, only the boot protocol is supported. … … 566 582 * @param actual_size Size of the data from keyboard (report size) in bytes. 567 583 * 568 * @sa usbhid_kbd_process_keycodes(), usb_hid_boot_keyboard_input_report(). 569 */ 570 static void usbhid_kbd_process_data(usbhid_kbd_t *kbd_dev, 584 * @sa usb_kbd_process_keycodes(), usb_hid_boot_keyboard_input_report(), 585 * usb_hid_parse_report(). 586 */ 587 static void usb_kbd_process_data(usb_kbd_t *kbd_dev, 571 588 uint8_t *buffer, size_t actual_size) 572 589 { 573 assert(kbd_dev->initialized == USB HID_KBD_STATUS_INITIALIZED);574 assert(kbd_dev-> hid_dev->parser != NULL);590 assert(kbd_dev->initialized == USB_KBD_STATUS_INITIALIZED); 591 assert(kbd_dev->parser != NULL); 575 592 576 593 usb_hid_report_in_callbacks_t *callbacks = … … 578 595 sizeof(usb_hid_report_in_callbacks_t)); 579 596 580 callbacks->keyboard = usb hid_kbd_process_keycodes;597 callbacks->keyboard = usb_kbd_process_keycodes; 581 598 582 599 usb_log_debug("Calling usb_hid_parse_report() with " … … 585 602 // int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size, 586 603 // callbacks, kbd_dev); 587 int rc = usb_hid_parse_report(kbd_dev->hid_dev->parser, buffer, 588 actual_size, callbacks, kbd_dev); 604 usb_hid_report_path_t *path = usb_hid_report_path(); 605 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0); 606 607 int rc = usb_hid_parse_report(kbd_dev->parser, buffer, 608 actual_size, path, USB_HID_PATH_COMPARE_STRICT, callbacks, kbd_dev); 609 610 usb_hid_report_path_free (path); 589 611 590 612 if (rc != EOK) { … … 597 619 /* HID/KBD structure manipulation */ 598 620 /*----------------------------------------------------------------------------*/ 621 622 static void usb_kbd_mark_unusable(usb_kbd_t *kbd_dev) 623 { 624 kbd_dev->initialized = USB_KBD_STATUS_TO_DESTROY; 625 } 626 627 628 /*----------------------------------------------------------------------------*/ 629 /* API functions */ 630 /*----------------------------------------------------------------------------*/ 599 631 /** 600 632 * Creates a new USB/HID keyboard structure. 601 633 * 602 634 * The structure returned by this function is not initialized. Use 603 * usb hid_kbd_init() to initialize it prior to polling.635 * usb_kbd_init() to initialize it prior to polling. 604 636 * 605 637 * @return New uninitialized structure for representing a USB/HID keyboard or 606 638 * NULL if not successful (memory error). 607 639 */ 608 static usbhid_kbd_t *usbhid_kbd_new(void)609 { 610 usb hid_kbd_t *kbd_dev =611 (usb hid_kbd_t *)malloc(sizeof(usbhid_kbd_t));640 usb_kbd_t *usb_kbd_new(void) 641 { 642 usb_kbd_t *kbd_dev = 643 (usb_kbd_t *)malloc(sizeof(usb_kbd_t)); 612 644 613 645 if (kbd_dev == NULL) { … … 616 648 } 617 649 618 memset(kbd_dev, 0, sizeof(usbhid_kbd_t)); 619 620 kbd_dev->hid_dev = usbhid_dev_new(); 621 if (kbd_dev->hid_dev == NULL) { 622 usb_log_fatal("Could not create HID device structure.\n"); 650 memset(kbd_dev, 0, sizeof(usb_kbd_t)); 651 652 kbd_dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof( 653 usb_hid_report_parser_t))); 654 if (kbd_dev->parser == NULL) { 655 usb_log_fatal("No memory!\n"); 656 free(kbd_dev); 623 657 return NULL; 624 658 } 625 659 626 660 kbd_dev->console_phone = -1; 627 kbd_dev->initialized = USB HID_KBD_STATUS_UNINITIALIZED;661 kbd_dev->initialized = USB_KBD_STATUS_UNINITIALIZED; 628 662 629 663 return kbd_dev; 630 }631 632 /*----------------------------------------------------------------------------*/633 634 static void usbhid_kbd_mark_unusable(usbhid_kbd_t *kbd_dev)635 {636 kbd_dev->initialized = USBHID_KBD_STATUS_TO_DESTROY;637 664 } 638 665 … … 658 685 * @return Other value inherited from function usbhid_dev_init(). 659 686 */ 660 static int usbhid_kbd_init(usbhid_kbd_t *kbd_dev, ddf_dev_t *dev)687 int usb_kbd_init(usb_kbd_t *kbd_dev, usb_device_t *dev) 661 688 { 662 689 int rc; … … 671 698 672 699 if (dev == NULL) { 673 usb_log_error("Failed to init keyboard structure: no device"700 usb_log_error("Failed to init keyboard structure: no USB device" 674 701 " given.\n"); 675 702 return EINVAL; 676 703 } 677 704 678 if (kbd_dev->initialized == USB HID_KBD_STATUS_INITIALIZED) {705 if (kbd_dev->initialized == USB_KBD_STATUS_INITIALIZED) { 679 706 usb_log_warning("Keyboard structure already initialized.\n"); 680 707 return EINVAL; 681 708 } 682 709 683 rc = usbhid_dev_init(kbd_dev->hid_dev, dev, &poll_endpoint_description); 684 710 /* TODO: does not work! */ 711 if (!dev->pipes[USB_KBD_POLL_EP_NO].present) { 712 usb_log_warning("Required endpoint not found - probably not " 713 "a supported device.\n"); 714 return ENOTSUP; 715 } 716 717 /* The USB device should already be initialized, save it in structure */ 718 kbd_dev->usb_dev = dev; 719 720 /* Initialize the report parser. */ 721 rc = usb_hid_parser_init(kbd_dev->parser); 685 722 if (rc != EOK) { 686 usb_log_error("Failed to initialize HID device structure: %s\n", 687 str_error(rc)); 723 usb_log_error("Failed to initialize report parser.\n"); 688 724 return rc; 689 725 } 690 726 691 assert(kbd_dev->hid_dev->initialized == USBHID_KBD_STATUS_INITIALIZED); 692 693 // save the size of the report (boot protocol report by default) 694 // kbd_dev->key_count = BOOTP_REPORT_SIZE; 695 696 usb_hid_report_path_t path; 697 path.usage_page = USB_HIDUT_PAGE_KEYBOARD; 727 /* Get the report descriptor and parse it. */ 728 rc = usb_hid_process_report_descriptor(kbd_dev->usb_dev, 729 kbd_dev->parser); 730 if (rc != EOK) { 731 usb_log_warning("Could not process report descriptor, " 732 "falling back to boot protocol.\n"); 733 rc = usb_hid_parse_report_descriptor(kbd_dev->parser, 734 BOOT_REPORT_DESCRIPTOR, BOOT_REPORT_DESCRIPTOR_SIZE); 735 if (rc != EOK) { 736 usb_log_error("Failed to parse boot report descriptor:" 737 " %s.\n", str_error(rc)); 738 return rc; 739 } 740 741 rc = usbhid_req_set_protocol(&kbd_dev->usb_dev->ctrl_pipe, 742 kbd_dev->usb_dev->interface_no, USB_HID_PROTOCOL_BOOT); 743 744 if (rc != EOK) { 745 usb_log_warning("Failed to set boot protocol to the " 746 "device: %s\n", str_error(rc)); 747 return rc; 748 } 749 } 750 751 /* 752 * TODO: make more general 753 */ 754 usb_hid_report_path_t *path = usb_hid_report_path(); 755 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0); 698 756 kbd_dev->key_count = usb_hid_report_input_length( 699 kbd_dev->hid_dev->parser, &path); 757 kbd_dev->parser, path, USB_HID_PATH_COMPARE_STRICT); 758 usb_hid_report_path_free (path); 700 759 701 760 usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count); … … 729 788 730 789 /* 731 * Set boot protocol.732 790 * Set LEDs according to initial setup. 733 791 * Set Idle rate 734 792 */ 735 assert(kbd_dev->hid_dev != NULL); 736 assert(kbd_dev->hid_dev->initialized); 737 //usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT); 738 739 usbhid_kbd_set_led(kbd_dev); 740 741 usbhid_req_set_idle(kbd_dev->hid_dev, IDLE_RATE); 742 743 kbd_dev->initialized = USBHID_KBD_STATUS_INITIALIZED; 793 usb_kbd_set_led(kbd_dev); 794 795 usbhid_req_set_idle(&kbd_dev->usb_dev->ctrl_pipe, 796 kbd_dev->usb_dev->interface_no, IDLE_RATE); 797 798 kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED; 744 799 usb_log_debug("HID/KBD device structure initialized.\n"); 745 800 … … 748 803 749 804 /*----------------------------------------------------------------------------*/ 750 /* HID/KBD polling */ 751 /*----------------------------------------------------------------------------*/ 752 /** 753 * Main keyboard polling function. 754 * 755 * This function uses the Interrupt In pipe of the keyboard to poll for events. 756 * The keyboard is initialized in a way that it reports only when a key is 757 * pressed or released, so there is no actual need for any sleeping between 758 * polls (see usbhid_kbd_try_add_device() or usbhid_kbd_init()). 759 * 760 * @param kbd_dev Initialized keyboard structure representing the device to 761 * poll. 762 * 763 * @sa usbhid_kbd_process_data() 764 */ 765 static void usbhid_kbd_poll(usbhid_kbd_t *kbd_dev) 766 { 767 int rc, sess_rc; 768 uint8_t buffer[BOOTP_BUFFER_SIZE]; 769 size_t actual_size; 770 771 usb_log_debug("Polling keyboard...\n"); 772 773 if (!kbd_dev->initialized) { 774 usb_log_error("HID/KBD device not initialized!\n"); 775 return; 776 } 777 778 assert(kbd_dev->hid_dev != NULL); 779 assert(kbd_dev->hid_dev->initialized); 780 781 while (true) { 782 sess_rc = usb_pipe_start_session( 783 &kbd_dev->hid_dev->poll_pipe); 784 if (sess_rc != EOK) { 785 usb_log_warning("Failed to start a session: %s.\n", 786 str_error(sess_rc)); 787 break; 788 } 789 790 rc = usb_pipe_read(&kbd_dev->hid_dev->poll_pipe, 791 buffer, BOOTP_BUFFER_SIZE, &actual_size); 792 793 sess_rc = usb_pipe_end_session( 794 &kbd_dev->hid_dev->poll_pipe); 795 796 if (rc != EOK) { 797 usb_log_warning("Error polling the keyboard: %s.\n", 798 str_error(rc)); 799 break; 800 } 801 802 if (sess_rc != EOK) { 803 usb_log_warning("Error closing session: %s.\n", 804 str_error(sess_rc)); 805 break; 806 } 807 808 /* 809 * If the keyboard answered with NAK, it returned no data. 810 * This implies that no change happened since last query. 811 */ 812 if (actual_size == 0) { 813 usb_log_debug("Keyboard returned NAK\n"); 814 continue; 815 } 816 817 /* 818 * TODO: Process pressed keys. 819 */ 820 usb_log_debug("Calling usbhid_kbd_process_data()\n"); 821 usbhid_kbd_process_data(kbd_dev, buffer, actual_size); 822 823 // disabled for now, no reason to sleep 824 //async_usleep(kbd_dev->hid_dev->poll_interval); 825 } 826 } 827 828 /*----------------------------------------------------------------------------*/ 829 /** 830 * Function executed by the main driver fibril. 831 * 832 * Just starts polling the keyboard for events. 833 * 834 * @param arg Initialized keyboard device structure (of type usbhid_kbd_t) 835 * representing the device. 836 * 837 * @retval EOK if the fibril finished polling the device. 838 * @retval EINVAL if no device was given in the argument. 839 * 840 * @sa usbhid_kbd_poll() 841 * 842 * @todo Change return value - only case when the fibril finishes is in case 843 * of some error, so the error should probably be propagated from function 844 * usbhid_kbd_poll() to here and up. 845 */ 846 static int usbhid_kbd_fibril(void *arg) 847 { 848 if (arg == NULL) { 849 usb_log_error("No device!\n"); 850 return EINVAL; 851 } 852 853 usbhid_kbd_t *kbd_dev = (usbhid_kbd_t *)arg; 854 855 usbhid_kbd_poll(kbd_dev); 856 857 // as there is another fibril using this device, so we must leave the 858 // structure to it, but mark it for destroying. 859 usbhid_kbd_mark_unusable(kbd_dev); 860 // at the end, properly destroy the KBD structure 861 // usbhid_kbd_free(&kbd_dev); 862 // assert(kbd_dev == NULL); 863 864 return EOK; 865 } 866 867 /*----------------------------------------------------------------------------*/ 868 /* API functions */ 869 /*----------------------------------------------------------------------------*/ 870 /** 871 * Function for adding a new device of type USB/HID/keyboard. 872 * 873 * This functions initializes required structures from the device's descriptors 874 * and starts new fibril for polling the keyboard for events and another one for 875 * handling auto-repeat of keys. 876 * 877 * During initialization, the keyboard is switched into boot protocol, the idle 878 * rate is set to 0 (infinity), resulting in the keyboard only reporting event 879 * when a key is pressed or released. Finally, the LED lights are turned on 880 * according to the default setup of lock keys. 881 * 882 * @note By default, the keyboards is initialized with Num Lock turned on and 883 * other locks turned off. 884 * @note Currently supports only boot-protocol keyboards. 885 * 886 * @param dev Device to add. 887 * 888 * @retval EOK if successful. 889 * @retval ENOMEM if there 890 * @return Other error code inherited from one of functions usbhid_kbd_init(), 891 * ddf_fun_bind() and ddf_fun_add_to_class(). 892 * 893 * @sa usbhid_kbd_fibril(), usbhid_kbd_repeat_fibril() 894 */ 895 int usbhid_kbd_try_add_device(ddf_dev_t *dev) 896 { 897 /* 898 * Create default function. 899 */ 900 ddf_fun_t *kbd_fun = ddf_fun_create(dev, fun_exposed, "keyboard"); 901 if (kbd_fun == NULL) { 902 usb_log_error("Could not create DDF function node.\n"); 903 return ENOMEM; 904 } 905 906 /* 907 * Initialize device (get and process descriptors, get address, etc.) 908 */ 909 usb_log_debug("Initializing USB/HID KBD device...\n"); 910 911 usbhid_kbd_t *kbd_dev = usbhid_kbd_new(); 912 if (kbd_dev == NULL) { 913 usb_log_error("Error while creating USB/HID KBD device " 914 "structure.\n"); 915 ddf_fun_destroy(kbd_fun); 916 return ENOMEM; // TODO: some other code?? 917 } 918 919 int rc = usbhid_kbd_init(kbd_dev, dev); 920 921 if (rc != EOK) { 922 usb_log_error("Failed to initialize USB/HID KBD device.\n"); 923 ddf_fun_destroy(kbd_fun); 924 usbhid_kbd_free(&kbd_dev); 925 return rc; 926 } 927 928 usb_log_debug("USB/HID KBD device structure initialized.\n"); 929 930 /* 931 * Store the initialized keyboard device and keyboard ops 932 * to the DDF function. 933 */ 934 kbd_fun->driver_data = kbd_dev; 935 kbd_fun->ops = &keyboard_ops; 936 937 rc = ddf_fun_bind(kbd_fun); 938 if (rc != EOK) { 939 usb_log_error("Could not bind DDF function: %s.\n", 940 str_error(rc)); 941 // TODO: Can / should I destroy the DDF function? 942 ddf_fun_destroy(kbd_fun); 943 usbhid_kbd_free(&kbd_dev); 944 return rc; 945 } 946 947 rc = ddf_fun_add_to_class(kbd_fun, "keyboard"); 948 if (rc != EOK) { 949 usb_log_error( 950 "Could not add DDF function to class 'keyboard': %s.\n", 951 str_error(rc)); 952 // TODO: Can / should I destroy the DDF function? 953 ddf_fun_destroy(kbd_fun); 954 usbhid_kbd_free(&kbd_dev); 955 return rc; 956 } 957 958 /* 959 * Create new fibril for handling this keyboard 960 */ 961 fid_t fid = fibril_create(usbhid_kbd_fibril, kbd_dev); 962 if (fid == 0) { 963 usb_log_error("Failed to start fibril for `%s' device.\n", 964 dev->name); 965 return ENOMEM; 966 } 967 fibril_add_ready(fid); 968 969 /* 970 * Create new fibril for auto-repeat 971 */ 972 fid = fibril_create(usbhid_kbd_repeat_fibril, kbd_dev); 973 if (fid == 0) { 974 usb_log_error("Failed to start fibril for KBD auto-repeat"); 975 return ENOMEM; 976 } 977 fibril_add_ready(fid); 978 979 (void)keyboard_ops; 980 981 /* 982 * Hurrah, device is initialized. 983 */ 984 return EOK; 985 } 986 987 /*----------------------------------------------------------------------------*/ 988 989 int usbhid_kbd_is_usable(const usbhid_kbd_t *kbd_dev) 990 { 991 return (kbd_dev->initialized == USBHID_KBD_STATUS_INITIALIZED); 805 806 bool usb_kbd_polling_callback(usb_device_t *dev, uint8_t *buffer, 807 size_t buffer_size, void *arg) 808 { 809 if (dev == NULL || buffer == NULL || arg == NULL) { 810 // do not continue polling (???) 811 return false; 812 } 813 814 usb_kbd_t *kbd_dev = (usb_kbd_t *)arg; 815 816 // TODO: add return value from this function 817 usb_kbd_process_data(kbd_dev, buffer, buffer_size); 818 819 return true; 820 } 821 822 /*----------------------------------------------------------------------------*/ 823 824 void usb_kbd_polling_ended_callback(usb_device_t *dev, bool reason, 825 void *arg) 826 { 827 if (dev == NULL || arg == NULL) { 828 return; 829 } 830 831 usb_kbd_t *kbd = (usb_kbd_t *)arg; 832 833 usb_kbd_mark_unusable(kbd); 834 } 835 836 /*----------------------------------------------------------------------------*/ 837 838 int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev) 839 { 840 return (kbd_dev->initialized == USB_KBD_STATUS_INITIALIZED); 841 } 842 843 /*----------------------------------------------------------------------------*/ 844 845 int usb_kbd_is_ready_to_destroy(const usb_kbd_t *kbd_dev) 846 { 847 return (kbd_dev->initialized == USB_KBD_STATUS_TO_DESTROY); 992 848 } 993 849 … … 998 854 * @param kbd_dev Pointer to the structure to be destroyed. 999 855 */ 1000 void usb hid_kbd_free(usbhid_kbd_t **kbd_dev)856 void usb_kbd_free(usb_kbd_t **kbd_dev) 1001 857 { 1002 858 if (kbd_dev == NULL || *kbd_dev == NULL) { … … 1007 863 async_hangup((*kbd_dev)->console_phone); 1008 864 1009 if ((*kbd_dev)->hid_dev != NULL) {1010 usbhid_dev_free(&(*kbd_dev)->hid_dev);1011 assert((*kbd_dev)->hid_dev == NULL);1012 }865 // if ((*kbd_dev)->hid_dev != NULL) { 866 // usbhid_dev_free(&(*kbd_dev)->hid_dev); 867 // assert((*kbd_dev)->hid_dev == NULL); 868 // } 1013 869 1014 870 if ((*kbd_dev)->repeat_mtx != NULL) { … … 1017 873 free((*kbd_dev)->repeat_mtx); 1018 874 } 875 876 // destroy the parser 877 if ((*kbd_dev)->parser != NULL) { 878 usb_hid_free_report_parser((*kbd_dev)->parser); 879 } 880 881 /* TODO: what about the USB device structure?? */ 1019 882 1020 883 free(*kbd_dev);
Note:
See TracChangeset
for help on using the changeset viewer.