Changeset 60c0573 in mainline for uspace/drv/usbhid/usbhid.c


Ignore:
Timestamp:
2011-04-10T15:17:22Z (13 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
ba358ed
Parents:
dc4c19e
Message:

Preparation for HID subdrivers.

  • Preparation for registering subdriver callbacks based on some device identifiers.
  • HID driver now uses one general callback which calls all the registered subdriver callbacks.
  • Other callbacks for init, deinit and polling ended.
  • Setting boot keyboard and mouse callbacks separately (special cases).

TODO: maybe also functions and function classes may be per-subdriver

(so a hybrid keyboard/pointing device may register itself as

both keyboard and mouse).

TODO: the current keyboard and mouse subdrivers should fall back to the

booot protocol by default.

File:
1 edited

Legend:

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

    rdc4c19e r60c0573  
    5151/*----------------------------------------------------------------------------*/
    5252
     53typedef struct usb_hid_callback_mapping {
     54        usb_hid_report_path_t *path;
     55        char *vendor_id;
     56        char *product_id;
     57} usb_hid_callback_mapping;
     58
     59/*----------------------------------------------------------------------------*/
     60
    5361/* Array of endpoints expected on the device, NULL terminated. */
    5462usb_endpoint_description_t *usb_hid_endpoints[USB_HID_POLL_EP_COUNT + 1] = {
     
    6169/*----------------------------------------------------------------------------*/
    6270
     71static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev)
     72{
     73        assert(hid_dev->subdriver_count == 0);
     74       
     75        hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
     76            sizeof(usb_hid_subdriver_t));
     77        if (hid_dev->subdrivers == NULL) {
     78                return ENOMEM;
     79        }
     80       
     81        // set the init callback
     82        hid_dev->subdrivers[0].init = usb_kbd_init;
     83       
     84        // set the polling callback
     85        hid_dev->subdrivers[0].poll = usb_kbd_polling_callback;
     86       
     87        // set the polling ended callback
     88        hid_dev->subdrivers[0].poll_end = NULL;
     89       
     90        // set the deinit callback
     91        hid_dev->subdrivers[0].deinit = usb_kbd_deinit;
     92       
     93        // set subdriver count
     94        hid_dev->subdriver_count = 1;
     95       
     96        return EOK;
     97}
     98
     99/*----------------------------------------------------------------------------*/
     100
     101static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev)
     102{
     103        assert(hid_dev->subdriver_count == 0);
     104       
     105        hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
     106            sizeof(usb_hid_subdriver_t));
     107        if (hid_dev->subdrivers == NULL) {
     108                return ENOMEM;
     109        }
     110       
     111        // set the init callback
     112        hid_dev->subdrivers[0].init = usb_mouse_init;
     113       
     114        // set the polling callback
     115        hid_dev->subdrivers[0].poll = usb_mouse_polling_callback;
     116       
     117        // set the polling ended callback
     118        hid_dev->subdrivers[0].poll_end = NULL;
     119       
     120        // set the deinit callback
     121        hid_dev->subdrivers[0].deinit = usb_mouse_deinit;
     122       
     123        // set subdriver count
     124        hid_dev->subdriver_count = 1;
     125       
     126        return EOK;
     127}
     128
     129/*----------------------------------------------------------------------------*/
     130
     131static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev)
     132{
     133        assert(hid_dev->subdriver_count == 0);
     134       
     135        hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
     136            sizeof(usb_hid_subdriver_t));
     137        if (hid_dev->subdrivers == NULL) {
     138                return ENOMEM;
     139        }
     140       
     141        // set the init callback
     142        hid_dev->subdrivers[0].init = NULL;
     143       
     144        // set the polling callback
     145        hid_dev->subdrivers[0].poll = usb_generic_hid_polling_callback;
     146       
     147        // set the polling ended callback
     148        hid_dev->subdrivers[0].poll_end = NULL;
     149       
     150        // set the deinit callback
     151        hid_dev->subdrivers[0].deinit = NULL;
     152       
     153        return EOK;
     154}
     155
     156/*----------------------------------------------------------------------------*/
     157
     158static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev)
     159{
     160        return EOK;
     161}
     162
     163/*----------------------------------------------------------------------------*/
     164
     165static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
     166{
     167        // first try to find subdrivers that may want to handle this device
     168        int rc = usb_hid_find_subdrivers(hid_dev);
     169       
     170        if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
     171                usb_log_debug("Found keyboard endpoint.\n");
     172               
     173                // save the pipe index
     174                hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
     175               
     176                // if no subdrivers registered, use the boot kbd subdriver
     177                if (hid_dev->subdriver_count == 0) {
     178                        rc = usb_hid_set_boot_kbd_subdriver(hid_dev);
     179                }
     180        } else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
     181                usb_log_debug("Found mouse endpoint.\n");
     182               
     183                // save the pipe index
     184                hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
     185                //hid_dev->device_type = USB_HID_PROTOCOL_MOUSE;
     186               
     187                // if no subdrivers registered, use the boot kbd subdriver
     188                if (hid_dev->subdriver_count == 0) {
     189                        rc = usb_hid_set_boot_mouse_subdriver(hid_dev);
     190                }               
     191        } else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
     192                usb_log_debug("Found generic HID endpoint.\n");
     193               
     194                // save the pipe index
     195                hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
     196               
     197                if (hid_dev->subdriver_count == 0) {
     198                        usb_log_warning("Found no subdriver for handling this"
     199                            " HID device. Setting generic HID subdriver.\n");
     200                        usb_hid_set_generic_hid_subdriver(hid_dev);
     201                        return EOK;
     202                }
     203        } else {
     204                usb_log_error("None of supported endpoints found - probably"
     205                    " not a supported device.\n");
     206                rc = ENOTSUP;
     207        }
     208       
     209        return rc;
     210}
     211
     212/*----------------------------------------------------------------------------*/
     213
     214static int usb_hid_init_parser(usb_hid_dev_t *hid_dev)
     215{
     216        /* Initialize the report parser. */
     217        int rc = usb_hid_parser_init(hid_dev->parser);
     218        if (rc != EOK) {
     219                usb_log_error("Failed to initialize report parser.\n");
     220                return rc;
     221        }
     222       
     223        /* Get the report descriptor and parse it. */
     224        rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
     225            hid_dev->parser);
     226       
     227        // TODO: remove the hack
     228        if (rc != EOK || hid_dev->poll_pipe_index == USB_HID_MOUSE_POLL_EP_NO) {
     229                usb_log_warning("Could not process report descriptor.\n");
     230               
     231                if (hid_dev->poll_pipe_index == USB_HID_KBD_POLL_EP_NO) {
     232                        usb_log_warning("Falling back to boot protocol.\n");
     233                        rc = usb_kbd_set_boot_protocol(hid_dev);
     234                } else if (hid_dev->poll_pipe_index
     235                    == USB_HID_MOUSE_POLL_EP_NO) {
     236                        usb_log_warning("Falling back to boot protocol.\n");
     237                        rc = usb_mouse_set_boot_protocol(hid_dev);
     238                }
     239        }
     240       
     241        return rc;
     242}
     243
     244/*----------------------------------------------------------------------------*/
     245
    63246usb_hid_dev_t *usb_hid_new(void)
    64247{
     
    84267/*----------------------------------------------------------------------------*/
    85268
    86 static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
    87 {
    88         if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
    89                 usb_log_debug("Found keyboard endpoint.\n");
    90                
    91                 // save the pipe index and device type
    92                 hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
    93                 hid_dev->device_type = USB_HID_PROTOCOL_KEYBOARD;
    94                
    95                 // set the polling callback
    96                 hid_dev->poll_callback = usb_kbd_polling_callback;
    97 
    98         } else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
    99                 usb_log_debug("Found mouse endpoint.\n");
    100                
    101                 // save the pipe index and device type
    102                 hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
    103                 hid_dev->device_type = USB_HID_PROTOCOL_MOUSE;
    104                
    105                 // set the polling callback
    106                 hid_dev->poll_callback = usb_mouse_polling_callback;
    107                
    108         } else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
    109                 usb_log_debug("Found generic HID endpoint.\n");
    110                
    111                 // save the pipe index and device type
    112                 hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
    113                 hid_dev->device_type = USB_HID_PROTOCOL_NONE;
    114                
    115                 // set the polling callback
    116                 hid_dev->poll_callback = usb_hid_polling_callback;
    117                
    118         } else {
    119                 usb_log_warning("None of supported endpoints found - probably"
    120                     " not a supported device.\n");
    121                 return ENOTSUP;
    122         }
    123        
    124         return EOK;
    125 }
    126 
    127 /*----------------------------------------------------------------------------*/
    128 
    129 static int usb_hid_init_parser(usb_hid_dev_t *hid_dev)
    130 {
    131         /* Initialize the report parser. */
    132         int rc = usb_hid_parser_init(hid_dev->parser);
    133         if (rc != EOK) {
    134                 usb_log_error("Failed to initialize report parser.\n");
    135                 return rc;
    136         }
    137        
    138         /* Get the report descriptor and parse it. */
    139         rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
    140             hid_dev->parser);
    141        
    142         if (rc != EOK || hid_dev->device_type == USB_HID_PROTOCOL_MOUSE) {
    143                 usb_log_warning("Could not process report descriptor.\n");
    144                
    145                 if (hid_dev->device_type == USB_HID_PROTOCOL_KEYBOARD) {
    146                         usb_log_warning("Falling back to boot protocol.\n");
    147                         rc = usb_kbd_set_boot_protocol(hid_dev);
    148                 } else if (hid_dev->device_type == USB_HID_PROTOCOL_MOUSE) {
    149                         usb_log_warning("Falling back to boot protocol.\n");
    150                         rc = usb_mouse_set_boot_protocol(hid_dev);
    151                 }
    152         }
    153        
    154         return rc;
    155 }
    156 
    157 /*----------------------------------------------------------------------------*/
    158 
    159269int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev)
    160270{
    161         int rc;
     271        int rc, i;
    162272       
    163273        usb_log_debug("Initializing HID structure...\n");
     
    189299        }
    190300       
    191         switch (hid_dev->device_type) {
    192         case USB_HID_PROTOCOL_KEYBOARD:
    193                 // initialize the keyboard structure
    194                 rc = usb_kbd_init(hid_dev);
    195                 if (rc != EOK) {
    196                         usb_log_warning("Failed to initialize KBD structure."
    197                             "\n");
    198                 }
    199                 break;
    200         case USB_HID_PROTOCOL_MOUSE:
    201                 rc = usb_mouse_init(hid_dev);
    202                 if (rc != EOK) {
    203                         usb_log_warning("Failed to initialize Mouse structure."
    204                             "\n");
    205                 }
    206                 break;
    207         default:
    208                 break;
     301        for (i = 0; i < hid_dev->subdriver_count; ++i) {
     302                if (hid_dev->subdrivers[i].init != NULL) {
     303                        rc = hid_dev->subdrivers[i].init(hid_dev);
     304                        if (rc != EOK) {
     305                                usb_log_warning("Failed to initialize HID"
     306                                    " subdriver structure.\n");
     307                        }
     308                }
    209309        }
    210310       
    211311        return rc;
     312}
     313
     314/*----------------------------------------------------------------------------*/
     315
     316bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
     317    size_t buffer_size, void *arg)
     318{
     319        int i;
     320       
     321        if (dev == NULL || arg == NULL || buffer == NULL) {
     322                usb_log_error("Missing arguments to polling callback.\n");
     323                return false;
     324        }
     325       
     326        usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
     327       
     328        bool cont = false;
     329       
     330        // continue if at least one of the subdrivers want to continue
     331        for (i = 0; i < hid_dev->subdriver_count; ++i) {
     332                if (hid_dev->subdrivers[i].poll != NULL
     333                    && hid_dev->subdrivers[i].poll(hid_dev, buffer,
     334                    buffer_size)) {
     335                        cont = true;
     336                }
     337        }
     338       
     339        return cont;
    212340}
    213341
     
    217345     void *arg)
    218346{
     347        int i;
     348       
    219349        if (dev == NULL || arg == NULL) {
    220350                return;
     
    223353        usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
    224354       
     355        for (i = 0; i < hid_dev->subdriver_count; ++i) {
     356                if (hid_dev->subdrivers[i].poll_end != NULL) {
     357                        hid_dev->subdrivers[i].poll_end(hid_dev, reason);
     358                }
     359        }
     360       
    225361        usb_hid_free(&hid_dev);
    226362}
     
    228364/*----------------------------------------------------------------------------*/
    229365
    230 const char *usb_hid_get_function_name(usb_hid_iface_protocol_t device_type)
    231 {
    232         switch (device_type) {
    233         case USB_HID_PROTOCOL_KEYBOARD:
     366const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev)
     367{
     368        switch (hid_dev->poll_pipe_index) {
     369        case USB_HID_KBD_POLL_EP_NO:
    234370                return HID_KBD_FUN_NAME;
    235371                break;
    236         case USB_HID_PROTOCOL_MOUSE:
     372        case USB_HID_MOUSE_POLL_EP_NO:
    237373                return HID_MOUSE_FUN_NAME;
    238374                break;
     
    244380/*----------------------------------------------------------------------------*/
    245381
    246 const char *usb_hid_get_class_name(usb_hid_iface_protocol_t device_type)
    247 {
    248         switch (device_type) {
    249         case USB_HID_PROTOCOL_KEYBOARD:
     382const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev)
     383{
     384        // this means that only boot protocol keyboards will be connected
     385        // to the console; there is probably no better way to do this
     386       
     387        switch (hid_dev->poll_pipe_index) {
     388        case USB_HID_KBD_POLL_EP_NO:
    250389                return HID_KBD_CLASS_NAME;
    251390                break;
    252         case USB_HID_PROTOCOL_MOUSE:
     391        case USB_HID_MOUSE_POLL_EP_NO:
    253392                return HID_MOUSE_CLASS_NAME;
    254393                break;
     
    262401void usb_hid_free(usb_hid_dev_t **hid_dev)
    263402{
     403        int i;
     404       
    264405        if (hid_dev == NULL || *hid_dev == NULL) {
    265406                return;
    266407        }
    267408       
    268         switch ((*hid_dev)->device_type) {
    269         case USB_HID_PROTOCOL_KEYBOARD:
    270                 usb_kbd_deinit(*hid_dev);
    271                 break;
    272         case USB_HID_PROTOCOL_MOUSE:
    273                 usb_mouse_deinit(*hid_dev);
    274                 break;
    275         default:
    276                 break;
     409        for (i = 0; i < (*hid_dev)->subdriver_count; ++i) {
     410                if ((*hid_dev)->subdrivers[i].deinit != NULL) {
     411                        (*hid_dev)->subdrivers[i].deinit(*hid_dev);
     412                }
    277413        }
    278414
Note: See TracChangeset for help on using the changeset viewer.