Changeset e1dbcbc in mainline for uspace/drv/usbhid/usbhid.c


Ignore:
Timestamp:
2011-04-29T13:43:01Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a81a1d09
Parents:
380e0364 (diff), f19f1b7 (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 development/ changes

File:
1 edited

Legend:

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

    r380e0364 re1dbcbc  
    4242#include <usb/classes/hidreq.h>
    4343#include <errno.h>
     44#include <str_error.h>
    4445
    4546#include "usbhid.h"
     
    4748#include "kbd/kbddev.h"
    4849#include "generic/hiddev.h"
    49 
    50 /*----------------------------------------------------------------------------*/
    51 
    52 /** Mouse polling endpoint description for boot protocol class. */
    53 static usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description = {
    54         .transfer_type = USB_TRANSFER_INTERRUPT,
    55         .direction = USB_DIRECTION_IN,
    56         .interface_class = USB_CLASS_HID,
    57         .interface_subclass = USB_HID_SUBCLASS_BOOT,
    58         .interface_protocol = USB_HID_PROTOCOL_MOUSE,
    59         .flags = 0
    60 };
     50#include "mouse/mousedev.h"
     51#include "subdrivers.h"
     52
     53/*----------------------------------------------------------------------------*/
    6154
    6255/* Array of endpoints expected on the device, NULL terminated. */
     
    6861};
    6962
    70 static const char *HID_MOUSE_FUN_NAME = "mouse";
    71 static const char *HID_MOUSE_CLASS_NAME = "mouse";
     63static const int USB_HID_MAX_SUBDRIVERS = 10;
     64
     65/*----------------------------------------------------------------------------*/
     66
     67static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev)
     68{
     69        assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
     70       
     71        hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
     72            sizeof(usb_hid_subdriver_t));
     73        if (hid_dev->subdrivers == NULL) {
     74                return ENOMEM;
     75        }
     76       
     77        // set the init callback
     78        hid_dev->subdrivers[0].init = usb_kbd_init;
     79       
     80        // set the polling callback
     81        hid_dev->subdrivers[0].poll = usb_kbd_polling_callback;
     82       
     83        // set the polling ended callback
     84        hid_dev->subdrivers[0].poll_end = NULL;
     85       
     86        // set the deinit callback
     87        hid_dev->subdrivers[0].deinit = usb_kbd_deinit;
     88       
     89        // set subdriver count
     90        hid_dev->subdriver_count = 1;
     91       
     92        return EOK;
     93}
     94
     95/*----------------------------------------------------------------------------*/
     96
     97static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev)
     98{
     99        assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
     100       
     101        hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
     102            sizeof(usb_hid_subdriver_t));
     103        if (hid_dev->subdrivers == NULL) {
     104                return ENOMEM;
     105        }
     106       
     107        // set the init callback
     108        hid_dev->subdrivers[0].init = usb_mouse_init;
     109       
     110        // set the polling callback
     111        hid_dev->subdrivers[0].poll = usb_mouse_polling_callback;
     112       
     113        // set the polling ended callback
     114        hid_dev->subdrivers[0].poll_end = NULL;
     115       
     116        // set the deinit callback
     117        hid_dev->subdrivers[0].deinit = usb_mouse_deinit;
     118       
     119        // set subdriver count
     120        hid_dev->subdriver_count = 1;
     121       
     122        return EOK;
     123}
     124
     125/*----------------------------------------------------------------------------*/
     126
     127static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev)
     128{
     129        assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
     130       
     131        hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
     132            sizeof(usb_hid_subdriver_t));
     133        if (hid_dev->subdrivers == NULL) {
     134                return ENOMEM;
     135        }
     136       
     137        // set the init callback
     138        hid_dev->subdrivers[0].init = NULL;
     139       
     140        // set the polling callback
     141        hid_dev->subdrivers[0].poll = usb_generic_hid_polling_callback;
     142       
     143        // set the polling ended callback
     144        hid_dev->subdrivers[0].poll_end = NULL;
     145       
     146        // set the deinit callback
     147        hid_dev->subdrivers[0].deinit = NULL;
     148       
     149        // set subdriver count
     150        hid_dev->subdriver_count = 1;
     151       
     152        return EOK;
     153}
     154
     155/*----------------------------------------------------------------------------*/
     156
     157static bool usb_hid_ids_match(usb_hid_dev_t *hid_dev,
     158    const usb_hid_subdriver_mapping_t *mapping)
     159{
     160        assert(hid_dev != NULL);
     161        assert(hid_dev->usb_dev != NULL);
     162       
     163        return (hid_dev->usb_dev->descriptors.device.vendor_id
     164            == mapping->vendor_id
     165            && hid_dev->usb_dev->descriptors.device.product_id
     166            == mapping->product_id);
     167}
     168
     169/*----------------------------------------------------------------------------*/
     170
     171static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev,
     172    const usb_hid_subdriver_mapping_t *mapping)
     173{
     174        assert(hid_dev != NULL);
     175        assert(mapping != NULL);
     176       
     177        usb_hid_report_path_t *usage_path = usb_hid_report_path();
     178        if (usage_path == NULL) {
     179                usb_log_debug("Failed to create usage path.\n");
     180                return false;
     181        }
     182        int i = 0;
     183        while (mapping->usage_path[i].usage != 0
     184            || mapping->usage_path[i].usage_page != 0) {
     185                if (usb_hid_report_path_append_item(usage_path,
     186                    mapping->usage_path[i].usage_page,
     187                    mapping->usage_path[i].usage) != EOK) {
     188                        usb_log_debug("Failed to append to usage path.\n");
     189                        usb_hid_report_path_free(usage_path);
     190                        return false;
     191                }
     192                ++i;
     193        }
     194       
     195        if (mapping->report_id >= 0) {
     196                usb_hid_report_path_set_report_id(usage_path,
     197                    mapping->report_id);
     198        }
     199       
     200        assert(hid_dev->report != NULL);
     201       
     202        usb_log_debug("Compare flags: %d\n", mapping->compare);
     203        size_t size = usb_hid_report_input_length(hid_dev->report, usage_path,
     204            mapping->compare);
     205        usb_log_debug("Size of the input report: %zuB\n", size);
     206       
     207        usb_hid_report_path_free(usage_path);
     208       
     209        return (size > 0);
     210}
     211
     212/*----------------------------------------------------------------------------*/
     213
     214static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev,
     215    const usb_hid_subdriver_t **subdrivers, int count)
     216{
     217        int i;
     218       
     219        if (count <= 0) {
     220                hid_dev->subdriver_count = 0;
     221                hid_dev->subdrivers = NULL;
     222                return EOK;
     223        }
     224       
     225        hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(count *
     226            sizeof(usb_hid_subdriver_t));
     227        if (hid_dev->subdrivers == NULL) {
     228                return ENOMEM;
     229        }
     230       
     231        for (i = 0; i < count; ++i) {
     232                hid_dev->subdrivers[i].init = subdrivers[i]->init;
     233                hid_dev->subdrivers[i].deinit = subdrivers[i]->deinit;
     234                hid_dev->subdrivers[i].poll = subdrivers[i]->poll;
     235                hid_dev->subdrivers[i].poll_end = subdrivers[i]->poll_end;
     236        }
     237       
     238        hid_dev->subdriver_count = count;
     239       
     240        return EOK;
     241}
     242
     243/*----------------------------------------------------------------------------*/
     244
     245static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev)
     246{
     247        assert(hid_dev != NULL);
     248       
     249        const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS];
     250       
     251        int i = 0, count = 0;
     252        const usb_hid_subdriver_mapping_t *mapping = &usb_hid_subdrivers[i];
     253
     254        bool ids_matched;
     255        bool matched;
     256       
     257        while (count < USB_HID_MAX_SUBDRIVERS &&
     258            (mapping->usage_path != NULL
     259            || mapping->vendor_id >= 0 || mapping->product_id >= 0)) {
     260                // check the vendor & product ID
     261                if (mapping->vendor_id >= 0 && mapping->product_id < 0) {
     262                        usb_log_warning("Missing Product ID for Vendor ID %d\n",
     263                            mapping->vendor_id);
     264                        return EINVAL;
     265                }
     266                if (mapping->product_id >= 0 && mapping->vendor_id < 0) {
     267                        usb_log_warning("Missing Vendor ID for Product ID %d\n",
     268                            mapping->product_id);
     269                        return EINVAL;
     270                }
     271               
     272                ids_matched = false;
     273                matched = false;
     274               
     275                if (mapping->vendor_id >= 0) {
     276                        assert(mapping->product_id >= 0);
     277                        usb_log_debug("Comparing device against vendor ID %u"
     278                            " and product ID %u.\n", mapping->vendor_id,
     279                            mapping->product_id);
     280                        if (usb_hid_ids_match(hid_dev, mapping)) {
     281                                usb_log_debug("IDs matched.\n");
     282                                ids_matched = true;
     283                        }
     284                }
     285               
     286                if (mapping->usage_path != NULL) {
     287                        usb_log_debug("Comparing device against usage path.\n");
     288                        if (usb_hid_path_matches(hid_dev, mapping)) {
     289                                // does not matter if IDs were matched
     290                                matched = true;
     291                        }
     292                } else {
     293                        // matched only if IDs were matched and there is no path
     294                        matched = ids_matched;
     295                }
     296               
     297                if (matched) {
     298                        subdrivers[count++] = &mapping->subdriver;
     299                }
     300               
     301                mapping = &usb_hid_subdrivers[++i];
     302        }
     303       
     304        // we have all subdrivers determined, save them into the hid device
     305        return usb_hid_save_subdrivers(hid_dev, subdrivers, count);
     306}
     307
     308/*----------------------------------------------------------------------------*/
     309
     310static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
     311{
     312        assert(hid_dev != NULL && dev != NULL);
     313       
     314        int rc = EOK;
     315       
     316        if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
     317                usb_log_debug("Found keyboard endpoint.\n");
     318                // save the pipe index
     319                hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
     320        } else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
     321                usb_log_debug("Found mouse endpoint.\n");
     322                // save the pipe index
     323                hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
     324        } else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
     325                usb_log_debug("Found generic HID endpoint.\n");
     326                // save the pipe index
     327                hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
     328        } else {
     329                usb_log_error("None of supported endpoints found - probably"
     330                    " not a supported device.\n");
     331                rc = ENOTSUP;
     332        }
     333       
     334        return rc;
     335}
    72336
    73337/*----------------------------------------------------------------------------*/
     
    83347        }
    84348       
    85         hid_dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(
    86             usb_hid_report_parser_t)));
    87         if (hid_dev->parser == NULL) {
     349        hid_dev->report = (usb_hid_report_t *)(malloc(sizeof(
     350            usb_hid_report_t)));
     351        if (hid_dev->report == NULL) {
    88352                usb_log_fatal("No memory!\n");
    89353                free(hid_dev);
     
    91355        }
    92356       
     357        hid_dev->poll_pipe_index = -1;
     358       
    93359        return hid_dev;
    94360}
     
    96362/*----------------------------------------------------------------------------*/
    97363
    98 static bool usb_dummy_polling_callback(usb_device_t *dev, uint8_t *buffer,
    99      size_t buffer_size, void *arg)
    100 {
    101         usb_log_debug("Dummy polling callback.\n");
    102         return false;
    103 }
    104 
    105 /*----------------------------------------------------------------------------*/
    106 
    107 static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
    108 {
    109         if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
    110                 usb_log_debug("Found keyboard endpoint.\n");
    111                
    112                 // save the pipe index and device type
    113                 hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
    114                 hid_dev->device_type = USB_HID_PROTOCOL_KEYBOARD;
    115                
    116                 // set the polling callback
    117                 hid_dev->poll_callback = usb_kbd_polling_callback;
    118 
    119         } else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
    120                 usb_log_debug("Found mouse endpoint.\n");
    121                
    122                 // save the pipe index and device type
    123                 hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
    124                 hid_dev->device_type = USB_HID_PROTOCOL_MOUSE;
    125                
    126                 // set the polling callback
    127                 hid_dev->poll_callback = usb_dummy_polling_callback;
    128                
    129         } else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
    130                 usb_log_debug("Found generic HID endpoint.\n");
    131                
    132                 // save the pipe index and device type
    133                 hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
    134                 hid_dev->device_type = USB_HID_PROTOCOL_NONE;
    135                
    136                 // set the polling callback
    137                 hid_dev->poll_callback = usb_hid_polling_callback;
    138                
    139         } else {
    140                 usb_log_warning("None of supported endpoints found - probably"
    141                     " not a supported device.\n");
    142                 return ENOTSUP;
    143         }
    144        
    145         return EOK;
    146 }
    147 
    148 /*----------------------------------------------------------------------------*/
    149 
    150 static int usb_hid_init_parser(usb_hid_dev_t *hid_dev)
    151 {
    152         /* Initialize the report parser. */
    153         int rc = usb_hid_parser_init(hid_dev->parser);
    154         if (rc != EOK) {
    155                 usb_log_error("Failed to initialize report parser.\n");
    156                 return rc;
    157         }
    158        
    159         /* Get the report descriptor and parse it. */
    160         rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
    161             hid_dev->parser);
    162        
    163         if (rc != EOK) {
    164                 usb_log_warning("Could not process report descriptor.\n");
    165                
    166                 if (hid_dev->device_type == USB_HID_PROTOCOL_KEYBOARD) {
    167                         usb_log_warning("Falling back to boot protocol.\n");
    168                        
    169                         rc = usb_kbd_set_boot_protocol(hid_dev);
    170                        
    171                 } else if (hid_dev->device_type == USB_HID_PROTOCOL_MOUSE) {
    172                         usb_log_warning("No boot protocol for mouse yet.\n");
    173                         rc = ENOTSUP;
    174                 }
    175         }
    176        
    177         return rc;
    178 }
    179 
    180 /*----------------------------------------------------------------------------*/
    181 
    182364int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev)
    183365{
    184         int rc;
     366        int rc, i;
    185367       
    186368        usb_log_debug("Initializing HID structure...\n");
     
    203385        rc = usb_hid_check_pipes(hid_dev, dev);
    204386        if (rc != EOK) {
     387                //usb_hid_free(&hid_dev);
    205388                return rc;
    206389        }
    207        
    208         rc = usb_hid_init_parser(hid_dev);
     390               
     391        /* Get the report descriptor and parse it. */
     392        rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
     393            hid_dev->report);
     394       
     395        bool fallback = false;
     396       
     397        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                }
     408        } 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        // TODO: remove the mouse hack
     415        if (hid_dev->poll_pipe_index == USB_HID_MOUSE_POLL_EP_NO ||
     416            fallback) {
     417                // fall back to boot protocol
     418                switch (hid_dev->poll_pipe_index) {
     419                case USB_HID_KBD_POLL_EP_NO:
     420                        usb_log_info("Falling back to kbd boot protocol.\n");
     421                        rc = usb_kbd_set_boot_protocol(hid_dev);
     422                        if (rc == EOK) {
     423                                rc = usb_hid_set_boot_kbd_subdriver(hid_dev);
     424                        }
     425                        break;
     426                case USB_HID_MOUSE_POLL_EP_NO:
     427                        usb_log_info("Falling back to mouse boot protocol.\n");
     428                        rc = usb_mouse_set_boot_protocol(hid_dev);
     429                        if (rc == EOK) {
     430                                rc = usb_hid_set_boot_mouse_subdriver(hid_dev);
     431                        }
     432                        break;
     433                default:
     434                        assert(hid_dev->poll_pipe_index
     435                            == USB_HID_GENERIC_POLL_EP_NO);
     436                       
     437                        /* TODO: this has no meaning if the report descriptor
     438                                 is not parsed */
     439                        usb_log_info("Falling back to generic HID driver.\n");
     440                        rc = usb_hid_set_generic_hid_subdriver(hid_dev);
     441                }
     442        }
     443       
    209444        if (rc != EOK) {
    210                 usb_log_error("Failed to initialize HID parser.\n");
    211                 return rc;
    212         }
    213        
    214         switch (hid_dev->device_type) {
    215         case USB_HID_PROTOCOL_KEYBOARD:
    216                 // initialize the keyboard structure
    217                 rc = usb_kbd_init(hid_dev);
    218                 if (rc != EOK) {
    219                         usb_log_warning("Failed to initialize KBD structure."
    220                             "\n");
    221                 }
    222                 break;
    223         case USB_HID_PROTOCOL_MOUSE:
    224                 break;
    225         default:
    226 //              usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    227 //                  hid_dev->usb_dev->interface_no, 0);
    228                 break;
     445                usb_log_error("No subdriver for handling this device could be"
     446                    " initialized: %s.\n", str_error(rc));
     447                usb_log_debug("Subdriver count: %d\n",
     448                    hid_dev->subdriver_count);
     449                //usb_hid_free(&hid_dev);
     450        } else {
     451                bool ok = false;
     452               
     453                usb_log_debug("Subdriver count: %d\n",
     454                    hid_dev->subdriver_count);
     455               
     456                for (i = 0; i < hid_dev->subdriver_count; ++i) {
     457                        if (hid_dev->subdrivers[i].init != NULL) {
     458                                usb_log_debug("Initializing subdriver %d.\n",i);
     459                                rc = hid_dev->subdrivers[i].init(hid_dev);
     460                                if (rc != EOK) {
     461                                        usb_log_warning("Failed to initialize"
     462                                            " HID subdriver structure.\n");
     463                                } else {
     464                                        // at least one subdriver initialized
     465                                        ok = true;
     466                                }
     467                        } else {
     468                                ok = true;
     469                        }
     470                }
     471               
     472                rc = (ok) ? EOK : -1;   // what error to report
    229473        }
    230474       
    231475        return rc;
     476}
     477
     478/*----------------------------------------------------------------------------*/
     479
     480bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
     481    size_t buffer_size, void *arg)
     482{
     483        int i;
     484       
     485        if (dev == NULL || arg == NULL || buffer == NULL) {
     486                usb_log_error("Missing arguments to polling callback.\n");
     487                return false;
     488        }
     489       
     490        usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
     491       
     492        bool cont = false;
     493       
     494        // continue if at least one of the subdrivers want to continue
     495        for (i = 0; i < hid_dev->subdriver_count; ++i) {
     496                if (hid_dev->subdrivers[i].poll != NULL
     497                    && hid_dev->subdrivers[i].poll(hid_dev, buffer,
     498                    buffer_size)) {
     499                        cont = true;
     500                }
     501        }
     502       
     503        return cont;
    232504}
    233505
     
    237509     void *arg)
    238510{
     511        int i;
     512       
    239513        if (dev == NULL || arg == NULL) {
    240514                return;
     
    243517        usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
    244518       
     519        for (i = 0; i < hid_dev->subdriver_count; ++i) {
     520                if (hid_dev->subdrivers[i].poll_end != NULL) {
     521                        hid_dev->subdrivers[i].poll_end(hid_dev, reason);
     522                }
     523        }
     524       
    245525        usb_hid_free(&hid_dev);
    246526}
     
    248528/*----------------------------------------------------------------------------*/
    249529
    250 const char *usb_hid_get_function_name(usb_hid_iface_protocol_t device_type)
    251 {
    252         switch (device_type) {
    253         case USB_HID_PROTOCOL_KEYBOARD:
     530const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev)
     531{
     532        switch (hid_dev->poll_pipe_index) {
     533        case USB_HID_KBD_POLL_EP_NO:
    254534                return HID_KBD_FUN_NAME;
    255535                break;
    256         case USB_HID_PROTOCOL_MOUSE:
     536        case USB_HID_MOUSE_POLL_EP_NO:
    257537                return HID_MOUSE_FUN_NAME;
    258538                break;
     
    264544/*----------------------------------------------------------------------------*/
    265545
    266 const char *usb_hid_get_class_name(usb_hid_iface_protocol_t device_type)
    267 {
    268         switch (device_type) {
    269         case USB_HID_PROTOCOL_KEYBOARD:
     546const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev)
     547{
     548        // this means that only boot protocol keyboards will be connected
     549        // to the console; there is probably no better way to do this
     550       
     551        switch (hid_dev->poll_pipe_index) {
     552        case USB_HID_KBD_POLL_EP_NO:
    270553                return HID_KBD_CLASS_NAME;
    271554                break;
    272         case USB_HID_PROTOCOL_MOUSE:
     555        case USB_HID_MOUSE_POLL_EP_NO:
    273556                return HID_MOUSE_CLASS_NAME;
    274557                break;
     
    282565void usb_hid_free(usb_hid_dev_t **hid_dev)
    283566{
     567        int i;
     568       
    284569        if (hid_dev == NULL || *hid_dev == NULL) {
    285570                return;
    286571        }
    287572       
    288         switch ((*hid_dev)->device_type) {
    289         case USB_HID_PROTOCOL_KEYBOARD:
    290                 usb_kbd_deinit(*hid_dev);
    291                 break;
    292         case USB_HID_PROTOCOL_MOUSE:
    293                 break;
    294         default:
    295                 break;
     573        usb_log_debug("Subdrivers: %p, subdriver count: %d\n",
     574            (*hid_dev)->subdrivers, (*hid_dev)->subdriver_count);
     575       
     576        assert((*hid_dev)->subdrivers != NULL
     577            || (*hid_dev)->subdriver_count == 0);
     578       
     579        for (i = 0; i < (*hid_dev)->subdriver_count; ++i) {
     580                if ((*hid_dev)->subdrivers[i].deinit != NULL) {
     581                        (*hid_dev)->subdrivers[i].deinit(*hid_dev);
     582                }
     583        }
     584       
     585        // free the subdrivers info
     586        if ((*hid_dev)->subdrivers != NULL) {
     587                free((*hid_dev)->subdrivers);
    296588        }
    297589
    298590        // destroy the parser
    299         if ((*hid_dev)->parser != NULL) {
    300                 usb_hid_free_report_parser((*hid_dev)->parser);
     591        if ((*hid_dev)->report != NULL) {
     592                usb_hid_free_report((*hid_dev)->report);
    301593        }
    302594
Note: See TracChangeset for help on using the changeset viewer.