Changeset f8e4cb6 in mainline for uspace/drv/usbhid/kbddev.c
- Timestamp:
- 2011-03-22T19:11:21Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 82d04a48
- Parents:
- 62f4212
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/usbhid/kbddev.c
r62f4212 rf8e4cb6 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> … … 53 55 #include <usb/classes/hidut.h> 54 56 57 #include <usb/devdrv.h> 58 55 59 #include "kbddev.h" 56 60 #include "hiddev.h" … … 86 90 87 91 /** Keyboard polling endpoint description for boot protocol class. */ 88 static usb_endpoint_description_t poll_endpoint_description = {92 static usb_endpoint_description_t boot_poll_endpoint_description = { 89 93 .transfer_type = USB_TRANSFER_INTERRUPT, 90 94 .direction = USB_DIRECTION_IN, … … 94 98 .flags = 0 95 99 }; 100 101 /** General keyboard polling endpoint description. */ 102 //static usb_endpoint_description_t general_poll_endpoint_description = { 103 // .transfer_type = USB_TRANSFER_INTERRUPT, 104 // .direction = USB_DIRECTION_IN, 105 // .interface_class = USB_CLASS_HID, 106 // .flags = 0 107 //}; 108 109 /* Array of endpoints expected on the device, NULL terminated. */ 110 usb_endpoint_description_t 111 *usbhid_kbd_endpoints[USBHID_KBD_POLL_EP_COUNT + 1] = { 112 &boot_poll_endpoint_description, 113 // &general_poll_endpoint_description, 114 NULL 115 }; 116 96 117 97 118 typedef enum usbhid_kbd_flags { … … 149 170 150 171 static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *); 151 staticddf_dev_ops_t keyboard_ops = {172 ddf_dev_ops_t keyboard_ops = { 152 173 .default_handler = default_connection_handler 153 174 }; … … 237 258 usb_debug_str_buffer(buffer, BOOTP_BUFFER_OUT_SIZE, 0)); 238 259 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, 260 assert(kbd_dev->usb_dev != NULL); 261 262 usbhid_req_set_report(&kbd_dev->usb_dev->ctrl_pipe, 263 kbd_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT, 242 264 buffer, BOOTP_BUFFER_OUT_SIZE); 243 265 } … … 370 392 //{ 371 393 // /* 372 // * TODO:why the USB keyboard has NUM_, SCROLL_ and CAPS_LOCK394 // * why the USB keyboard has NUM_, SCROLL_ and CAPS_LOCK 373 395 // * both as modifiers and as keyUSB_HID_LOCK_COUNTs with their own scancodes??? 374 396 // * … … 434 456 * First of all, check if the kbd have reported phantom state. 435 457 * 436 * TODO:this must be changed as we don't know which keys are modifiers458 * this must be changed as we don't know which keys are modifiers 437 459 * and which are regular keys. 438 460 */ … … 566 588 * @param actual_size Size of the data from keyboard (report size) in bytes. 567 589 * 568 * @sa usbhid_kbd_process_keycodes(), usb_hid_boot_keyboard_input_report(). 590 * @sa usbhid_kbd_process_keycodes(), usb_hid_boot_keyboard_input_report(), 591 * usb_hid_parse_report(). 569 592 */ 570 593 static void usbhid_kbd_process_data(usbhid_kbd_t *kbd_dev, … … 572 595 { 573 596 assert(kbd_dev->initialized == USBHID_KBD_STATUS_INITIALIZED); 574 assert(kbd_dev-> hid_dev->parser != NULL);597 assert(kbd_dev->parser != NULL); 575 598 576 599 usb_hid_report_in_callbacks_t *callbacks = … … 585 608 // int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size, 586 609 // callbacks, kbd_dev); 587 int rc = usb_hid_parse_report(kbd_dev-> hid_dev->parser, buffer,610 int rc = usb_hid_parse_report(kbd_dev->parser, buffer, 588 611 actual_size, callbacks, kbd_dev); 589 612 … … 597 620 /* HID/KBD structure manipulation */ 598 621 /*----------------------------------------------------------------------------*/ 622 623 static void usbhid_kbd_mark_unusable(usbhid_kbd_t *kbd_dev) 624 { 625 kbd_dev->initialized = USBHID_KBD_STATUS_TO_DESTROY; 626 } 627 628 /*----------------------------------------------------------------------------*/ 629 /* HID/KBD polling */ 630 /*----------------------------------------------------------------------------*/ 631 /** 632 * Main keyboard polling function. 633 * 634 * This function uses the Interrupt In pipe of the keyboard to poll for events. 635 * The keyboard is initialized in a way that it reports only when a key is 636 * pressed or released, so there is no actual need for any sleeping between 637 * polls (see usbhid_kbd_try_add_device() or usbhid_kbd_init()). 638 * 639 * @param kbd_dev Initialized keyboard structure representing the device to 640 * poll. 641 * 642 * @sa usbhid_kbd_process_data() 643 */ 644 //static void usbhid_kbd_poll(usbhid_kbd_t *kbd_dev) 645 //{ 646 // int rc, sess_rc; 647 // uint8_t buffer[BOOTP_BUFFER_SIZE]; 648 // size_t actual_size; 649 650 // usb_log_debug("Polling keyboard...\n"); 651 652 // if (!kbd_dev->initialized) { 653 // usb_log_error("HID/KBD device not initialized!\n"); 654 // return; 655 // } 656 657 // assert(kbd_dev->hid_dev != NULL); 658 // assert(kbd_dev->hid_dev->initialized); 659 660 // while (true) { 661 // sess_rc = usb_pipe_start_session( 662 // &kbd_dev->hid_dev->poll_pipe); 663 // if (sess_rc != EOK) { 664 // usb_log_warning("Failed to start a session: %s.\n", 665 // str_error(sess_rc)); 666 // break; 667 // } 668 669 // rc = usb_pipe_read(&kbd_dev->hid_dev->poll_pipe, 670 // buffer, BOOTP_BUFFER_SIZE, &actual_size); 671 672 // sess_rc = usb_pipe_end_session( 673 // &kbd_dev->hid_dev->poll_pipe); 674 675 // if (rc != EOK) { 676 // usb_log_warning("Error polling the keyboard: %s.\n", 677 // str_error(rc)); 678 // break; 679 // } 680 681 // if (sess_rc != EOK) { 682 // usb_log_warning("Error closing session: %s.\n", 683 // str_error(sess_rc)); 684 // break; 685 // } 686 687 // /* 688 // * If the keyboard answered with NAK, it returned no data. 689 // * This implies that no change happened since last query. 690 // */ 691 // if (actual_size == 0) { 692 // usb_log_debug("Keyboard returned NAK\n"); 693 // continue; 694 // } 695 696 // /* 697 // * TODO: Process pressed keys. 698 // */ 699 // usb_log_debug("Calling usbhid_kbd_process_data()\n"); 700 // usbhid_kbd_process_data(kbd_dev, buffer, actual_size); 701 702 // // disabled for now, no reason to sleep 703 // //async_usleep(kbd_dev->hid_dev->poll_interval); 704 // } 705 //} 706 707 /*----------------------------------------------------------------------------*/ 708 /** 709 * Function executed by the main driver fibril. 710 * 711 * Just starts polling the keyboard for events. 712 * 713 * @param arg Initialized keyboard device structure (of type usbhid_kbd_t) 714 * representing the device. 715 * 716 * @retval EOK if the fibril finished polling the device. 717 * @retval EINVAL if no device was given in the argument. 718 * 719 * @sa usbhid_kbd_poll() 720 * 721 * @todo Change return value - only case when the fibril finishes is in case 722 * of some error, so the error should probably be propagated from function 723 * usbhid_kbd_poll() to here and up. 724 */ 725 //static int usbhid_kbd_fibril(void *arg) 726 //{ 727 // if (arg == NULL) { 728 // usb_log_error("No device!\n"); 729 // return EINVAL; 730 // } 731 732 // usbhid_kbd_t *kbd_dev = (usbhid_kbd_t *)arg; 733 734 // usbhid_kbd_poll(kbd_dev); 735 736 // // as there is another fibril using this device, so we must leave the 737 // // structure to it, but mark it for destroying. 738 // usbhid_kbd_mark_unusable(kbd_dev); 739 // // at the end, properly destroy the KBD structure 740 //// usbhid_kbd_free(&kbd_dev); 741 //// assert(kbd_dev == NULL); 742 743 // return EOK; 744 //} 745 746 static int usbhid_dev_get_report_descriptor(usbhid_kbd_t *kbd_dev) 747 { 748 assert(kbd_dev != NULL); 749 assert(kbd_dev->usb_dev != NULL); 750 assert(kbd_dev->usb_dev->interface_no >= 0); 751 752 usb_dp_parser_t parser = { 753 .nesting = usb_dp_standard_descriptor_nesting 754 }; 755 756 usb_dp_parser_data_t parser_data = { 757 .data = kbd_dev->usb_dev->descriptors.configuration, 758 .size = kbd_dev->usb_dev->descriptors.configuration_size, 759 .arg = NULL 760 }; 761 762 /* 763 * First nested descriptor of the configuration descriptor. 764 */ 765 uint8_t *d = 766 usb_dp_get_nested_descriptor(&parser, &parser_data, 767 kbd_dev->usb_dev->descriptors.configuration); 768 769 /* 770 * Find the interface descriptor corresponding to our interface number. 771 */ 772 int i = 0; 773 while (d != NULL && i < kbd_dev->usb_dev->interface_no) { 774 d = usb_dp_get_sibling_descriptor(&parser, &parser_data, 775 kbd_dev->usb_dev->descriptors.configuration, d); 776 } 777 778 if (d == NULL) { 779 usb_log_fatal("The %. interface descriptor not found!\n", 780 kbd_dev->usb_dev->interface_no); 781 return ENOENT; 782 } 783 784 /* 785 * First nested descriptor of the interface descriptor. 786 */ 787 uint8_t *iface_desc = d; 788 d = usb_dp_get_nested_descriptor(&parser, &parser_data, iface_desc); 789 790 /* 791 * Search through siblings until the HID descriptor is found. 792 */ 793 while (d != NULL && *(d + 1) != USB_DESCTYPE_HID) { 794 d = usb_dp_get_sibling_descriptor(&parser, &parser_data, 795 iface_desc, d); 796 } 797 798 if (d == NULL) { 799 usb_log_fatal("No HID descriptor found!\n"); 800 return ENOENT; 801 } 802 803 if (*d != sizeof(usb_standard_hid_descriptor_t)) { 804 usb_log_fatal("HID descriptor hass wrong size (%u, expected %u" 805 ")\n", *d, sizeof(usb_standard_hid_descriptor_t)); 806 return EINVAL; 807 } 808 809 usb_standard_hid_descriptor_t *hid_desc = 810 (usb_standard_hid_descriptor_t *)d; 811 812 uint16_t length = hid_desc->report_desc_info.length; 813 size_t actual_size = 0; 814 815 /* 816 * Start session for the control transfer. 817 */ 818 int sess_rc = usb_pipe_start_session(&kbd_dev->usb_dev->ctrl_pipe); 819 if (sess_rc != EOK) { 820 usb_log_warning("Failed to start a session: %s.\n", 821 str_error(sess_rc)); 822 return sess_rc; 823 } 824 825 /* 826 * Allocate space for the report descriptor. 827 */ 828 kbd_dev->report_desc = (uint8_t *)malloc(length); 829 if (kbd_dev->report_desc == NULL) { 830 usb_log_fatal("Failed to allocate space for Report descriptor." 831 "\n"); 832 return ENOMEM; 833 } 834 835 usb_log_debug("Getting Report descriptor, expected size: %u\n", length); 836 837 /* 838 * Get the descriptor from the device. 839 */ 840 int rc = usb_request_get_descriptor(&kbd_dev->usb_dev->ctrl_pipe, 841 USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE, 842 USB_DESCTYPE_HID_REPORT, 0, kbd_dev->usb_dev->interface_no, 843 kbd_dev->report_desc, length, &actual_size); 844 845 if (rc != EOK) { 846 free(kbd_dev->report_desc); 847 kbd_dev->report_desc = NULL; 848 return rc; 849 } 850 851 if (actual_size != length) { 852 free(kbd_dev->report_desc); 853 kbd_dev->report_desc = NULL; 854 usb_log_fatal("Report descriptor has wrong size (%u, expected " 855 "%u)\n", actual_size, length); 856 return EINVAL; 857 } 858 859 /* 860 * End session for the control transfer. 861 */ 862 sess_rc = usb_pipe_end_session(&kbd_dev->usb_dev->ctrl_pipe); 863 if (sess_rc != EOK) { 864 usb_log_warning("Failed to end a session: %s.\n", 865 str_error(sess_rc)); 866 free(kbd_dev->report_desc); 867 kbd_dev->report_desc = NULL; 868 return sess_rc; 869 } 870 871 kbd_dev->report_desc_size = length; 872 873 usb_log_debug("Done.\n"); 874 875 return EOK; 876 } 877 878 /*----------------------------------------------------------------------------*/ 879 880 static int usbhid_kbd_process_report_descriptor(usbhid_kbd_t *kbd_dev) 881 { 882 int rc = usbhid_dev_get_report_descriptor(kbd_dev); 883 884 if (rc != EOK) { 885 usb_log_warning("Problem with getting Report descriptor: %s.\n", 886 str_error(rc)); 887 return rc; 888 } 889 890 rc = usb_hid_parse_report_descriptor(kbd_dev->parser, 891 kbd_dev->report_desc, kbd_dev->report_desc_size); 892 if (rc != EOK) { 893 usb_log_warning("Problem parsing Report descriptor: %s.\n", 894 str_error(rc)); 895 return rc; 896 } 897 898 usb_hid_descriptor_print(kbd_dev->parser); 899 900 /* 901 * TODO: if failed, try to parse the boot report descriptor. 902 */ 903 904 return EOK; 905 } 906 907 /*----------------------------------------------------------------------------*/ 908 /* API functions */ 909 /*----------------------------------------------------------------------------*/ 599 910 /** 600 911 * Creates a new USB/HID keyboard structure. … … 606 917 * NULL if not successful (memory error). 607 918 */ 608 staticusbhid_kbd_t *usbhid_kbd_new(void)919 usbhid_kbd_t *usbhid_kbd_new(void) 609 920 { 610 921 usbhid_kbd_t *kbd_dev = … … 618 929 memset(kbd_dev, 0, sizeof(usbhid_kbd_t)); 619 930 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");623 return NULL;624 }625 626 931 kbd_dev->console_phone = -1; 627 932 kbd_dev->initialized = USBHID_KBD_STATUS_UNINITIALIZED; 628 933 629 934 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 935 } 638 936 … … 658 956 * @return Other value inherited from function usbhid_dev_init(). 659 957 */ 660 static int usbhid_kbd_init(usbhid_kbd_t *kbd_dev, ddf_dev_t *dev)958 int usbhid_kbd_init(usbhid_kbd_t *kbd_dev, usb_device_t *dev) 661 959 { 662 960 int rc; … … 671 969 672 970 if (dev == NULL) { 673 usb_log_error("Failed to init keyboard structure: no device"971 usb_log_error("Failed to init keyboard structure: no USB device" 674 972 " given.\n"); 675 973 return EINVAL; … … 681 979 } 682 980 683 rc = usbhid_dev_init(kbd_dev->hid_dev, dev, &poll_endpoint_description); 684 685 if (rc != EOK) { 686 usb_log_error("Failed to initialize HID device structure: %s\n", 687 str_error(rc)); 688 return rc; 689 } 690 691 assert(kbd_dev->hid_dev->initialized == USBHID_KBD_STATUS_INITIALIZED); 981 //rc = usbhid_dev_init(kbd_dev->hid_dev, dev, &poll_endpoint_description); 982 983 984 // if (rc != EOK) { 985 // usb_log_error("Failed to initialize HID device structure: %s\n", 986 // str_error(rc)); 987 // return rc; 988 // } 989 990 // assert(kbd_dev->hid_dev->initialized == USBHID_KBD_STATUS_INITIALIZED); 692 991 693 992 // save the size of the report (boot protocol report by default) 694 993 // kbd_dev->key_count = BOOTP_REPORT_SIZE; 695 994 995 /* The USB device should already be initialized, save it in structure */ 996 kbd_dev->usb_dev = dev; 997 998 /* Get the report descriptor and initialize report parser. */ 999 rc = usbhid_kbd_process_report_descriptor(kbd_dev); 1000 if (rc != EOK) { 1001 usb_log_warning("Could not process report descriptor.\n"); 1002 return rc; 1003 } 1004 1005 /* 1006 * TODO: make more general 1007 */ 696 1008 usb_hid_report_path_t path; 697 1009 path.usage_page = USB_HIDUT_PAGE_KEYBOARD; 698 1010 kbd_dev->key_count = usb_hid_report_input_length( 699 kbd_dev-> hid_dev->parser, &path);1011 kbd_dev->parser, &path); 700 1012 701 1013 usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count); … … 733 1045 * Set Idle rate 734 1046 */ 735 assert(kbd_dev->hid_dev != NULL);736 assert(kbd_dev->hid_dev->initialized);1047 //assert(kbd_dev->hid_dev != NULL); 1048 //assert(kbd_dev->hid_dev->initialized); 737 1049 //usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT); 738 1050 739 1051 usbhid_kbd_set_led(kbd_dev); 740 1052 741 usbhid_req_set_idle(kbd_dev->hid_dev, IDLE_RATE); 1053 usbhid_req_set_idle(&kbd_dev->usb_dev->ctrl_pipe, 1054 kbd_dev->usb_dev->interface_no, IDLE_RATE); 742 1055 743 1056 kbd_dev->initialized = USBHID_KBD_STATUS_INITIALIZED; … … 748 1061 749 1062 /*----------------------------------------------------------------------------*/ 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"); 1063 1064 bool usbhid_kbd_polling_callback(usb_device_t *dev, uint8_t *buffer, 1065 size_t buffer_size, void *arg) 1066 { 1067 if (dev == NULL || buffer == NULL || arg == NULL) { 1068 // do not continue polling (???) 1069 return false; 1070 } 1071 1072 usbhid_kbd_t *kbd_dev = (usbhid_kbd_t *)arg; 1073 1074 // TODO: add return value from this function 1075 usbhid_kbd_process_data(kbd_dev, buffer, buffer_size); 1076 1077 return true; 1078 } 1079 1080 /*----------------------------------------------------------------------------*/ 1081 1082 void usbhid_kbd_polling_ended_callback(usb_device_t *dev, bool reason, 1083 void *arg) 1084 { 1085 if (dev == NULL || arg == NULL) { 775 1086 return; 776 1087 } 777 1088 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; 1089 usbhid_kbd_t *kbd = (usbhid_kbd_t *)arg; 1090 1091 usbhid_kbd_mark_unusable(kbd); 985 1092 } 986 1093 … … 1014 1121 async_hangup((*kbd_dev)->console_phone); 1015 1122 1016 if ((*kbd_dev)->hid_dev != NULL) {1017 usbhid_dev_free(&(*kbd_dev)->hid_dev);1018 assert((*kbd_dev)->hid_dev == NULL);1019 }1123 // if ((*kbd_dev)->hid_dev != NULL) { 1124 // usbhid_dev_free(&(*kbd_dev)->hid_dev); 1125 // assert((*kbd_dev)->hid_dev == NULL); 1126 // } 1020 1127 1021 1128 if ((*kbd_dev)->repeat_mtx != NULL) { … … 1024 1131 free((*kbd_dev)->repeat_mtx); 1025 1132 } 1133 1134 /* TODO: what about the USB device structure?? */ 1026 1135 1027 1136 free(*kbd_dev);
Note:
See TracChangeset
for help on using the changeset viewer.