Changeset 9d9ffdd in mainline for uspace/drv/usbhid


Ignore:
Timestamp:
2011-03-11T15:42:43Z (15 years ago)
Author:
Matej Klonfar <maklf@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0bd4810c
Parents:
60a228f (diff), a8def7d (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.
Message:

merge with hidd

Location:
uspace/drv/usbhid
Files:
2 added
11 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/usbhid/Makefile

    r60a228f r9d9ffdd  
    4242        hidreq.c \
    4343        kbddev.c \
     44        kbdrepeat.c \
    4445        hiddev.c \
    4546        $(STOLEN_LAYOUT_SOURCES)
  • uspace/drv/usbhid/conv.c

    r60a228f r9d9ffdd  
    4040#include "conv.h"
    4141
     42/**
     43 * Mapping between USB HID key codes (from HID Usage Tables) and corresponding
     44 * HelenOS key codes.
     45 */
    4246static int scanmap_simple[255] = {
    4347
     
    163167};
    164168
     169/**
     170 * Translate USB HID key codes (from HID Usage Tables) to generic key codes
     171 * recognized by HelenOS.
     172 *
     173 * @param scancode USB HID key code (from HID Usage Tables).
     174 *
     175 * @retval HelenOS key code corresponding to the given USB HID key code.
     176 */
    165177unsigned int usbhid_parse_scancode(int scancode)
    166178{
  • uspace/drv/usbhid/descdump.c

    r60a228f r9d9ffdd  
    4444#define BYTES_PER_LINE 12
    4545
     46/**
     47 * Dumps the given buffer in hexadecimal format to standard output.
     48 *
     49 * @param msg Message to print before the buffer.
     50 * @param buffer Buffer to print.
     51 * @param length Size of the buffer in bytes.
     52 */
    4653static void dump_buffer(const char *msg, const uint8_t *buffer, size_t length)
    4754{
     
    6269#define INDENT "  "
    6370
     71/**
     72 * Print standard configuration descriptor to standard output.
     73 *
     74 * @param index Index of the descriptor.
     75 * @param d Standard configuration descriptor to print.
     76 */
    6477void dump_standard_configuration_descriptor(
    6578    int index, const usb_standard_configuration_descriptor_t *d)
     
    8497}
    8598
     99/**
     100 * Print standard interface descriptor to standard output.
     101 *
     102 * @param d Standard interface descriptor to print.
     103 */
    86104void dump_standard_interface_descriptor(
    87105    const usb_standard_interface_descriptor_t *d)
     
    99117}
    100118
     119/**
     120 * Print standard endpoint descriptor to standard output.
     121 *
     122 * @param d Standard endpoint descriptor to print.
     123 */
    101124void dump_standard_endpoint_descriptor(
    102125    const usb_standard_endpoint_descriptor_t *d)
     
    126149}
    127150
     151/**
     152 * Print standard HID descriptor to standard output.
     153 *
     154 * @param d Standard HID descriptor to print.
     155 */
    128156void dump_standard_hid_descriptor_header(
    129157    const usb_standard_hid_descriptor_t *d)
     
    139167}
    140168
     169/**
     170 * Print HID class-specific descriptor header (type and length) to standard
     171 * output.
     172 *
     173 * @param d HID class-specific descriptor header to print.
     174 */
    141175void dump_standard_hid_class_descriptor_info(
    142176    const usb_standard_hid_class_descriptor_info_t *d)
     
    146180}
    147181
     182/**
     183 * Print HID class-specific descriptor (without the header) to standard output.
     184 *
     185 * @param index Index of the descriptor.
     186 * @param type Type of the HID class-specific descriptor (Report or Physical).
     187 * @param d HID class descriptor to print.
     188 * @param size Size of the descriptor in bytes.
     189 */
    148190void dump_hid_class_descriptor(int index, uint8_t type,
    149191    const uint8_t *d, size_t size )
  • uspace/drv/usbhid/hiddev.c

    r60a228f r9d9ffdd  
    5353/* Non-API functions                                                          */
    5454/*----------------------------------------------------------------------------*/
    55 
     55/**
     56 * Retreives HID Report descriptor from the device.
     57 *
     58 * This function first parses the HID descriptor from the Interface descriptor
     59 * to get the size of the Report descriptor and then requests the Report
     60 * descriptor from the device.
     61 *
     62 * @param hid_dev HID device structure.
     63 * @param config_desc Full configuration descriptor (including all nested
     64 *                    descriptors).
     65 * @param config_desc_size Size of the full configuration descriptor (in bytes).
     66 * @param iface_desc Pointer to the interface descriptor inside the full
     67 *                   configuration descriptor (@a config_desc) for the interface
     68 *                   assigned with this device (@a hid_dev).
     69 *
     70 * @retval EOK if successful.
     71 * @retval ENOENT if no HID descriptor could be found.
     72 * @retval EINVAL if the HID descriptor  or HID report descriptor have different
     73 *                size than expected.
     74 * @retval ENOMEM if some allocation failed.
     75 * @return Other value inherited from function usb_request_get_descriptor().
     76 *
     77 * @sa usb_request_get_descriptor()
     78 */
    5679static int usbhid_dev_get_report_descriptor(usbhid_dev_t *hid_dev,
    5780    uint8_t *config_desc, size_t config_desc_size, uint8_t *iface_desc)
     
    135158        }
    136159       
     160        hid_dev->report_desc_size = length;
     161       
    137162        usb_log_debug("Done.\n");
    138163       
     
    141166
    142167/*----------------------------------------------------------------------------*/
    143 
     168/**
     169 * Retreives descriptors from the device, initializes pipes and stores
     170 * important information from descriptors.
     171 *
     172 * Initializes the polling pipe described by the given endpoint description
     173 * (@a poll_ep_desc).
     174 *
     175 * Information retreived from descriptors and stored in the HID device structure:
     176 *    - Assigned interface number (the interface controlled by this instance of
     177 *                                 the driver)
     178 *    - Polling interval (from the interface descriptor)
     179 *    - Report descriptor
     180 *
     181 * @param hid_dev HID device structure to be initialized.
     182 * @param poll_ep_desc Description of the polling (Interrupt In) endpoint
     183 *                     that has to be present in the device in order to
     184 *                     successfuly initialize the structure.
     185 *
     186 * @sa usb_endpoint_pipe_initialize_from_configuration(),
     187 *     usbhid_dev_get_report_descriptor()
     188 */
    144189static int usbhid_dev_process_descriptors(usbhid_dev_t *hid_dev,
    145190    usb_endpoint_description_t *poll_ep_desc)
     
    149194        usb_log_info("Processing descriptors...\n");
    150195       
    151         // get the first configuration descriptor
    152         usb_standard_configuration_descriptor_t config_desc;
    153        
    154196        int rc;
    155         rc = usb_request_get_bare_configuration_descriptor(&hid_dev->ctrl_pipe,
    156             0, &config_desc);
    157        
    158         if (rc != EOK) {
    159                 usb_log_error("Failed to get bare config descriptor: %s.\n",
     197
     198        uint8_t *descriptors = NULL;
     199        size_t descriptors_size;
     200        rc = usb_request_get_full_configuration_descriptor_alloc(
     201            &hid_dev->ctrl_pipe, 0, (void **) &descriptors, &descriptors_size);
     202        if (rc != EOK) {
     203                usb_log_error("Failed to retrieve config descriptor: %s.\n",
    160204                    str_error(rc));
    161205                return rc;
    162         }
    163        
    164         // prepare space for all underlying descriptors
    165         uint8_t *descriptors = (uint8_t *)malloc(config_desc.total_length);
    166         if (descriptors == NULL) {
    167                 usb_log_error("No memory!.\n");
    168                 return ENOMEM;
    169         }
    170        
    171         size_t transferred = 0;
    172         // get full configuration descriptor
    173         rc = usb_request_get_full_configuration_descriptor(&hid_dev->ctrl_pipe,
    174             0, descriptors, config_desc.total_length, &transferred);
    175        
    176         if (rc != EOK) {
    177                 usb_log_error("Failed to get full config descriptor: %s.\n",
    178                     str_error(rc));
    179                 free(descriptors);
    180                 return rc;
    181         }
    182        
    183         if (transferred != config_desc.total_length) {
    184                 usb_log_error("Configuration descriptor has wrong size (%u, "
    185                     "expected %u).\n", transferred, config_desc.total_length);
    186                 free(descriptors);
    187                 return ELIMIT;
    188206        }
    189207       
     
    201219       
    202220        rc = usb_endpoint_pipe_initialize_from_configuration(
    203             endpoint_mapping, 1, descriptors, config_desc.total_length,
     221            endpoint_mapping, 1, descriptors, descriptors_size,
    204222            &hid_dev->wire);
    205223       
     
    233251        assert(endpoint_mapping[0].interface != NULL);
    234252       
    235         rc = usbhid_dev_get_report_descriptor(hid_dev, descriptors, transferred,
     253        /*
     254         * Save polling interval
     255         */
     256        hid_dev->poll_interval = endpoint_mapping[0].descriptor->poll_interval;
     257        assert(hid_dev->poll_interval > 0);
     258       
     259        rc = usbhid_dev_get_report_descriptor(hid_dev,
     260            descriptors, descriptors_size,
    236261            (uint8_t *)endpoint_mapping[0].interface);
    237262       
     
    239264       
    240265        if (rc != EOK) {
    241                 usb_log_warning("Problem with parsing Report descriptor: %s.\n",
     266                usb_log_warning("Problem with getting Report descriptor: %s.\n",
    242267                    str_error(rc));
    243268                return rc;
    244269        }
     270       
     271        rc = usb_hid_parse_report_descriptor(hid_dev->parser,
     272            hid_dev->report_desc, hid_dev->report_desc_size);
     273        if (rc != EOK) {
     274                usb_log_warning("Problem parsing Report descriptor: %s.\n",
     275                    str_error(rc));
     276                return rc;
     277        }
     278       
     279        usb_hid_descriptor_print(hid_dev->parser);
    245280       
    246281        return EOK;
     
    250285/* API functions                                                              */
    251286/*----------------------------------------------------------------------------*/
    252 
     287/**
     288 * Creates new uninitialized HID device structure.
     289 *
     290 * @return Pointer to the new HID device structure, or NULL if an error occured.
     291 */
    253292usbhid_dev_t *usbhid_dev_new(void)
    254293{
     
    263302        memset(dev, 0, sizeof(usbhid_dev_t));
    264303       
     304        dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(
     305            usb_hid_report_parser_t)));
     306        if (dev->parser == NULL) {
     307                usb_log_fatal("No memory!\n");
     308                free(dev);
     309                return NULL;
     310        }
     311       
    265312        dev->initialized = 0;
    266313       
     
    269316
    270317/*----------------------------------------------------------------------------*/
    271 
     318/**
     319 * Properly destroys the HID device structure.
     320 *
     321 * @note Currently does not clean-up the used pipes, as there are no functions
     322 *       offering such functionality.
     323 *
     324 * @param hid_dev Pointer to the structure to be destroyed.
     325 */
    272326void usbhid_dev_free(usbhid_dev_t **hid_dev)
    273327{
     
    292346
    293347/*----------------------------------------------------------------------------*/
    294 
     348/**
     349 * Initializes HID device structure.
     350 *
     351 * @param hid_dev HID device structure to be initialized.
     352 * @param dev DDF device representing the HID device.
     353 * @param poll_ep_desc Description of the polling (Interrupt In) endpoint
     354 *                     that has to be present in the device in order to
     355 *                     successfuly initialize the structure.
     356 *
     357 * @retval EOK if successful.
     358 * @retval EINVAL if some argument is missing.
     359 * @return Other value inherited from one of functions
     360 *         usb_device_connection_initialize_from_device(),
     361 *         usb_endpoint_pipe_initialize_default_control(),
     362 *         usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),
     363 *         usbhid_dev_process_descriptors().
     364 *
     365 * @sa usbhid_dev_process_descriptors()
     366 */
    295367int usbhid_dev_init(usbhid_dev_t *hid_dev, ddf_dev_t *dev,
    296368    usb_endpoint_description_t *poll_ep_desc)
     
    339411                return rc;
    340412        }
     413       
     414        /*
     415         * Initialize the report parser.
     416         */
     417        rc = usb_hid_parser_init(hid_dev->parser);
     418        if (rc != EOK) {
     419                usb_log_error("Failed to initialize report parser.\n");
     420                return rc;
     421        }
    341422
    342423        /*
    343424         * Get descriptors, parse descriptors and save endpoints.
    344425         */
    345         usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
     426        rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
     427        if (rc != EOK) {
     428                usb_log_error("Failed to start session on the control pipe: %s"
     429                    ".\n", str_error(rc));
     430                return rc;
     431        }
    346432       
    347433        rc = usbhid_dev_process_descriptors(hid_dev, poll_ep_desc);
    348        
    349         usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
    350         if (rc != EOK) {
     434        if (rc != EOK) {
     435                /* TODO: end session?? */
    351436                usb_log_error("Failed to process descriptors: %s.\n",
    352437                    str_error(rc));
     
    354439        }
    355440       
     441        rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
     442        if (rc != EOK) {
     443                usb_log_warning("Failed to start session on the control pipe: "
     444                    "%s.\n", str_error(rc));
     445                return rc;
     446        }
     447       
    356448        hid_dev->initialized = 1;
    357449        usb_log_info("HID device structure initialized.\n");
  • uspace/drv/usbhid/hiddev.h

    r60a228f r9d9ffdd  
    4848
    4949/**
    50  * @brief USB/HID device type.
     50 * USB/HID device type.
     51 *
     52 * Holds a reference to DDF device structure, and HID-specific data, such
     53 * as information about used pipes (one Control pipe and one Interrupt In pipe),
     54 * polling interval, assigned interface number, Report descriptor and a
     55 * reference to the Report parser used to parse incoming reports and composing
     56 * outgoing reports.
    5157 */
    5258typedef struct {
     59        /** DDF device representing the controlled HID device. */
    5360        ddf_dev_t *device;
    5461
     62        /** Physical connection to the device. */
    5563        usb_device_connection_t wire;
     64        /** USB pipe corresponding to the default Control endpoint. */
    5665        usb_endpoint_pipe_t ctrl_pipe;
     66        /** USB pipe corresponding to the Interrupt In (polling) pipe. */
    5767        usb_endpoint_pipe_t poll_pipe;
    5868       
     69        /** Polling interval retreived from the Interface descriptor. */
     70        short poll_interval;
     71       
     72        /** Interface number assigned to this device. */
    5973        uint16_t iface;
    6074       
     75        /** Report descriptor. */
    6176        uint8_t *report_desc;
     77
     78        size_t report_desc_size;
     79
     80        /** HID Report parser. */
    6281        usb_hid_report_parser_t *parser;
    6382       
     83        /** State of the structure (for checking before use). */
    6484        int initialized;
    6585} usbhid_dev_t;
  • uspace/drv/usbhid/hidreq.c

    r60a228f r9d9ffdd  
    4646
    4747/*----------------------------------------------------------------------------*/
    48 
     48/**
     49 * Send Set Report request to the HID device.
     50 *
     51 * @param hid_dev HID device to send the request to.
     52 * @param type Type of the report.
     53 * @param buffer Report data.
     54 * @param buf_size Report data size (in bytes).
     55 *
     56 * @retval EOK if successful.
     57 * @retval EINVAL if no HID device is given.
     58 * @return Other value inherited from one of functions
     59 *         usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),
     60 *         usb_control_request_set().
     61 */
    4962int usbhid_req_set_report(usbhid_dev_t *hid_dev,
    5063    usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size)
     
    6982                return sess_rc;
    7083        }
     84       
     85        uint16_t value = 0;
     86        value |= (type << 8);
    7187
    7288        usb_log_debug("Sending Set_Report request to the device.\n");
     
    7490        rc = usb_control_request_set(&hid_dev->ctrl_pipe,
    7591            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
    76             USB_HIDREQ_SET_REPORT, type, hid_dev->iface, buffer, buf_size);
    77 
    78         sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
    79 
    80         if (rc != EOK) {
    81                 usb_log_warning("Error sending output report to the keyboard: "
    82                     "%s.\n", str_error(rc));
    83                 return rc;
    84         }
    85 
    86         if (sess_rc != EOK) {
    87                 usb_log_warning("Error closing session: %s.\n",
    88                     str_error(sess_rc));
    89                 return sess_rc;
    90         }
    91        
    92         return EOK;
    93 }
    94 
    95 /*----------------------------------------------------------------------------*/
    96 
     92            USB_HIDREQ_SET_REPORT, value, hid_dev->iface, buffer, buf_size);
     93
     94        sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
     95
     96        if (rc != EOK) {
     97                usb_log_warning("Error sending output report to the keyboard: "
     98                    "%s.\n", str_error(rc));
     99                return rc;
     100        }
     101
     102        if (sess_rc != EOK) {
     103                usb_log_warning("Error closing session: %s.\n",
     104                    str_error(sess_rc));
     105                return sess_rc;
     106        }
     107       
     108        return EOK;
     109}
     110
     111/*----------------------------------------------------------------------------*/
     112/**
     113 * Send Set Protocol request to the HID device.
     114 *
     115 * @param hid_dev HID device to send the request to.
     116 * @param protocol Protocol to set.
     117 *
     118 * @retval EOK if successful.
     119 * @retval EINVAL if no HID device is given.
     120 * @return Other value inherited from one of functions
     121 *         usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),
     122 *         usb_control_request_set().
     123 */
    97124int usbhid_req_set_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t protocol)
    98125{
     
    142169
    143170/*----------------------------------------------------------------------------*/
     171/**
     172 * Send Set Idle request to the HID device.
     173 *
     174 * @param hid_dev HID device to send the request to.
     175 * @param duration Duration value (is multiplicated by 4 by the device to
     176 *                 get real duration in miliseconds).
     177 *
     178 * @retval EOK if successful.
     179 * @retval EINVAL if no HID device is given.
     180 * @return Other value inherited from one of functions
     181 *         usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),
     182 *         usb_control_request_set().
     183 */
     184int usbhid_req_set_idle(usbhid_dev_t *hid_dev, uint8_t duration)
     185{
     186        if (hid_dev == NULL) {
     187                usb_log_error("usbhid_req_set_idle(): no HID device "
     188                    "structure given.\n");
     189                return EINVAL;
     190        }
     191       
     192        /*
     193         * No need for checking other parameters, as they are checked in
     194         * the called function (usb_control_request_set()).
     195         */
     196       
     197        int rc, sess_rc;
     198       
     199        sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
     200        if (sess_rc != EOK) {
     201                usb_log_warning("Failed to start a session: %s.\n",
     202                    str_error(sess_rc));
     203                return sess_rc;
     204        }
     205
     206        usb_log_debug("Sending Set_Idle request to the device ("
     207            "duration: %u, iface: %d).\n", duration, hid_dev->iface);
     208       
     209        uint16_t value = duration << 8;
     210       
     211        rc = usb_control_request_set(&hid_dev->ctrl_pipe,
     212            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
     213            USB_HIDREQ_SET_IDLE, value, hid_dev->iface, NULL, 0);
     214
     215        sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
     216
     217        if (rc != EOK) {
     218                usb_log_warning("Error sending output report to the keyboard: "
     219                    "%s.\n", str_error(rc));
     220                return rc;
     221        }
     222
     223        if (sess_rc != EOK) {
     224                usb_log_warning("Error closing session: %s.\n",
     225                    str_error(sess_rc));
     226                return sess_rc;
     227        }
     228       
     229        return EOK;
     230}
     231
     232/*----------------------------------------------------------------------------*/
     233/**
     234 * Send Get Report request to the HID device.
     235 *
     236 * @param[in] hid_dev HID device to send the request to.
     237 * @param[in] type Type of the report.
     238 * @param[in][out] buffer Buffer for the report data.
     239 * @param[in] buf_size Size of the buffer (in bytes).
     240 * @param[out] actual_size Actual size of report received from the device
     241 *                         (in bytes).
     242 *
     243 * @retval EOK if successful.
     244 * @retval EINVAL if no HID device is given.
     245 * @return Other value inherited from one of functions
     246 *         usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),
     247 *         usb_control_request_set().
     248 */
     249int usbhid_req_get_report(usbhid_dev_t *hid_dev, usb_hid_report_type_t type,
     250    uint8_t *buffer, size_t buf_size, size_t *actual_size)
     251{
     252        if (hid_dev == NULL) {
     253                usb_log_error("usbhid_req_set_report(): no HID device structure"
     254                    " given.\n");
     255                return EINVAL;
     256        }
     257       
     258        /*
     259         * No need for checking other parameters, as they are checked in
     260         * the called function (usb_control_request_set()).
     261         */
     262       
     263        int rc, sess_rc;
     264       
     265        sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
     266        if (sess_rc != EOK) {
     267                usb_log_warning("Failed to start a session: %s.\n",
     268                    str_error(sess_rc));
     269                return sess_rc;
     270        }
     271
     272        uint16_t value = 0;
     273        value |= (type << 8);
     274       
     275        usb_log_debug("Sending Get_Report request to the device.\n");
     276       
     277        rc = usb_control_request_get(&hid_dev->ctrl_pipe,
     278            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
     279            USB_HIDREQ_GET_REPORT, value, hid_dev->iface, buffer, buf_size,
     280            actual_size);
     281
     282        sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
     283
     284        if (rc != EOK) {
     285                usb_log_warning("Error sending output report to the keyboard: "
     286                    "%s.\n", str_error(rc));
     287                return rc;
     288        }
     289
     290        if (sess_rc != EOK) {
     291                usb_log_warning("Error closing session: %s.\n",
     292                    str_error(sess_rc));
     293                return sess_rc;
     294        }
     295       
     296        return EOK;
     297}
     298
     299/*----------------------------------------------------------------------------*/
     300/**
     301 * Send Get Protocol request to the HID device.
     302 *
     303 * @param[in] hid_dev HID device to send the request to.
     304 * @param[out] protocol Current protocol of the device.
     305 *
     306 * @retval EOK if successful.
     307 * @retval EINVAL if no HID device is given.
     308 * @return Other value inherited from one of functions
     309 *         usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),
     310 *         usb_control_request_set().
     311 */
     312int usbhid_req_get_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t *protocol)
     313{
     314        if (hid_dev == NULL) {
     315                usb_log_error("usbhid_req_set_protocol(): no HID device "
     316                    "structure given.\n");
     317                return EINVAL;
     318        }
     319       
     320        /*
     321         * No need for checking other parameters, as they are checked in
     322         * the called function (usb_control_request_set()).
     323         */
     324       
     325        int rc, sess_rc;
     326       
     327        sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
     328        if (sess_rc != EOK) {
     329                usb_log_warning("Failed to start a session: %s.\n",
     330                    str_error(sess_rc));
     331                return sess_rc;
     332        }
     333
     334        usb_log_debug("Sending Get_Protocol request to the device ("
     335            "iface: %d).\n", hid_dev->iface);
     336       
     337        uint8_t buffer[1];
     338        size_t actual_size = 0;
     339       
     340        rc = usb_control_request_get(&hid_dev->ctrl_pipe,
     341            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
     342            USB_HIDREQ_GET_PROTOCOL, 0, hid_dev->iface, buffer, 1, &actual_size);
     343
     344        sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
     345
     346        if (rc != EOK) {
     347                usb_log_warning("Error sending output report to the keyboard: "
     348                    "%s.\n", str_error(rc));
     349                return rc;
     350        }
     351
     352        if (sess_rc != EOK) {
     353                usb_log_warning("Error closing session: %s.\n",
     354                    str_error(sess_rc));
     355                return sess_rc;
     356        }
     357       
     358        if (actual_size != 1) {
     359                usb_log_warning("Wrong data size: %zu, expected: 1.\n",
     360                        actual_size);
     361                return ELIMIT;
     362        }
     363       
     364        *protocol = buffer[0];
     365       
     366        return EOK;
     367}
     368
     369/*----------------------------------------------------------------------------*/
     370/**
     371 * Send Get Idle request to the HID device.
     372 *
     373 * @param[in] hid_dev HID device to send the request to.
     374 * @param[out] duration Duration value (multiplicate by 4 to get real duration
     375 *                      in miliseconds).
     376 *
     377 * @retval EOK if successful.
     378 * @retval EINVAL if no HID device is given.
     379 * @return Other value inherited from one of functions
     380 *         usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),
     381 *         usb_control_request_set().
     382 */
     383int usbhid_req_get_idle(usbhid_dev_t *hid_dev, uint8_t *duration)
     384{
     385        if (hid_dev == NULL) {
     386                usb_log_error("usbhid_req_set_idle(): no HID device "
     387                    "structure given.\n");
     388                return EINVAL;
     389        }
     390       
     391        /*
     392         * No need for checking other parameters, as they are checked in
     393         * the called function (usb_control_request_set()).
     394         */
     395       
     396        int rc, sess_rc;
     397       
     398        sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
     399        if (sess_rc != EOK) {
     400                usb_log_warning("Failed to start a session: %s.\n",
     401                    str_error(sess_rc));
     402                return sess_rc;
     403        }
     404
     405        usb_log_debug("Sending Get_Idle request to the device ("
     406            "iface: %d).\n", hid_dev->iface);
     407       
     408        uint16_t value = 0;
     409        uint8_t buffer[1];
     410        size_t actual_size = 0;
     411       
     412        rc = usb_control_request_get(&hid_dev->ctrl_pipe,
     413            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
     414            USB_HIDREQ_GET_IDLE, value, hid_dev->iface, buffer, 1,
     415            &actual_size);
     416
     417        sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
     418
     419        if (rc != EOK) {
     420                usb_log_warning("Error sending output report to the keyboard: "
     421                    "%s.\n", str_error(rc));
     422                return rc;
     423        }
     424
     425        if (sess_rc != EOK) {
     426                usb_log_warning("Error closing session: %s.\n",
     427                    str_error(sess_rc));
     428                return sess_rc;
     429        }
     430       
     431        if (actual_size != 1) {
     432                usb_log_warning("Wrong data size: %zu, expected: 1.\n",
     433                        actual_size);
     434                return ELIMIT;
     435        }
     436       
     437        *duration = buffer[0];
     438       
     439        return EOK;
     440}
     441
     442/*----------------------------------------------------------------------------*/
    144443
    145444/**
  • uspace/drv/usbhid/hidreq.h

    r60a228f r9d9ffdd  
    5050int usbhid_req_set_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t protocol);
    5151
     52int usbhid_req_set_idle(usbhid_dev_t *hid_dev, uint8_t duration);
     53
     54int usbhid_req_get_report(usbhid_dev_t *hid_dev, usb_hid_report_type_t type,
     55    uint8_t *buffer, size_t buf_size, size_t *actual_size);
     56
     57int usbhid_req_get_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t *protocol);
     58
     59int usbhid_req_get_idle(usbhid_dev_t *hid_dev, uint8_t *duration);
     60
    5261/*----------------------------------------------------------------------------*/
    5362
  • uspace/drv/usbhid/kbddev.c

    r60a228f r9d9ffdd  
    3737#include <errno.h>
    3838#include <str_error.h>
    39 #include <fibril.h>
     39#include <stdio.h>
    4040
    4141#include <io/keycode.h>
    4242#include <ipc/kbd.h>
    4343#include <async.h>
     44#include <fibril.h>
     45#include <fibril_synch.h>
    4446
    4547#include <usb/usb.h>
     
    5557#include "layout.h"
    5658#include "conv.h"
    57 
    58 /*----------------------------------------------------------------------------*/
    59 
     59#include "kbdrepeat.h"
     60
     61/*----------------------------------------------------------------------------*/
     62/** Default modifiers when the keyboard is initialized. */
    6063static const unsigned DEFAULT_ACTIVE_MODS = KM_NUM_LOCK;
     64
     65/** Boot protocol report size (key part). */
    6166static const size_t BOOTP_REPORT_SIZE = 6;
     67
     68/** Boot protocol total report size. */
    6269static const size_t BOOTP_BUFFER_SIZE = 8;
     70
     71/** Boot protocol output report size. */
    6372static const size_t BOOTP_BUFFER_OUT_SIZE = 1;
     73
     74/** Boot protocol error key code. */
     75static const uint8_t BOOTP_ERROR_ROLLOVER = 1;
     76
     77/** Default idle rate for keyboards. */
     78static const uint8_t IDLE_RATE = 0;
     79
     80/** Delay before a pressed key starts auto-repeating. */
     81static const unsigned int DEFAULT_DELAY_BEFORE_FIRST_REPEAT = 500 * 1000;
     82
     83/** Delay between two repeats of a pressed key when auto-repeating. */
     84static const unsigned int DEFAULT_REPEAT_DELAY = 50 * 1000;
    6485
    6586/** Keyboard polling endpoint description for boot protocol class. */
     
    79100#define NUM_LAYOUTS 3
    80101
     102/** Keyboard layout map. */
    81103static layout_op_t *layout[NUM_LAYOUTS] = {
    82104        &us_qwerty_op,
     
    90112/* Modifier constants                                                         */
    91113/*----------------------------------------------------------------------------*/
    92 
     114/** Mapping of USB modifier key codes to generic modifier key codes. */
    93115static const keycode_t usbhid_modifiers_keycodes[USB_HID_MOD_COUNT] = {
    94116        KC_LCTRL,         /* USB_HID_MOD_LCTRL */
     
    111133};
    112134
    113 /** Default handler for IPC methods not handled by DDF.
    114  *
    115  * @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.
    116143 * @param icallid Call id.
    117144 * @param icall Call data.
     
    144171/* Key processing functions                                                   */
    145172/*----------------------------------------------------------------------------*/
    146 
     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 */
    147185static void usbhid_kbd_set_led(usbhid_kbd_t *kbd_dev)
    148186{
    149187        uint8_t buffer[BOOTP_BUFFER_OUT_SIZE];
    150188        int rc= 0;
    151         unsigned i;
    152189       
    153190        memset(buffer, 0, BOOTP_BUFFER_OUT_SIZE);
     
    177214        }
    178215       
    179         // TODO: REFACTOR!!!
    180        
    181         usb_log_debug("Output report buffer: ");
    182         for (i = 0; i < BOOTP_BUFFER_OUT_SIZE; ++i) {
    183                 usb_log_debug("0x%x ", buffer[i]);
    184         }
    185         usb_log_debug("\n");
    186        
    187         uint16_t value = 0;
    188         value |= (USB_HID_REPORT_TYPE_OUTPUT << 8);
    189 
     216        usb_log_debug("Output report buffer: %s\n",
     217            usb_debug_str_buffer(buffer, BOOTP_BUFFER_OUT_SIZE, 0));
     218       
    190219        assert(kbd_dev->hid_dev != NULL);
    191220        assert(kbd_dev->hid_dev->initialized);
    192         usbhid_req_set_report(kbd_dev->hid_dev, value, buffer,
    193             BOOTP_BUFFER_OUT_SIZE);
    194 }
    195 
    196 /*----------------------------------------------------------------------------*/
    197 
    198 static void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type,
    199     unsigned int key)
     221        usbhid_req_set_report(kbd_dev->hid_dev, USB_HID_REPORT_TYPE_OUTPUT,
     222            buffer, BOOTP_BUFFER_OUT_SIZE);
     223}
     224
     225/*----------------------------------------------------------------------------*/
     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 */
     242void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key)
    200243{
    201244        console_event_t ev;
    202245        unsigned mod_mask;
    203246
    204         // 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         */
    205253        switch (key) {
    206254        case KC_LCTRL: mod_mask = KM_LCTRL; break;
     
    228276
    229277        if (mod_mask != 0) {
    230                 usb_log_debug2("\n\nChanging mods and lock keys\n");
    231                 usb_log_debug2("\nmods before: 0x%x\n", kbd_dev->mods);
    232                 usb_log_debug2("\nLock keys before:0x%x\n\n",
    233                     kbd_dev->lock_keys);
    234                
    235278                if (type == KEY_PRESS) {
    236                         usb_log_debug2("\nKey pressed.\n");
    237279                        /*
    238280                         * Only change lock state on transition from released
     
    240282                         * up the lock state.
    241283                         */
     284                        unsigned int locks_old = kbd_dev->lock_keys;
     285                       
    242286                        kbd_dev->mods =
    243287                            kbd_dev->mods ^ (mod_mask & ~kbd_dev->lock_keys);
     
    245289
    246290                        /* Update keyboard lock indicator lights. */
    247                         usbhid_kbd_set_led(kbd_dev);
     291                        if (kbd_dev->lock_keys != locks_old) {
     292                                usbhid_kbd_set_led(kbd_dev);
     293                        }
    248294                } else {
    249                         usb_log_debug2("\nKey released.\n");
    250295                        kbd_dev->lock_keys = kbd_dev->lock_keys & ~mod_mask;
    251296                }
    252297        }
    253298
    254         usb_log_debug2("\n\nmods after: 0x%x\n", kbd_dev->mods);
    255         usb_log_debug2("\nLock keys after: 0x%x\n\n", kbd_dev->lock_keys);
    256        
    257299        if (key == KC_CAPS_LOCK || key == KC_NUM_LOCK || key == KC_SCROLL_LOCK) {
    258300                // do not send anything to the console, this is our business
     
    281323        ev.key = key;
    282324        ev.mods = kbd_dev->mods;
    283        
    284         if (ev.mods & KM_NUM_LOCK) {
    285                 usb_log_debug("\n\nNum Lock turned on.\n\n");
    286         }
    287325
    288326        ev.c = layout[active_layout]->parse_ev(&ev);
    289327
    290328        usb_log_debug2("Sending key %d to the console\n", ev.key);
    291         assert(kbd_dev->console_phone != -1);
     329        if (kbd_dev->console_phone < 0) {
     330                usb_log_warning(
     331                    "Connection to console not ready, key discarded.\n");
     332                return;
     333        }
    292334       
    293335        async_msg_4(kbd_dev->console_phone, KBD_EVENT, ev.type, ev.key,
     
    296338
    297339/*----------------------------------------------------------------------------*/
    298 
     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 */
    299348static void usbhid_kbd_check_modifier_changes(usbhid_kbd_t *kbd_dev,
    300349    uint8_t modifiers)
     
    332381
    333382/*----------------------------------------------------------------------------*/
    334 
     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 */
    335398static void usbhid_kbd_check_key_changes(usbhid_kbd_t *kbd_dev,
    336     const uint8_t *key_codes)
    337 {
    338         // TODO: phantom state!!
    339        
     399    const uint8_t *key_codes, size_t count)
     400{
    340401        unsigned int key;
    341402        unsigned int i, j;
    342403       
    343         // TODO: quite dummy right now, think of better implementation
     404        /*
     405         * First of all, check if the kbd have reported phantom state.
     406         */
     407        i = 0;
     408        // all fields should report Error Rollover
     409        while (i < count &&
     410            key_codes[i] == BOOTP_ERROR_ROLLOVER) {
     411                ++i;
     412        }
     413        if (i == count) {
     414                usb_log_debug("Phantom state occured.\n");
     415                // phantom state, do nothing
     416                return;
     417        }
     418       
     419        /* TODO: quite dummy right now, think of better implementation */
     420        assert(count == kbd_dev->key_count);
    344421       
    345422        /*
    346423         * 1) Key releases
    347424         */
    348         for (j = 0; j < kbd_dev->keycode_count; ++j) {
     425        for (j = 0; j < count; ++j) {
    349426                // try to find the old key in the new key list
    350427                i = 0;
    351                 while (i < kbd_dev->keycode_count
    352                     && key_codes[i] != kbd_dev->keycodes[j]) {
     428                while (i < kbd_dev->key_count
     429                    && key_codes[i] != kbd_dev->keys[j]) {
    353430                        ++i;
    354431                }
    355432               
    356                 if (i == kbd_dev->keycode_count) {
     433                if (i == count) {
    357434                        // not found, i.e. the key was released
    358                         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);
    359437                        usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, key);
    360                         usb_log_debug2("\nKey released: %d\n", key);
     438                        usb_log_debug2("Key released: %d\n", key);
    361439                } else {
    362440                        // found, nothing happens
     
    367445         * 1) Key presses
    368446         */
    369         for (i = 0; i < kbd_dev->keycode_count; ++i) {
     447        for (i = 0; i < kbd_dev->key_count; ++i) {
    370448                // try to find the new key in the old key list
    371449                j = 0;
    372                 while (j < kbd_dev->keycode_count
    373                     && kbd_dev->keycodes[j] != key_codes[i]) {
     450                while (j < count && kbd_dev->keys[j] != key_codes[i]) {
    374451                        ++j;
    375452                }
    376453               
    377                 if (j == kbd_dev->keycode_count) {
     454                if (j == count) {
    378455                        // not found, i.e. new key pressed
    379456                        key = usbhid_parse_scancode(key_codes[i]);
    380                         usb_log_debug2("\nKey pressed: %d (keycode: %d)\n", key,
     457                        usb_log_debug2("Key pressed: %d (keycode: %d)\n", key,
    381458                            key_codes[i]);
    382459                        usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, key);
     460                        usbhid_kbd_repeat_start(kbd_dev, key);
    383461                } else {
    384462                        // found, nothing happens
     
    386464        }
    387465       
    388         memcpy(kbd_dev->keycodes, key_codes, kbd_dev->keycode_count);
    389        
    390         usb_log_debug2("\nNew stored keycodes: ");
    391         for (i = 0; i < kbd_dev->keycode_count; ++i) {
    392                 usb_log_debug2("%d ", kbd_dev->keycodes[i]);
    393         }
     466        memcpy(kbd_dev->keys, key_codes, count);
     467
     468        usb_log_debug("New stored keycodes: %s\n",
     469            usb_debug_str_buffer(kbd_dev->keys, kbd_dev->key_count, 0));
    394470}
    395471
     
    397473/* Callbacks for parser                                                       */
    398474/*----------------------------------------------------------------------------*/
    399 
     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 */
    400491static void usbhid_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
    401492    uint8_t modifiers, void *arg)
     
    406497                return;
    407498        }
    408 
    409         usb_log_debug2("Got keys from parser: ");
    410         unsigned i;
    411         for (i = 0; i < count; ++i) {
    412                 usb_log_debug2("%d ", key_codes[i]);
    413         }
    414         usb_log_debug2("\n");
    415499       
    416500        usbhid_kbd_t *kbd_dev = (usbhid_kbd_t *)arg;
    417501        assert(kbd_dev != NULL);
    418        
    419         if (count != kbd_dev->keycode_count) {
     502
     503        usb_log_debug("Got keys from parser: %s\n",
     504            usb_debug_str_buffer(key_codes, count, 0));
     505       
     506        if (count != kbd_dev->key_count) {
    420507                usb_log_warning("Number of received keycodes (%d) differs from"
    421                     " expected number (%d).\n", count, kbd_dev->keycode_count);
     508                    " expected number (%d).\n", count, kbd_dev->key_count);
    422509                return;
    423510        }
    424511       
    425512        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);
    427514}
    428515
     
    430517/* General kbd functions                                                      */
    431518/*----------------------------------------------------------------------------*/
    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 */
    433534static void usbhid_kbd_process_data(usbhid_kbd_t *kbd_dev,
    434535                                    uint8_t *buffer, size_t actual_size)
    435536{
     537        assert(kbd_dev->initialized);
     538        assert(kbd_dev->hid_dev->parser != NULL);
     539       
    436540        usb_hid_report_in_callbacks_t *callbacks =
    437541            (usb_hid_report_in_callbacks_t *)malloc(
     
    440544        callbacks->keyboard = usbhid_kbd_process_keycodes;
    441545
    442         //usb_hid_parse_report(kbd_dev->parser, buffer, actual_size, callbacks,
    443         //    NULL);
    444         /*usb_log_debug2("Calling usb_hid_boot_keyboard_input_report() with size"
    445             " %zu\n", actual_size);*/
    446         //dump_buffer("bufffer: ", buffer, actual_size);
    447        
    448         int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size,
    449             callbacks, kbd_dev);
     546        usb_log_debug("Calling usb_hid_parse_report() with "
     547            "buffer %s\n", usb_debug_str_buffer(buffer, actual_size, 0));
     548       
     549//      int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size,
     550//          callbacks, kbd_dev);
     551        int rc = usb_hid_parse_report(kbd_dev->hid_dev->parser, buffer,
     552            actual_size, callbacks, kbd_dev);
    450553       
    451554        if (rc != EOK) {
     
    458561/* HID/KBD structure manipulation                                             */
    459562/*----------------------------------------------------------------------------*/
    460 
     563/**
     564 * Creates a new USB/HID keyboard structure.
     565 *
     566 * The structure returned by this function is not initialized. Use
     567 * usbhid_kbd_init() to initialize it prior to polling.
     568 *
     569 * @return New uninitialized structure for representing a USB/HID keyboard or
     570 *         NULL if not successful (memory error).
     571 */
    461572static usbhid_kbd_t *usbhid_kbd_new(void)
    462573{
     
    484595
    485596/*----------------------------------------------------------------------------*/
    486 
     597/**
     598 * Properly destroys the USB/HID keyboard structure.
     599 *
     600 * @param kbd_dev Pointer to the structure to be destroyed.
     601 */
    487602static void usbhid_kbd_free(usbhid_kbd_t **kbd_dev)
    488603{
     
    499614        }
    500615       
     616        if ((*kbd_dev)->repeat_mtx != NULL) {
     617                /* TODO: replace by some check and wait */
     618                assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
     619                free((*kbd_dev)->repeat_mtx);
     620        }
     621
    501622        free(*kbd_dev);
    502623        *kbd_dev = NULL;
     
    504625
    505626/*----------------------------------------------------------------------------*/
    506 
     627/**
     628 * Initialization of the USB/HID keyboard structure.
     629 *
     630 * This functions initializes required structures from the device's descriptors.
     631 *
     632 * During initialization, the keyboard is switched into boot protocol, the idle
     633 * rate is set to 0 (infinity), resulting in the keyboard only reporting event
     634 * when a key is pressed or released. Finally, the LED lights are turned on
     635 * according to the default setup of lock keys.
     636 *
     637 * @note By default, the keyboards is initialized with Num Lock turned on and
     638 *       other locks turned off.
     639 *
     640 * @param kbd_dev Keyboard device structure to be initialized.
     641 * @param dev DDF device structure of the keyboard.
     642 *
     643 * @retval EOK if successful.
     644 * @retval EINVAL if some parameter is not given.
     645 * @return Other value inherited from function usbhid_dev_init().
     646 */
    507647static int usbhid_kbd_init(usbhid_kbd_t *kbd_dev, ddf_dev_t *dev)
    508648{
     
    539679       
    540680        // save the size of the report (boot protocol report by default)
    541         kbd_dev->keycode_count = BOOTP_REPORT_SIZE;
    542         kbd_dev->keycodes = (uint8_t *)calloc(
    543             kbd_dev->keycode_count, sizeof(uint8_t));
    544        
    545         if (kbd_dev->keycodes == NULL) {
     681        kbd_dev->key_count = BOOTP_REPORT_SIZE;
     682        kbd_dev->keys = (uint8_t *)calloc(
     683            kbd_dev->key_count, sizeof(uint8_t));
     684       
     685        if (kbd_dev->keys == NULL) {
    546686                usb_log_fatal("No memory!\n");
    547                 return rc;
     687                return ENOMEM;
    548688        }
    549689       
     
    552692        kbd_dev->lock_keys = 0;
    553693       
     694        kbd_dev->repeat.key_new = 0;
     695        kbd_dev->repeat.key_repeated = 0;
     696        kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
     697        kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
     698       
     699        kbd_dev->repeat_mtx = (fibril_mutex_t *)(
     700            malloc(sizeof(fibril_mutex_t)));
     701        if (kbd_dev->repeat_mtx == NULL) {
     702                usb_log_fatal("No memory!\n");
     703                free(kbd_dev->keys);
     704                return ENOMEM;
     705        }
     706       
     707        fibril_mutex_initialize(kbd_dev->repeat_mtx);
     708       
    554709        /*
    555710         * Set boot protocol.
    556711         * Set LEDs according to initial setup.
     712         * Set Idle rate
    557713         */
    558714        assert(kbd_dev->hid_dev != NULL);
    559715        assert(kbd_dev->hid_dev->initialized);
    560         usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT);
     716        //usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT);
    561717       
    562718        usbhid_kbd_set_led(kbd_dev);
     719       
     720        usbhid_req_set_idle(kbd_dev->hid_dev, IDLE_RATE);
    563721       
    564722        kbd_dev->initialized = 1;
     
    571729/* HID/KBD polling                                                            */
    572730/*----------------------------------------------------------------------------*/
    573 
     731/**
     732 * Main keyboard polling function.
     733 *
     734 * This function uses the Interrupt In pipe of the keyboard to poll for events.
     735 * The keyboard is initialized in a way that it reports only when a key is
     736 * pressed or released, so there is no actual need for any sleeping between
     737 * polls (see usbhid_kbd_try_add_device() or usbhid_kbd_init()).
     738 *
     739 * @param kbd_dev Initialized keyboard structure representing the device to
     740 *                poll.
     741 *
     742 * @sa usbhid_kbd_process_data()
     743 */
    574744static void usbhid_kbd_poll(usbhid_kbd_t *kbd_dev)
    575745{
     
    589759
    590760        while (true) {
    591                 async_usleep(1000 * 10);
    592 
    593761                sess_rc = usb_endpoint_pipe_start_session(
    594762                    &kbd_dev->hid_dev->poll_pipe);
     
    596764                        usb_log_warning("Failed to start a session: %s.\n",
    597765                            str_error(sess_rc));
    598                         continue;
     766                        break;
    599767                }
    600768
     
    608776                        usb_log_warning("Error polling the keyboard: %s.\n",
    609777                            str_error(rc));
    610                         continue;
     778                        break;
    611779                }
    612780
     
    614782                        usb_log_warning("Error closing session: %s.\n",
    615783                            str_error(sess_rc));
    616                         continue;
     784                        break;
    617785                }
    618786
     
    631799                usb_log_debug("Calling usbhid_kbd_process_data()\n");
    632800                usbhid_kbd_process_data(kbd_dev, buffer, actual_size);
    633         }
    634 
    635         // not reached
    636         assert(0);
    637 }
    638 
    639 /*----------------------------------------------------------------------------*/
    640 
     801               
     802                // disabled for now, no reason to sleep
     803                //async_usleep(kbd_dev->hid_dev->poll_interval);
     804        }
     805}
     806
     807/*----------------------------------------------------------------------------*/
     808/**
     809 * Function executed by the main driver fibril.
     810 *
     811 * Just starts polling the keyboard for events.
     812 *
     813 * @param arg Initialized keyboard device structure (of type usbhid_kbd_t)
     814 *            representing the device.
     815 *
     816 * @retval EOK if the fibril finished polling the device.
     817 * @retval EINVAL if no device was given in the argument.
     818 *
     819 * @sa usbhid_kbd_poll()
     820 *
     821 * @todo Change return value - only case when the fibril finishes is in case
     822 *       of some error, so the error should probably be propagated from function
     823 *       usbhid_kbd_poll() to here and up.
     824 */
    641825static int usbhid_kbd_fibril(void *arg)
    642826{
     
    660844/* API functions                                                              */
    661845/*----------------------------------------------------------------------------*/
    662 
     846/**
     847 * Function for adding a new device of type USB/HID/keyboard.
     848 *
     849 * This functions initializes required structures from the device's descriptors
     850 * and starts new fibril for polling the keyboard for events and another one for
     851 * handling auto-repeat of keys.
     852 *
     853 * During initialization, the keyboard is switched into boot protocol, the idle
     854 * rate is set to 0 (infinity), resulting in the keyboard only reporting event
     855 * when a key is pressed or released. Finally, the LED lights are turned on
     856 * according to the default setup of lock keys.
     857 *
     858 * @note By default, the keyboards is initialized with Num Lock turned on and
     859 *       other locks turned off.
     860 * @note Currently supports only boot-protocol keyboards.
     861 *
     862 * @param dev Device to add.
     863 *
     864 * @retval EOK if successful.
     865 * @retval ENOMEM if there
     866 * @return Other error code inherited from one of functions usbhid_kbd_init(),
     867 *         ddf_fun_bind() and ddf_fun_add_to_class().
     868 *
     869 * @sa usbhid_kbd_fibril(), usbhid_kbd_repeat_fibril()
     870 */
    663871int usbhid_kbd_try_add_device(ddf_dev_t *dev)
    664872{
     
    682890                    "structure.\n");
    683891                ddf_fun_destroy(kbd_fun);
    684                 return EINVAL;  // TODO: some other code??
     892                return ENOMEM;  // TODO: some other code??
    685893        }
    686894       
     
    731939        }
    732940        fibril_add_ready(fid);
     941       
     942        /*
     943         * Create new fibril for auto-repeat
     944         */
     945        fid = fibril_create(usbhid_kbd_repeat_fibril, kbd_dev);
     946        if (fid == 0) {
     947                usb_log_error("Failed to start fibril for KBD auto-repeat");
     948                return ENOMEM;
     949        }
     950        fibril_add_ready(fid);
    733951
    734952        (void)keyboard_ops;
  • uspace/drv/usbhid/kbddev.h

    r60a228f r9d9ffdd  
    3939#include <stdint.h>
    4040
     41#include <fibril_synch.h>
     42
    4143#include <usb/classes/hid.h>
     44#include <usb/classes/hidparser.h>
    4245#include <ddf/driver.h>
    4346#include <usb/pipes.h>
     
    4649
    4750/*----------------------------------------------------------------------------*/
     51/**
     52 * Structure for keeping information needed for auto-repeat of keys.
     53 */
     54typedef struct {
     55        /** Last pressed key. */
     56        unsigned int key_new;
     57        /** Key to be repeated. */
     58        unsigned int key_repeated;
     59        /** Delay before first repeat in microseconds. */
     60        unsigned int delay_before;
     61        /** Delay between repeats in microseconds. */
     62        unsigned int delay_between;
     63} usbhid_kbd_repeat_t;
    4864
    4965/**
    50  * @brief USB/HID keyboard device type.
     66 * USB/HID keyboard device type.
     67 *
     68 * Holds a reference to generic USB/HID device structure and keyboard-specific
     69 * data, such as currently pressed keys, modifiers and lock keys.
     70 *
     71 * Also holds a IPC phone to the console (since there is now no other way to
     72 * communicate with it).
     73 *
     74 * @note Storing active lock keys in this structure results in their setting
     75 *       being device-specific.
    5176 */
    5277typedef struct {
     78        /** Structure holding generic USB/HID device information. */
    5379        usbhid_dev_t *hid_dev;
    5480       
    55         uint8_t *keycodes;
    56         size_t keycode_count;
     81        /** Currently pressed keys (not translated to key codes). */
     82        uint8_t *keys;
     83        /** Count of stored keys (i.e. number of keys in the report). */
     84        size_t key_count;
     85        /** Currently pressed modifiers (bitmap). */
    5786        uint8_t modifiers;
    5887       
     88        /** Currently active modifiers including locks. Sent to the console. */
    5989        unsigned mods;
     90       
     91        /** Currently active lock keys. */
    6092        unsigned lock_keys;
    6193       
     94        /** IPC phone to the console device (for sending key events). */
    6295        int console_phone;
    6396       
     97        /** Information for auto-repeat of keys. */
     98        usbhid_kbd_repeat_t repeat;
     99       
     100        /** Mutex for accessing the information about auto-repeat. */
     101        fibril_mutex_t *repeat_mtx;
     102       
     103        /** State of the structure (for checking before use). */
    64104        int initialized;
    65105} usbhid_kbd_t;
     
    69109int usbhid_kbd_try_add_device(ddf_dev_t *dev);
    70110
     111void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key);
     112
    71113#endif /* USBHID_KBDDEV_H_ */
    72114
  • uspace/drv/usbhid/main.c

    r60a228f r9d9ffdd  
    4747
    4848/*----------------------------------------------------------------------------*/
    49 
     49/**
     50 * Callback for passing a new device to the driver.
     51 *
     52 * @note Currently, only boot-protocol keyboards are supported by this driver.
     53 *
     54 * @param dev Structure representing the new device.
     55 *
     56 * @retval EOK if successful.
     57 * @retval EREFUSED if the device is not supported.
     58 */
    5059static int usbhid_add_device(ddf_dev_t *dev)
    5160{
     
    8089int main(int argc, char *argv[])
    8190{
    82         usb_log_enable(USB_LOG_LEVEL_INFO, NAME);
     91        usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
    8392        return ddf_driver_main(&kbd_driver);
    8493}
  • uspace/drv/usbhid/usbhid.ma

    r60a228f r9d9ffdd  
    1 10 usb&class=hid
    2 10 usb&class=HID
     1100 usb&interface&class=HID&subclass=0x01&protocol=0x01
    3210 usb&interface&class=HID
    4 10 usb&hid
Note: See TracChangeset for help on using the changeset viewer.