Changeset 747ef72 in mainline for uspace/drv/bus/usb/usbhid/usbhid.c


Ignore:
Timestamp:
2011-11-10T11:29:10Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
54464f6a, c2245a3, c6f189f7
Parents:
2e1b9dc (diff), 2d1ba51 (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 USB changes.

Interface changes:

  • GET_ADDRESS has been renamed to GET_MY_ADDRESS and the handle parameter was dropped. Tis call no longer cascades up to the root hub, but it is answered in the first place the information is available (nearest hub)
  • Reintroduced address reservation for USB_DEFAULT_ADDRESS. The interface now enables device drivers to request specific address on initialization and either insists on that address or accept any other if the address is not available. Note that it is not possible to get the default address if the driver does not insist.
  • Any endpoint registered is removed when address is released and a warning is produced if there were any such endpoints.
  • It is no longer necessary or possible to pass device speed information when registering endpoints.

Driver fixes: memory leaks and crashes (not only) in error paths.
Fixes or removes flaky device_remove implementation in device drivers.

File:
1 edited

Legend:

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

    r2e1b9dc r747ef72  
    5151#include "subdrivers.h"
    5252
    53 /*----------------------------------------------------------------------------*/
    54 
    5553/* Array of endpoints expected on the device, NULL terminated. */
    5654const usb_endpoint_description_t *usb_hid_endpoints[] = {
     
    6058        NULL
    6159};
    62 
    63 /*----------------------------------------------------------------------------*/
    64 
     60/*----------------------------------------------------------------------------*/
    6561static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev)
    6662{
     
    7874        return EOK;
    7975}
    80 
    81 /*----------------------------------------------------------------------------*/
    82 
     76/*----------------------------------------------------------------------------*/
    8377static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev)
    8478{
     
    9286        hid_dev->subdriver_count = 1;
    9387        // TODO 2 should be mouse, but find a better way
    94         hid_dev->subdrivers[2] = usb_hid_subdrivers[0].subdriver;
     88        hid_dev->subdrivers[0] = usb_hid_subdrivers[2].subdriver;
    9589
    9690        return EOK;
    9791}
    98 
    99 /*----------------------------------------------------------------------------*/
    100 
     92/*----------------------------------------------------------------------------*/
    10193static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev)
    10294{
    103         assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
     95        assert(hid_dev != NULL);
     96        assert(hid_dev->subdriver_count == 0);
    10497
    10598        hid_dev->subdrivers = malloc(sizeof(usb_hid_subdriver_t));
     
    117110        return EOK;
    118111}
    119 
    120 /*----------------------------------------------------------------------------*/
    121 
     112/*----------------------------------------------------------------------------*/
    122113static bool usb_hid_ids_match(const usb_hid_dev_t *hid_dev,
    123114    const usb_hid_subdriver_mapping_t *mapping)
     
    128119        return (hid_dev->usb_dev->descriptors.device.vendor_id
    129120            == mapping->vendor_id
    130             && hid_dev->usb_dev->descriptors.device.product_id 
     121            && hid_dev->usb_dev->descriptors.device.product_id
    131122            == mapping->product_id);
    132123}
    133 
    134 /*----------------------------------------------------------------------------*/
    135 
     124/*----------------------------------------------------------------------------*/
    136125static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev,
    137126    const usb_hid_subdriver_mapping_t *mapping)
     
    145134                return false;
    146135        }
    147         int i = 0;
    148         while (mapping->usage_path[i].usage != 0
    149             || mapping->usage_path[i].usage_page != 0) {
     136
     137        for (int i = 0; mapping->usage_path[i].usage != 0
     138            || mapping->usage_path[i].usage_page != 0; ++i) {
    150139                if (usb_hid_report_path_append_item(usage_path,
    151140                    mapping->usage_path[i].usage_page,
     
    155144                        return false;
    156145                }
    157                 ++i;
    158146        }
    159147
     
    165153        do {
    166154                usb_log_debug("Trying report id %u\n", report_id);
    167 
    168155                if (report_id != 0) {
    169156                        usb_hid_report_path_set_report_id(usage_path,
     
    171158                }
    172159
    173                 usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    174                     &hid_dev->report, NULL, usage_path, mapping->compare,
    175                     USB_HID_REPORT_TYPE_INPUT);
     160                const usb_hid_report_field_t *field =
     161                    usb_hid_report_get_sibling(
     162                        &hid_dev->report, NULL, usage_path, mapping->compare,
     163                        USB_HID_REPORT_TYPE_INPUT);
    176164
    177165                usb_log_debug("Field: %p\n", field);
     
    190178        return matches;
    191179}
    192 
    193 /*----------------------------------------------------------------------------*/
    194 
     180/*----------------------------------------------------------------------------*/
    195181static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev,
    196     const usb_hid_subdriver_t **subdrivers, int count)
    197 {
    198         int i;
    199 
    200         if (count <= 0) {
     182    const usb_hid_subdriver_t **subdrivers, unsigned count)
     183{
     184        assert(hid_dev);
     185        assert(subdrivers);
     186
     187        if (count == 0) {
    201188                hid_dev->subdriver_count = 0;
    202189                hid_dev->subdrivers = NULL;
     
    210197        }
    211198
    212         for (i = 0; i < count; ++i) {
    213                 hid_dev->subdrivers[i].init = subdrivers[i]->init;
    214                 hid_dev->subdrivers[i].deinit = subdrivers[i]->deinit;
    215                 hid_dev->subdrivers[i].poll = subdrivers[i]->poll;
    216                 hid_dev->subdrivers[i].poll_end = subdrivers[i]->poll_end;
     199        for (unsigned i = 0; i < count; ++i) {
     200                hid_dev->subdrivers[i] = *subdrivers[i];
    217201        }
    218202
     
    227211        return EOK;
    228212}
    229 
    230 /*----------------------------------------------------------------------------*/
    231 
     213/*----------------------------------------------------------------------------*/
    232214static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev)
    233215{
     
    235217
    236218        const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS];
    237 
    238         int i = 0, count = 0;
    239         const usb_hid_subdriver_mapping_t *mapping = &usb_hid_subdrivers[i];
    240 
    241         bool ids_matched;
    242         bool matched;
    243 
    244         while (count < USB_HID_MAX_SUBDRIVERS &&
    245             (mapping->usage_path != NULL
    246             || mapping->vendor_id >= 0 || mapping->product_id >= 0)) {
    247                 // check the vendor & product ID
     219        unsigned count = 0;
     220
     221        for (unsigned i = 0; i < USB_HID_MAX_SUBDRIVERS; ++i) {
     222                const usb_hid_subdriver_mapping_t *mapping =
     223                    &usb_hid_subdrivers[i];
     224                /* Check the vendor & product ID. */
    248225                if (mapping->vendor_id >= 0 && mapping->product_id < 0) {
    249                         usb_log_warning("Missing Product ID for Vendor ID %d\n",
    250                             mapping->vendor_id);
    251                         return EINVAL;
     226                        usb_log_warning("Mapping[%d]: Missing Product ID for "
     227                            "Vendor ID %d\n", i, mapping->vendor_id);
    252228                }
    253229                if (mapping->product_id >= 0 && mapping->vendor_id < 0) {
    254                         usb_log_warning("Missing Vendor ID for Product ID %d\n",
    255                             mapping->product_id);
    256                         return EINVAL;
    257                 }
    258 
    259                 ids_matched = false;
    260                 matched = false;
    261 
    262                 if (mapping->vendor_id >= 0) {
    263                         assert(mapping->product_id >= 0);
     230                        usb_log_warning("Mapping[%d]: Missing Vendor ID for "
     231                            "Product ID %d\n", i, mapping->product_id);
     232                }
     233
     234                bool matched = false;
     235
     236                /* Check ID match. */
     237                if (mapping->vendor_id >= 0 && mapping->product_id >= 0) {
    264238                        usb_log_debug("Comparing device against vendor ID %u"
    265239                            " and product ID %u.\n", mapping->vendor_id,
     
    267241                        if (usb_hid_ids_match(hid_dev, mapping)) {
    268242                                usb_log_debug("IDs matched.\n");
    269                                 ids_matched = true;
     243                                matched = true;
    270244                        }
    271245                }
    272246
     247                /* Check usage match. */
    273248                if (mapping->usage_path != NULL) {
    274249                        usb_log_debug("Comparing device against usage path.\n");
    275250                        if (usb_hid_path_matches(hid_dev, mapping)) {
    276                                 // does not matter if IDs were matched
     251                                /* Does not matter if IDs were matched. */
    277252                                matched = true;
    278253                        }
    279                 } else {
    280                         // matched only if IDs were matched and there is no path
    281                         matched = ids_matched;
    282254                }
    283255
     
    286258                        subdrivers[count++] = &mapping->subdriver;
    287259                }
    288 
    289                 mapping = &usb_hid_subdrivers[++i];
    290260        }
    291261
    292262        /* We have all subdrivers determined, save them into the hid device */
    293         // TODO Dowe really need this complicated stuff if there is
    294         // max_subdrivers limitation?
    295263        return usb_hid_save_subdrivers(hid_dev, subdrivers, count);
    296264}
    297 
    298 /*----------------------------------------------------------------------------*/
    299 
     265/*----------------------------------------------------------------------------*/
    300266static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, const usb_device_t *dev)
    301267{
     
    303269        assert(dev);
    304270
    305         if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
    306                 usb_log_debug("Found keyboard endpoint.\n");
    307                 // save the pipe index
    308                 hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
    309         } else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
    310                 usb_log_debug("Found mouse endpoint.\n");
    311                 // save the pipe index
    312                 hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
    313         } else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
    314                 usb_log_debug("Found generic HID endpoint.\n");
    315                 // save the pipe index
    316                 hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
    317         } else {
    318                 usb_log_error("None of supported endpoints found - probably"
    319                     " not a supported device.\n");
    320                 return ENOTSUP;
    321         }
    322 
    323         return EOK;
    324 }
    325 
    326 /*----------------------------------------------------------------------------*/
    327 
     271        static const struct {
     272                unsigned ep_number;
     273                const char* description;
     274        } endpoints[] = {
     275                {USB_HID_KBD_POLL_EP_NO, "Keyboard endpoint"},
     276                {USB_HID_MOUSE_POLL_EP_NO, "Mouse endpoint"},
     277                {USB_HID_GENERIC_POLL_EP_NO, "Generic HID endpoint"},
     278        };
     279
     280        for (unsigned i = 0; i < sizeof(endpoints)/sizeof(endpoints[0]); ++i) {
     281                if (endpoints[i].ep_number >= dev->pipes_count) {
     282                        return EINVAL;
     283                }
     284                if (dev->pipes[endpoints[i].ep_number].present) {
     285                        usb_log_debug("Found: %s.\n", endpoints[i].description);
     286                        hid_dev->poll_pipe_index = endpoints[i].ep_number;
     287                        return EOK;
     288                }
     289        }
     290        return ENOTSUP;
     291}
     292/*----------------------------------------------------------------------------*/
    328293static int usb_hid_init_report(usb_hid_dev_t *hid_dev)
    329294{
     
    357322        return EOK;
    358323}
    359 
    360 /*----------------------------------------------------------------------------*/
    361 
     324/*----------------------------------------------------------------------------*/
     325/*
     326 * This functions initializes required structures from the device's descriptors
     327 * and starts new fibril for polling the keyboard for events and another one for
     328 * handling auto-repeat of keys.
     329 *
     330 * During initialization, the keyboard is switched into boot protocol, the idle
     331 * rate is set to 0 (infinity), resulting in the keyboard only reporting event
     332 * when a key is pressed or released. Finally, the LED lights are turned on
     333 * according to the default setup of lock keys.
     334 *
     335 * @note By default, the keyboards is initialized with Num Lock turned on and
     336 *       other locks turned off.
     337 *
     338 * @param hid_dev Device to initialize, non-NULL.
     339 * @param dev USB device, non-NULL.
     340 * @return Error code.
     341 */
    362342int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev)
    363343{
    364         int rc, i;
     344        assert(hid_dev);
     345        assert(dev);
    365346
    366347        usb_log_debug("Initializing HID structure...\n");
    367 
    368         if (hid_dev == NULL) {
    369                 usb_log_error("Failed to init HID structure: no structure given"
    370                     ".\n");
    371                 return EINVAL;
    372         }
    373 
    374         if (dev == NULL) {
    375                 usb_log_error("Failed to init HID structure: no USB device"
    376                     " given.\n");
    377                 return EINVAL;
    378         }
    379348
    380349        usb_hid_report_init(&hid_dev->report);
     
    384353        hid_dev->poll_pipe_index = -1;
    385354
    386         rc = usb_hid_check_pipes(hid_dev, dev);
     355        int rc = usb_hid_check_pipes(hid_dev, dev);
    387356        if (rc != EOK) {
    388357                return rc;
     
    390359
    391360        /* Get the report descriptor and parse it. */
    392         rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
    393             &hid_dev->report, &hid_dev->report_desc, &hid_dev->report_desc_size);
    394 
    395         bool fallback = false;
    396 
     361        rc = usb_hid_process_report_descriptor(
     362            hid_dev->usb_dev, &hid_dev->report, &hid_dev->report_desc,
     363            &hid_dev->report_desc_size);
     364
     365        /* If report parsing went well, find subdrivers. */
    397366        if (rc == EOK) {
    398                 // try to find subdrivers that may want to handle this device
    399                 rc = usb_hid_find_subdrivers(hid_dev);
    400                 if (rc != EOK || hid_dev->subdriver_count == 0) {
    401                         // try to fall back to the boot protocol if available
    402                         usb_log_info("No subdrivers found to handle this"
    403                             " device.\n");
    404                         fallback = true;
    405                         assert(hid_dev->subdrivers == NULL);
    406                         assert(hid_dev->subdriver_count == 0);
    407                 }
     367                usb_hid_find_subdrivers(hid_dev);
    408368        } else {
    409                 usb_log_error("Failed to parse Report descriptor.\n");
    410                 // try to fall back to the boot protocol if available
    411                 fallback = true;
    412         }
    413 
    414         if (fallback) {
    415                 // fall back to boot protocol
     369                usb_log_error("Failed to parse report descriptor: fallback.\n");
     370                hid_dev->subdrivers = NULL;
     371                hid_dev->subdriver_count = 0;
     372        }
     373
     374        usb_log_debug("Subdriver count(before trying boot protocol): %d\n",
     375            hid_dev->subdriver_count);
     376
     377        /* No subdrivers, fall back to the boot protocol if available. */
     378        if (hid_dev->subdriver_count == 0) {
     379                assert(hid_dev->subdrivers == NULL);
     380                usb_log_info("No subdrivers found to handle device, trying "
     381                    "boot protocol.\n");
     382
    416383                switch (hid_dev->poll_pipe_index) {
    417384                case USB_HID_KBD_POLL_EP_NO:
     
    419386                        rc = usb_kbd_set_boot_protocol(hid_dev);
    420387                        if (rc == EOK) {
    421                                 rc = usb_hid_set_boot_kbd_subdriver(hid_dev);
     388                                usb_hid_set_boot_kbd_subdriver(hid_dev);
    422389                        }
    423390                        break;
     
    426393                        rc = usb_mouse_set_boot_protocol(hid_dev);
    427394                        if (rc == EOK) {
    428                                 rc = usb_hid_set_boot_mouse_subdriver(hid_dev);
     395                                usb_hid_set_boot_mouse_subdriver(hid_dev);
    429396                        }
    430397                        break;
     
    432399                        assert(hid_dev->poll_pipe_index
    433400                            == USB_HID_GENERIC_POLL_EP_NO);
    434 
    435401                        usb_log_info("Falling back to generic HID driver.\n");
    436                         rc = usb_hid_set_generic_hid_subdriver(hid_dev);
    437                 }
    438         }
    439 
    440         if (rc != EOK) {
    441                 usb_log_error("No subdriver for handling this device could be"
    442                     " initialized: %s.\n", str_error(rc));
    443                 usb_log_debug("Subdriver count: %d\n",
    444                     hid_dev->subdriver_count);
    445         } else {
    446                 bool ok = false;
    447 
    448                 usb_log_debug("Subdriver count: %d\n",
    449                     hid_dev->subdriver_count);
    450 
    451                 for (i = 0; i < hid_dev->subdriver_count; ++i) {
    452                         if (hid_dev->subdrivers[i].init != NULL) {
    453                                 usb_log_debug("Initializing subdriver %d.\n",i);
    454                                 rc = hid_dev->subdrivers[i].init(hid_dev,
    455                                     &hid_dev->subdrivers[i].data);
    456                                 if (rc != EOK) {
    457                                         usb_log_warning("Failed to initialize"
    458                                             " HID subdriver structure.\n");
    459                                 } else {
    460                                         // at least one subdriver initialized
    461                                         ok = true;
    462                                 }
     402                        usb_hid_set_generic_hid_subdriver(hid_dev);
     403                }
     404        }
     405
     406        usb_log_debug("Subdriver count(after trying boot protocol): %d\n",
     407            hid_dev->subdriver_count);
     408
     409        /* Still no subdrivers? */
     410        if (hid_dev->subdriver_count == 0) {
     411                assert(hid_dev->subdrivers == NULL);
     412                usb_log_error(
     413                    "No subdriver for handling this device could be found.\n");
     414                return ENOTSUP;
     415        }
     416
     417        /*
     418         * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da
     419         *    do nej.
     420         * 2) do tych ops do .interfaces[DEV_IFACE_USBHID (asi)] priradi
     421         *    vyplnenu strukturu usbhid_iface_t.
     422         * 3) klientska aplikacia - musi si rucne vytvorit telefon
     423         *    (devman_device_connect() - cesta k zariadeniu (/hw/pci0/...) az
     424         *    k tej fcii.
     425         *    pouzit usb/classes/hid/iface.h - prvy int je telefon
     426         */
     427        bool ok = false;
     428        for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) {
     429                if (hid_dev->subdrivers[i].init != NULL) {
     430                        usb_log_debug("Initializing subdriver %d.\n",i);
     431                        const int pret = hid_dev->subdrivers[i].init(hid_dev,
     432                            &hid_dev->subdrivers[i].data);
     433                        if (pret != EOK) {
     434                                usb_log_warning("Failed to initialize"
     435                                    " HID subdriver structure: %s.\n",
     436                                    str_error(pret));
     437                                rc = pret;
    463438                        } else {
     439                                /* At least one subdriver initialized. */
    464440                                ok = true;
    465441                        }
    466                 }
    467 
    468                 rc = (ok) ? EOK : -1;   // what error to report
    469         }
    470 
    471 
    472         if (rc == EOK) {
    473                 // save max input report size and allocate space for the report
     442                } else {
     443                        /* Does not need initialization. */
     444                        ok = true;
     445                }
     446        }
     447
     448        if (ok) {
     449                /* Save max input report size and
     450                 * allocate space for the report */
    474451                rc = usb_hid_init_report(hid_dev);
    475452                if (rc != EOK) {
     
    481458        return rc;
    482459}
    483 
    484 /*----------------------------------------------------------------------------*/
    485 
     460/*----------------------------------------------------------------------------*/
    486461bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
    487462    size_t buffer_size, void *arg)
     
    516491        bool cont = false;
    517492        /* Continue if at least one of the subdrivers want to continue */
    518         for (int i = 0; i < hid_dev->subdriver_count; ++i) {
     493        for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) {
    519494                if (hid_dev->subdrivers[i].poll != NULL) {
    520495                        cont = cont || hid_dev->subdrivers[i].poll(
     
    525500        return cont;
    526501}
    527 
    528 /*----------------------------------------------------------------------------*/
    529 
     502/*----------------------------------------------------------------------------*/
    530503void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, void *arg)
    531504{
     
    535508        usb_hid_dev_t *hid_dev = arg;
    536509
    537         for (int i = 0; i < hid_dev->subdriver_count; ++i) {
     510        for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) {
    538511                if (hid_dev->subdrivers[i].poll_end != NULL) {
    539512                        hid_dev->subdrivers[i].poll_end(
     
    544517        hid_dev->running = false;
    545518}
    546 
    547 /*----------------------------------------------------------------------------*/
    548 
     519/*----------------------------------------------------------------------------*/
    549520void usb_hid_new_report(usb_hid_dev_t *hid_dev)
    550521{
    551522        ++hid_dev->report_nr;
    552523}
    553 
    554 /*----------------------------------------------------------------------------*/
    555 
     524/*----------------------------------------------------------------------------*/
    556525int usb_hid_report_number(const usb_hid_dev_t *hid_dev)
    557526{
    558527        return hid_dev->report_nr;
    559528}
    560 
    561 /*----------------------------------------------------------------------------*/
    562 
     529/*----------------------------------------------------------------------------*/
    563530void usb_hid_deinit(usb_hid_dev_t *hid_dev)
    564531{
     
    570537            hid_dev->subdrivers, hid_dev->subdriver_count);
    571538
    572         for (int i = 0; i < hid_dev->subdriver_count; ++i) {
     539        for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) {
    573540                if (hid_dev->subdrivers[i].deinit != NULL) {
    574541                        hid_dev->subdrivers[i].deinit(hid_dev,
Note: See TracChangeset for help on using the changeset viewer.