Changeset 61257f4 in mainline for uspace/drv/usbhid/usbhid.c


Ignore:
Timestamp:
2011-04-07T20:19:24Z (13 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f8e8738
Parents:
fd9ba204
Message:

Initial implementation of general HID driver.

  • Should handle:
    • keyboard (most of functions from usbkbd driver), more-or-less works
    • mouse (not implemented yet)
    • generic HID device (just dummy polling callback now)
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/usbhid/usbhid.c

    rfd9ba204 r61257f4  
    3737#include <usb/debug.h>
    3838#include <usb/classes/classes.h>
     39#include <usb/classes/hid.h>
     40#include <usb/classes/hidparser.h>
     41#include <usb/classes/hidreport.h>
     42#include <errno.h>
    3943
    4044#include "usbhid.h"
    4145
    42 /*----------------------------------------------------------------------------*/
    43 
    44 /** HID device polling endpoint description. */
    45 static usb_endpoint_description_t poll_endpoint_description = {
     46#include "kbd/kbddev.h"
     47#include "generic/hidd.h"
     48
     49/*----------------------------------------------------------------------------*/
     50
     51/** Generic HID device polling endpoint description. */
     52//static usb_endpoint_description_t usb_hid_generic_poll_endpoint_description = {
     53//      .transfer_type = USB_TRANSFER_INTERRUPT,
     54//      .direction = USB_DIRECTION_IN,
     55//      .interface_class = USB_CLASS_HID,
     56//      .flags = 0
     57//};
     58
     59///** Keyboard polling endpoint description for boot protocol class. */
     60//static usb_endpoint_description_t ush_hid_kbd_poll_endpoint_description = {
     61//      .transfer_type = USB_TRANSFER_INTERRUPT,
     62//      .direction = USB_DIRECTION_IN,
     63//      .interface_class = USB_CLASS_HID,
     64//      .interface_subclass = USB_HID_SUBCLASS_BOOT,
     65//      .interface_protocol = USB_HID_PROTOCOL_KEYBOARD,
     66//      .flags = 0
     67//};
     68
     69/** Mouse polling endpoint description for boot protocol class. */
     70static usb_endpoint_description_t ush_hid_mouse_poll_endpoint_description = {
    4671        .transfer_type = USB_TRANSFER_INTERRUPT,
    4772        .direction = USB_DIRECTION_IN,
    4873        .interface_class = USB_CLASS_HID,
     74        .interface_subclass = USB_HID_SUBCLASS_BOOT,
     75        .interface_protocol = USB_HID_PROTOCOL_MOUSE,
    4976        .flags = 0
    5077};
     
    5380usb_endpoint_description_t
    5481    *usb_hid_endpoints[USB_HID_POLL_EP_COUNT + 1] = {
    55         &poll_endpoint_description,
     82        &ush_hid_kbd_poll_endpoint_description,
     83        &ush_hid_mouse_poll_endpoint_description,
     84        &usb_hid_generic_poll_endpoint_description,
    5685        NULL
    5786};
    5887
    59 /*----------------------------------------------------------------------------*/
    60 
    61 ddf_dev_ops_t hid_ops = {
    62         .default_handler = NULL
    63 };
    64 
    65 /*----------------------------------------------------------------------------*/
    66 
    67 bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
     88static const char *HID_MOUSE_FUN_NAME = "mouse";
     89static const char *HID_MOUSE_CLASS_NAME = "mouse";
     90
     91/*----------------------------------------------------------------------------*/
     92
     93usb_hid_dev_t *usb_hid_new(void)
     94{
     95        usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)calloc(1,
     96            sizeof(usb_hid_dev_t));
     97       
     98        if (hid_dev == NULL) {
     99                usb_log_fatal("No memory!\n");
     100                return NULL;
     101        }
     102       
     103        hid_dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(
     104            usb_hid_report_parser_t)));
     105        if (hid_dev->parser == NULL) {
     106                usb_log_fatal("No memory!\n");
     107                free(hid_dev);
     108                return NULL;
     109        }
     110       
     111        return hid_dev;
     112}
     113
     114/*----------------------------------------------------------------------------*/
     115
     116static bool usb_dummy_polling_callback(usb_device_t *dev, uint8_t *buffer,
    68117     size_t buffer_size, void *arg)
    69118{
    70         usb_debug_str_buffer(buffer, buffer_size, 0);
    71         return true;
    72 }
    73 
    74 /*----------------------------------------------------------------------------*/
    75 
    76 void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason,
    77      void *arg)
    78 {
    79        
     119        return false;
     120}
     121
     122/*----------------------------------------------------------------------------*/
     123
     124static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
     125{
     126        if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
     127                usb_log_debug("Found keyboard endpoint.\n");
     128               
     129                // save the pipe index and device type
     130                hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
     131                hid_dev->device_type = USB_HID_PROTOCOL_KEYBOARD;
     132               
     133                // set the polling callback
     134                hid_dev->poll_callback = usb_kbd_polling_callback;
     135
     136        } else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
     137                usb_log_debug("Found mouse endpoint.\n");
     138               
     139                // save the pipe index and device type
     140                hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
     141                hid_dev->device_type = USB_HID_PROTOCOL_MOUSE;
     142               
     143                // set the polling callback
     144                hid_dev->poll_callback = usb_dummy_polling_callback;
     145               
     146        } else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
     147                usb_log_debug("Found generic HID endpoint.\n");
     148               
     149                // save the pipe index and device type
     150                hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
     151                hid_dev->device_type = USB_HID_PROTOCOL_NONE;
     152               
     153                // set the polling callback
     154                hid_dev->poll_callback = usb_hid_polling_callback;
     155               
     156        } else {
     157                usb_log_warning("None of supported endpoints found - probably"
     158                    " not a supported device.\n");
     159                return ENOTSUP;
     160        }
     161       
     162        return EOK;
     163}
     164
     165/*----------------------------------------------------------------------------*/
     166
     167static int usb_hid_init_parser(usb_hid_dev_t *hid_dev)
     168{
     169        /* Initialize the report parser. */
     170        int rc = usb_hid_parser_init(hid_dev->parser);
     171        if (rc != EOK) {
     172                usb_log_error("Failed to initialize report parser.\n");
     173                return rc;
     174        }
     175       
     176        /* Get the report descriptor and parse it. */
     177        rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
     178            hid_dev->parser);
     179        if (rc != EOK) {
     180                usb_log_warning("Could not process report descriptor.\n");
     181               
     182                if (hid_dev->device_type == USB_HID_PROTOCOL_KEYBOARD) {
     183                        usb_log_warning("Falling back to boot protocol.\n");
     184                       
     185                        rc = usb_kbd_set_boot_protocol(hid_dev);
     186                       
     187                } else if (hid_dev->device_type == USB_HID_PROTOCOL_MOUSE) {
     188                        usb_log_warning("No boot protocol for mouse yet.\n");
     189                        rc = ENOTSUP;
     190                }
     191        }
     192       
     193        return rc;
     194}
     195
     196/*----------------------------------------------------------------------------*/
     197
     198int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev)
     199{
     200        int rc;
     201       
     202        usb_log_debug("Initializing HID structure...\n");
     203       
     204        if (hid_dev == NULL) {
     205                usb_log_error("Failed to init HID structure: no structure given"
     206                    ".\n");
     207                return EINVAL;
     208        }
     209       
     210        if (dev == NULL) {
     211                usb_log_error("Failed to init HID structure: no USB device"
     212                    " given.\n");
     213                return EINVAL;
     214        }
     215       
     216        /* The USB device should already be initialized, save it in structure */
     217        hid_dev->usb_dev = dev;
     218       
     219        rc = usb_hid_check_pipes(hid_dev, dev);
     220        if (rc != EOK) {
     221                return rc;
     222        }
     223       
     224        rc = usb_hid_init_parser(hid_dev);
     225        if (rc != EOK) {
     226                usb_log_error("Failed to initialize HID parser.\n");
     227                return rc;
     228        }
     229       
     230        switch (hid_dev->device_type) {
     231        case USB_HID_PROTOCOL_KEYBOARD:
     232                // initialize the keyboard structure
     233                rc = usb_kbd_init(hid_dev);
     234                if (rc != EOK) {
     235                        usb_log_warning("Failed to initialize KBD structure."
     236                            "\n");
     237                }
     238                break;
     239        case USB_HID_PROTOCOL_MOUSE:
     240                break;
     241        default:
     242                break;
     243        }
     244       
     245        return rc;
     246}
     247
     248/*----------------------------------------------------------------------------*/
     249
     250void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason,
     251     void *arg)
     252{
     253        if (dev == NULL || arg == NULL) {
     254                return;
     255        }
     256       
     257        usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
     258       
     259        usb_hid_free(&hid_dev);
     260}
     261
     262/*----------------------------------------------------------------------------*/
     263
     264const char *usb_hid_get_function_name(usb_hid_iface_protocol_t device_type)
     265{
     266        switch (device_type) {
     267        case USB_HID_PROTOCOL_KEYBOARD:
     268                return HID_KBD_FUN_NAME;
     269                break;
     270        case USB_HID_PROTOCOL_MOUSE:
     271                return HID_MOUSE_FUN_NAME;
     272                break;
     273        default:
     274                return HID_GENERIC_FUN_NAME;
     275        }
     276}
     277
     278/*----------------------------------------------------------------------------*/
     279
     280const char *usb_hid_get_class_name(usb_hid_iface_protocol_t device_type)
     281{
     282        switch (device_type) {
     283        case USB_HID_PROTOCOL_KEYBOARD:
     284                return HID_KBD_CLASS_NAME;
     285                break;
     286        case USB_HID_PROTOCOL_MOUSE:
     287                return HID_MOUSE_CLASS_NAME;
     288                break;
     289        default:
     290                return HID_GENERIC_CLASS_NAME;
     291        }
     292}
     293
     294/*----------------------------------------------------------------------------*/
     295
     296void usb_hid_free(usb_hid_dev_t **hid_dev)
     297{
     298        if (hid_dev == NULL || *hid_dev == NULL) {
     299                return;
     300        }
     301       
     302        switch ((*hid_dev)->device_type) {
     303        case USB_HID_PROTOCOL_KEYBOARD:
     304                usb_kbd_deinit(*hid_dev);
     305                break;
     306        case USB_HID_PROTOCOL_MOUSE:
     307                break;
     308        default:
     309                break;
     310        }
     311
     312        // destroy the parser
     313        if ((*hid_dev)->parser != NULL) {
     314                usb_hid_free_report_parser((*hid_dev)->parser);
     315        }
     316
     317        if ((*hid_dev)->report_desc != NULL) {
     318                free((*hid_dev)->report_desc);
     319        }
     320
     321        free(*hid_dev);
     322        *hid_dev = NULL;
    80323}
    81324
Note: See TracChangeset for help on using the changeset viewer.