Ignore:
File:
1 edited

Legend:

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

    r2d1ba51 r93d2684  
    5151#include "subdrivers.h"
    5252
     53/*----------------------------------------------------------------------------*/
     54
    5355/* Array of endpoints expected on the device, NULL terminated. */
    5456const usb_endpoint_description_t *usb_hid_endpoints[] = {
     
    5860        NULL
    5961};
    60 /*----------------------------------------------------------------------------*/
     62
     63/*----------------------------------------------------------------------------*/
     64
    6165static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev)
    6266{
     
    7478        return EOK;
    7579}
    76 /*----------------------------------------------------------------------------*/
     80
     81/*----------------------------------------------------------------------------*/
     82
    7783static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev)
    7884{
     
    8692        hid_dev->subdriver_count = 1;
    8793        // TODO 2 should be mouse, but find a better way
    88         hid_dev->subdrivers[0] = usb_hid_subdrivers[2].subdriver;
     94        hid_dev->subdrivers[2] = usb_hid_subdrivers[0].subdriver;
    8995
    9096        return EOK;
    9197}
    92 /*----------------------------------------------------------------------------*/
     98
     99/*----------------------------------------------------------------------------*/
     100
    93101static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev)
    94102{
    95         assert(hid_dev != NULL);
    96         assert(hid_dev->subdriver_count == 0);
     103        assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
    97104
    98105        hid_dev->subdrivers = malloc(sizeof(usb_hid_subdriver_t));
     
    110117        return EOK;
    111118}
    112 /*----------------------------------------------------------------------------*/
     119
     120/*----------------------------------------------------------------------------*/
     121
    113122static bool usb_hid_ids_match(const usb_hid_dev_t *hid_dev,
    114123    const usb_hid_subdriver_mapping_t *mapping)
     
    119128        return (hid_dev->usb_dev->descriptors.device.vendor_id
    120129            == mapping->vendor_id
    121             && hid_dev->usb_dev->descriptors.device.product_id
     130            && hid_dev->usb_dev->descriptors.device.product_id 
    122131            == mapping->product_id);
    123132}
    124 /*----------------------------------------------------------------------------*/
     133
     134/*----------------------------------------------------------------------------*/
     135
    125136static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev,
    126137    const usb_hid_subdriver_mapping_t *mapping)
     
    134145                return false;
    135146        }
    136 
    137         for (int i = 0; mapping->usage_path[i].usage != 0
    138             || mapping->usage_path[i].usage_page != 0; ++i) {
     147        int i = 0;
     148        while (mapping->usage_path[i].usage != 0
     149            || mapping->usage_path[i].usage_page != 0) {
    139150                if (usb_hid_report_path_append_item(usage_path,
    140151                    mapping->usage_path[i].usage_page,
     
    144155                        return false;
    145156                }
     157                ++i;
    146158        }
    147159
     
    153165        do {
    154166                usb_log_debug("Trying report id %u\n", report_id);
     167
    155168                if (report_id != 0) {
    156169                        usb_hid_report_path_set_report_id(usage_path,
     
    158171                }
    159172
    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);
     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);
    164176
    165177                usb_log_debug("Field: %p\n", field);
     
    178190        return matches;
    179191}
    180 /*----------------------------------------------------------------------------*/
     192
     193/*----------------------------------------------------------------------------*/
     194
    181195static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev,
    182     const usb_hid_subdriver_t **subdrivers, unsigned count)
    183 {
    184         assert(hid_dev);
    185         assert(subdrivers);
    186 
    187         if (count == 0) {
     196    const usb_hid_subdriver_t **subdrivers, int count)
     197{
     198        int i;
     199
     200        if (count <= 0) {
    188201                hid_dev->subdriver_count = 0;
    189202                hid_dev->subdrivers = NULL;
     
    197210        }
    198211
    199         for (unsigned i = 0; i < count; ++i) {
    200                 hid_dev->subdrivers[i] = *subdrivers[i];
     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;
    201217        }
    202218
     
    211227        return EOK;
    212228}
    213 /*----------------------------------------------------------------------------*/
     229
     230/*----------------------------------------------------------------------------*/
     231
    214232static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev)
    215233{
     
    217235
    218236        const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS];
    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. */
     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
    225248                if (mapping->vendor_id >= 0 && mapping->product_id < 0) {
    226                         usb_log_warning("Mapping[%d]: Missing Product ID for "
    227                             "Vendor ID %d\n", i, mapping->vendor_id);
     249                        usb_log_warning("Missing Product ID for Vendor ID %d\n",
     250                            mapping->vendor_id);
     251                        return EINVAL;
    228252                }
    229253                if (mapping->product_id >= 0 && mapping->vendor_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) {
     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);
    238264                        usb_log_debug("Comparing device against vendor ID %u"
    239265                            " and product ID %u.\n", mapping->vendor_id,
     
    241267                        if (usb_hid_ids_match(hid_dev, mapping)) {
    242268                                usb_log_debug("IDs matched.\n");
    243                                 matched = true;
     269                                ids_matched = true;
    244270                        }
    245271                }
    246272
    247                 /* Check usage match. */
    248273                if (mapping->usage_path != NULL) {
    249274                        usb_log_debug("Comparing device against usage path.\n");
    250275                        if (usb_hid_path_matches(hid_dev, mapping)) {
    251                                 /* Does not matter if IDs were matched. */
     276                                // does not matter if IDs were matched
    252277                                matched = true;
    253278                        }
     279                } else {
     280                        // matched only if IDs were matched and there is no path
     281                        matched = ids_matched;
    254282                }
    255283
     
    258286                        subdrivers[count++] = &mapping->subdriver;
    259287                }
     288
     289                mapping = &usb_hid_subdrivers[++i];
    260290        }
    261291
    262292        /* 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?
    263295        return usb_hid_save_subdrivers(hid_dev, subdrivers, count);
    264296}
    265 /*----------------------------------------------------------------------------*/
     297
     298/*----------------------------------------------------------------------------*/
     299
    266300static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, const usb_device_t *dev)
    267301{
     
    269303        assert(dev);
    270304
    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 /*----------------------------------------------------------------------------*/
     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
    293328static int usb_hid_init_report(usb_hid_dev_t *hid_dev)
    294329{
     
    322357        return EOK;
    323358}
    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  */
     359
     360/*----------------------------------------------------------------------------*/
     361
    342362int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev)
    343363{
    344         assert(hid_dev);
    345         assert(dev);
     364        int rc, i;
    346365
    347366        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        }
    348379
    349380        usb_hid_report_init(&hid_dev->report);
     
    353384        hid_dev->poll_pipe_index = -1;
    354385
    355         int rc = usb_hid_check_pipes(hid_dev, dev);
     386        rc = usb_hid_check_pipes(hid_dev, dev);
    356387        if (rc != EOK) {
    357388                return rc;
     
    359390
    360391        /* Get the report descriptor and parse it. */
    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. */
     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
    366397        if (rc == EOK) {
    367                 usb_hid_find_subdrivers(hid_dev);
     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                }
    368408        } else {
    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 
     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
    383416                switch (hid_dev->poll_pipe_index) {
    384417                case USB_HID_KBD_POLL_EP_NO:
     
    386419                        rc = usb_kbd_set_boot_protocol(hid_dev);
    387420                        if (rc == EOK) {
    388                                 usb_hid_set_boot_kbd_subdriver(hid_dev);
     421                                rc = usb_hid_set_boot_kbd_subdriver(hid_dev);
    389422                        }
    390423                        break;
     
    393426                        rc = usb_mouse_set_boot_protocol(hid_dev);
    394427                        if (rc == EOK) {
    395                                 usb_hid_set_boot_mouse_subdriver(hid_dev);
     428                                rc = usb_hid_set_boot_mouse_subdriver(hid_dev);
    396429                        }
    397430                        break;
     
    399432                        assert(hid_dev->poll_pipe_index
    400433                            == USB_HID_GENERIC_POLL_EP_NO);
     434
    401435                        usb_log_info("Falling back to generic HID driver.\n");
    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;
     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                                }
    438463                        } else {
    439                                 /* At least one subdriver initialized. */
    440464                                ok = true;
    441465                        }
    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 */
     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
    451474                rc = usb_hid_init_report(hid_dev);
    452475                if (rc != EOK) {
     
    458481        return rc;
    459482}
    460 /*----------------------------------------------------------------------------*/
     483
     484/*----------------------------------------------------------------------------*/
     485
    461486bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
    462487    size_t buffer_size, void *arg)
     
    491516        bool cont = false;
    492517        /* Continue if at least one of the subdrivers want to continue */
    493         for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) {
     518        for (int i = 0; i < hid_dev->subdriver_count; ++i) {
    494519                if (hid_dev->subdrivers[i].poll != NULL) {
    495520                        cont = cont || hid_dev->subdrivers[i].poll(
     
    500525        return cont;
    501526}
    502 /*----------------------------------------------------------------------------*/
     527
     528/*----------------------------------------------------------------------------*/
     529
    503530void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, void *arg)
    504531{
     
    508535        usb_hid_dev_t *hid_dev = arg;
    509536
    510         for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) {
     537        for (int i = 0; i < hid_dev->subdriver_count; ++i) {
    511538                if (hid_dev->subdrivers[i].poll_end != NULL) {
    512539                        hid_dev->subdrivers[i].poll_end(
     
    517544        hid_dev->running = false;
    518545}
    519 /*----------------------------------------------------------------------------*/
     546
     547/*----------------------------------------------------------------------------*/
     548
    520549void usb_hid_new_report(usb_hid_dev_t *hid_dev)
    521550{
    522551        ++hid_dev->report_nr;
    523552}
    524 /*----------------------------------------------------------------------------*/
     553
     554/*----------------------------------------------------------------------------*/
     555
    525556int usb_hid_report_number(const usb_hid_dev_t *hid_dev)
    526557{
    527558        return hid_dev->report_nr;
    528559}
    529 /*----------------------------------------------------------------------------*/
     560
     561/*----------------------------------------------------------------------------*/
     562
    530563void usb_hid_deinit(usb_hid_dev_t *hid_dev)
    531564{
     
    537570            hid_dev->subdrivers, hid_dev->subdriver_count);
    538571
    539         for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) {
     572        for (int i = 0; i < hid_dev->subdriver_count; ++i) {
    540573                if (hid_dev->subdrivers[i].deinit != NULL) {
    541574                        hid_dev->subdrivers[i].deinit(hid_dev,
Note: See TracChangeset for help on using the changeset viewer.