Ignore:
File:
1 edited

Legend:

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

    r93d2684 r2d1ba51  
    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.