Changeset f76153ce in mainline


Ignore:
Timestamp:
2011-04-10T17:57:23Z (14 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1cbb4b7
Parents:
62bd8d3
Message:

Subdriver initialization.

  • Function for finding proper subdrivers (matching only based on usage path, no IDs yet).
  • Fixed setting generic HID subdriver.
  • Major changes to usb_hid_init(): fallback to boot protocol happens if:
    • the Report descriptor cannot be parsed, or
    • there is no subdriver found for the Report
Location:
uspace/drv/usbhid
Files:
3 edited

Legend:

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

    r62bd8d3 rf76153ce  
    4141        {
    4242                path_kbd,
     43                1,
    4344                USB_HID_PATH_COMPARE_END
    4445                | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
     
    5354               
    5455        },
    55         {NULL, 0, NULL, NULL, {NULL, NULL, NULL, NULL}}
     56        {NULL, 0, 0, NULL, NULL, {NULL, NULL, NULL, NULL}}
    5657};
    5758
  • uspace/drv/usbhid/subdrivers.h

    r62bd8d3 rf76153ce  
    4949/*----------------------------------------------------------------------------*/
    5050
     51/* TODO: This mapping must contain some other information to get the proper
     52 *       interface.
     53 */
    5154typedef struct usb_hid_subdriver_mapping {
    5255        const usb_hid_subdriver_usage_t *usage_path;
     56        int path_size;
    5357        int compare;
    5458        const char *vendor_id;
  • uspace/drv/usbhid/usbhid.c

    r62bd8d3 rf76153ce  
    4242#include <usb/classes/hidreq.h>
    4343#include <errno.h>
     44#include <str_error.h>
    4445
    4546#include "usbhid.h"
     
    6061};
    6162
     63static const int USB_HID_MAX_SUBDRIVERS = 10;
     64
    6265/*----------------------------------------------------------------------------*/
    6366
     
    144147        hid_dev->subdrivers[0].deinit = NULL;
    145148       
     149        // set subdriver count
     150        hid_dev->subdriver_count = 1;
     151       
    146152        return EOK;
    147153}
     
    149155/*----------------------------------------------------------------------------*/
    150156
     157static bool usb_hid_ids_match(usb_hid_dev_t *hid_dev,
     158    const usb_hid_subdriver_mapping_t *mapping)
     159{
     160        return false;
     161}
     162
     163/*----------------------------------------------------------------------------*/
     164
     165static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev,
     166    const usb_hid_subdriver_usage_t *path, int path_size, int compare)
     167{
     168        assert(hid_dev != NULL);
     169        assert(path != NULL);
     170       
     171        usb_hid_report_path_t *usage_path = usb_hid_report_path();
     172        if (usage_path == NULL) {
     173                return false;
     174        }
     175        int i;
     176        for (i = 0; i < path_size; ++i) {
     177                if (usb_hid_report_path_append_item(usage_path,
     178                    path[i].usage_page, path[i].usage) != EOK) {
     179                        usb_hid_report_path_free(usage_path);
     180                        return false;
     181                }
     182        }
     183       
     184        bool matches = (usb_hid_report_input_length(hid_dev->parser, usage_path,
     185            compare) > 0);
     186       
     187        usb_hid_report_path_free(usage_path);
     188       
     189        return matches;
     190}
     191
     192/*----------------------------------------------------------------------------*/
     193
     194static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev,
     195    const usb_hid_subdriver_t **subdrivers, int count)
     196{
     197        int i;
     198       
     199        if (count <= 0) {
     200                hid_dev->subdriver_count = 0;
     201                hid_dev->subdrivers = NULL;
     202                return EOK;
     203        }
     204       
     205        hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(count *
     206            sizeof(usb_hid_subdriver_t));
     207        if (hid_dev->subdrivers == NULL) {
     208                return ENOMEM;
     209        }
     210       
     211        for (i = 0; i < count; ++i) {
     212                hid_dev->subdrivers[i].init = subdrivers[i]->init;
     213                hid_dev->subdrivers[i].deinit = subdrivers[i]->deinit;
     214                hid_dev->subdrivers[i].poll = subdrivers[i]->poll;
     215                hid_dev->subdrivers[i].poll_end = subdrivers[i]->poll_end;
     216        }
     217       
     218        hid_dev->subdriver_count = count;
     219       
     220        return EOK;
     221}
     222
     223/*----------------------------------------------------------------------------*/
     224
    151225static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev)
    152226{
    153         return EOK;
     227        const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS];
     228       
     229        int i = 0, count = 0;
     230        const usb_hid_subdriver_mapping_t *mapping = &usb_hid_subdrivers[i];
     231       
     232        while (count < USB_HID_MAX_SUBDRIVERS &&
     233            (mapping->usage_path != NULL
     234            || mapping->vendor_id != NULL
     235            || mapping->product_id != NULL)) {
     236                // check the vendor & product ID
     237                if (mapping->vendor_id != NULL && mapping->product_id == NULL) {
     238                        usb_log_warning("Missing Product ID for Vendor ID %s\n",
     239                            mapping->vendor_id);
     240                        return EINVAL;
     241                }
     242                if (mapping->product_id != NULL && mapping->vendor_id == NULL) {
     243                        usb_log_warning("Missing Vendor ID for Product ID %s\n",
     244                            mapping->product_id);
     245                        return EINVAL;
     246                }
     247               
     248                if (mapping->vendor_id != NULL) {
     249                        assert(mapping->product_id != NULL);
     250                        usb_log_debug("Comparing device against vendor ID %s"
     251                            " and product ID %s.\n", mapping->vendor_id,
     252                            mapping->product_id);
     253                        if (usb_hid_ids_match(hid_dev, mapping)) {
     254                                usb_log_debug("Matched.\n");
     255                                subdrivers[count++] = &mapping->subdriver;
     256                                // skip the checking of usage path
     257                                goto next;
     258                        }
     259                }
     260               
     261                if (mapping->usage_path != NULL) {
     262                        if (usb_hid_path_matches(hid_dev,
     263                            mapping->usage_path, mapping->path_size,
     264                            mapping->compare)) {
     265                                subdrivers[count++] = &mapping->subdriver;
     266                        }
     267                }
     268        next:
     269                mapping = &usb_hid_subdrivers[++i];
     270        }
     271       
     272        // we have all subdrivers determined, save them into the hid device
     273        return usb_hid_save_subdrivers(hid_dev, subdrivers, count);
    154274}
    155275
     
    158278static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
    159279{
    160         // first try to find subdrivers that may want to handle this device
    161         int rc = usb_hid_find_subdrivers(hid_dev);
     280        int rc = EOK;
    162281       
    163282        if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
    164283                usb_log_debug("Found keyboard endpoint.\n");
    165                
    166284                // save the pipe index
    167285                hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
    168                
    169                 // if no subdrivers registered, use the boot kbd subdriver
    170                 if (hid_dev->subdriver_count == 0) {
    171                         rc = usb_hid_set_boot_kbd_subdriver(hid_dev);
    172                 }
    173286        } else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
    174287                usb_log_debug("Found mouse endpoint.\n");
    175                
    176288                // save the pipe index
    177289                hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
    178                 //hid_dev->device_type = USB_HID_PROTOCOL_MOUSE;
    179                
    180                 // if no subdrivers registered, use the boot kbd subdriver
    181                 if (hid_dev->subdriver_count == 0) {
    182                         rc = usb_hid_set_boot_mouse_subdriver(hid_dev);
    183                 }               
    184290        } else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
    185291                usb_log_debug("Found generic HID endpoint.\n");
    186                
    187292                // save the pipe index
    188293                hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
    189                
    190                 if (hid_dev->subdriver_count == 0) {
    191                         usb_log_warning("Found no subdriver for handling this"
    192                             " HID device. Setting generic HID subdriver.\n");
    193                         usb_hid_set_generic_hid_subdriver(hid_dev);
    194                         return EOK;
    195                 }
    196294        } else {
    197295                usb_log_error("None of supported endpoints found - probably"
    198296                    " not a supported device.\n");
    199297                rc = ENOTSUP;
    200         }
    201        
    202         return rc;
    203 }
    204 
    205 /*----------------------------------------------------------------------------*/
    206 
    207 static int usb_hid_init_parser(usb_hid_dev_t *hid_dev)
    208 {
    209         /* Initialize the report parser. */
    210         int rc = usb_hid_parser_init(hid_dev->parser);
    211         if (rc != EOK) {
    212                 usb_log_error("Failed to initialize report parser.\n");
    213                 return rc;
    214         }
    215        
    216         /* Get the report descriptor and parse it. */
    217         rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
    218             hid_dev->parser);
    219        
    220         // TODO: remove the hack
    221         if (rc != EOK || hid_dev->poll_pipe_index == USB_HID_MOUSE_POLL_EP_NO) {
    222                 usb_log_warning("Could not process report descriptor.\n");
    223                
    224                 if (hid_dev->poll_pipe_index == USB_HID_KBD_POLL_EP_NO) {
    225                         usb_log_warning("Falling back to boot protocol.\n");
    226                         rc = usb_kbd_set_boot_protocol(hid_dev);
    227                 } else if (hid_dev->poll_pipe_index
    228                     == USB_HID_MOUSE_POLL_EP_NO) {
    229                         usb_log_warning("Falling back to boot protocol.\n");
    230                         rc = usb_mouse_set_boot_protocol(hid_dev);
    231                 }
    232298        }
    233299       
     
    255321        }
    256322       
     323        hid_dev->poll_pipe_index = -1;
     324       
    257325        return hid_dev;
    258326}
     
    283351        rc = usb_hid_check_pipes(hid_dev, dev);
    284352        if (rc != EOK) {
     353                usb_hid_free(&hid_dev);
    285354                return rc;
    286355        }
    287356       
    288         rc = usb_hid_init_parser(hid_dev);
     357        /* Initialize the report parser. */
     358        rc = usb_hid_parser_init(hid_dev->parser);
    289359        if (rc != EOK) {
    290                 usb_log_error("Failed to initialize HID parser.\n");
     360                usb_log_error("Failed to initialize report parser.\n");
     361                usb_hid_free(&hid_dev);
    291362                return rc;
    292363        }
    293364       
    294         for (i = 0; i < hid_dev->subdriver_count; ++i) {
    295                 if (hid_dev->subdrivers[i].init != NULL) {
    296                         rc = hid_dev->subdrivers[i].init(hid_dev);
    297                         if (rc != EOK) {
    298                                 usb_log_warning("Failed to initialize HID"
    299                                     " subdriver structure.\n");
     365        /* Get the report descriptor and parse it. */
     366        rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
     367            hid_dev->parser);
     368       
     369        bool fallback = false;
     370       
     371        if (rc == EOK) {
     372                // try to find subdrivers that may want to handle this device
     373                rc = usb_hid_find_subdrivers(hid_dev);
     374                if (rc != EOK || hid_dev->subdriver_count == 0) {
     375                        // try to fall back to the boot protocol if available
     376                        usb_log_info("No subdrivers found to handle this"
     377                            " device.\n");
     378                        fallback = true;
     379                }
     380        } else {
     381                usb_log_error("Failed to parse Report descriptor.\n");
     382                // try to fall back to the boot protocol if available
     383                fallback = true;
     384        }
     385       
     386        // TODO: remove the mouse hack
     387        if (hid_dev->poll_pipe_index == USB_HID_MOUSE_POLL_EP_NO ||
     388            fallback) {
     389                // fall back to boot protocol
     390                switch (hid_dev->poll_pipe_index) {
     391                case USB_HID_KBD_POLL_EP_NO:
     392                        usb_log_info("Falling back to kbd boot protocol.\n");
     393                        rc = usb_kbd_set_boot_protocol(hid_dev);
     394                        if (rc == EOK) {
     395                                rc = usb_hid_set_boot_kbd_subdriver(hid_dev);
    300396                        }
    301                 }
     397                        break;
     398                case USB_HID_MOUSE_POLL_EP_NO:
     399                        usb_log_info("Falling back to mouse boot protocol.\n");
     400                        rc = usb_mouse_set_boot_protocol(hid_dev);
     401                        if (rc == EOK) {
     402                                rc = usb_hid_set_boot_mouse_subdriver(hid_dev);
     403                        }
     404                        break;
     405                default:
     406                        assert(hid_dev->poll_pipe_index
     407                            == USB_HID_GENERIC_POLL_EP_NO);
     408                       
     409                        /* TODO: this has no meaning if the report descriptor
     410                                 is not parsed */
     411                        usb_log_info("Falling back to generic HID driver.\n");
     412                        rc = usb_hid_set_generic_hid_subdriver(hid_dev);
     413                }
     414        }
     415       
     416        if (rc != EOK) {
     417                usb_log_error("No subdriver for handling this device could be"
     418                    " initialized: %s.\n", str_error(rc));
     419                usb_hid_free(&hid_dev);
     420        } else {
     421                bool ok = false;
     422               
     423                usb_log_debug("Subdriver count: %d\n",
     424                    hid_dev->subdriver_count);
     425               
     426                for (i = 0; i < hid_dev->subdriver_count; ++i) {
     427                        if (hid_dev->subdrivers[i].init != NULL) {
     428                                usb_log_debug("Initializing subdriver %d.\n",i);
     429                                rc = hid_dev->subdrivers[i].init(hid_dev);
     430                                if (rc != EOK) {
     431                                        usb_log_warning("Failed to initialize"
     432                                            " HID subdriver structure.\n");
     433                                } else {
     434                                        // at least one subdriver initialized
     435                                        ok = true;
     436                                }
     437                        } else {
     438                                ok = true;
     439                        }
     440                }
     441               
     442                rc = (ok) ? EOK : -1;   // what error to report
    302443        }
    303444       
     
    400541        }
    401542       
     543        assert((*hid_dev)->subdrivers != NULL
     544            || (*hid_dev)->subdriver_count == 0);
     545       
    402546        for (i = 0; i < (*hid_dev)->subdriver_count; ++i) {
    403547                if ((*hid_dev)->subdrivers[i].deinit != NULL) {
     
    405549                }
    406550        }
     551       
     552        // free the subdrivers info
     553        if ((*hid_dev)->subdrivers != NULL) {
     554                free(subdrivers);
     555        }
    407556
    408557        // destroy the parser
Note: See TracChangeset for help on using the changeset viewer.