Ignore:
Timestamp:
2011-11-10T11:29:10Z (14 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/multimedia/multimedia.c

    r2e1b9dc r747ef72  
    6767        /** IPC session to the console device (for sending key events). */
    6868        async_sess_t *console_sess;
    69         /** DDF function */
    70         ddf_fun_t *fun;
    7169} usb_multimedia_t;
    7270
    7371
    7472/*----------------------------------------------------------------------------*/
    75 /** 
     73/**
    7674 * Default handler for IPC methods not handled by DDF.
    7775 *
     
    8886{
    8987        usb_log_debug(NAME " default_connection_handler()\n");
    90 
    91         usb_multimedia_t *multim_dev = (usb_multimedia_t *)fun->driver_data;
    92 
    93         if (multim_dev == NULL) {
     88        if (fun == NULL || fun->driver_data == NULL) {
    9489                async_answer_0(icallid, EINVAL);
    9590                return;
    9691        }
     92
     93        usb_multimedia_t *multim_dev = fun->driver_data;
    9794
    9895        async_sess_t *sess =
     
    109106                async_answer_0(icallid, EINVAL);
    110107}
    111 
    112 /*----------------------------------------------------------------------------*/
    113 
     108/*----------------------------------------------------------------------------*/
    114109static ddf_dev_ops_t multimedia_ops = {
    115110        .default_handler = default_connection_handler
    116111};
    117 
    118112/*----------------------------------------------------------------------------*/
    119113/**
     
    127121 *       sends also these keys to application (otherwise it cannot use those
    128122 *       keys at all).
    129  * 
    130  * @param hid_dev 
    131  * @param lgtch_dev
    132  * @param type Type of the event (press / release). Recognized values: 
     123 *
     124 * @param hid_dev
     125 * @param multim_dev
     126 * @param type Type of the event (press / release). Recognized values:
    133127 *             KEY_PRESS, KEY_RELEASE
    134128 * @param key Key code of the key according to HID Usage Tables.
    135129 */
    136 static void usb_multimedia_push_ev(usb_hid_dev_t *hid_dev,
     130static void usb_multimedia_push_ev(
    137131    usb_multimedia_t *multim_dev, int type, unsigned int key)
    138132{
    139         assert(hid_dev != NULL);
    140133        assert(multim_dev != NULL);
    141134
    142         kbd_event_t ev;
    143 
    144         ev.type = type;
    145         ev.key = key;
    146         ev.mods = 0;
    147         ev.c = 0;
     135        const kbd_event_t ev = {
     136                .type = type,
     137                .key = key,
     138                .mods = 0,
     139                .c = 0,
     140        };
    148141
    149142        usb_log_debug2(NAME " Sending key %d to the console\n", ev.key);
     
    155148
    156149        async_exch_t *exch = async_exchange_begin(multim_dev->console_sess);
    157         async_msg_4(exch, KBDEV_EVENT, ev.type, ev.key, ev.mods, ev.c);
    158         async_exchange_end(exch);
    159 }
    160 
    161 /*----------------------------------------------------------------------------*/
    162 
     150        if (exch != NULL) {
     151                async_msg_4(exch, KBDEV_EVENT, ev.type, ev.key, ev.mods, ev.c);
     152                async_exchange_end(exch);
     153        } else {
     154                usb_log_warning("Failed to send multimedia key.\n");
     155        }
     156}
     157/*----------------------------------------------------------------------------*/
    163158int usb_multimedia_init(struct usb_hid_dev *hid_dev, void **data)
    164159{
    165160        if (hid_dev == NULL || hid_dev->usb_dev == NULL) {
    166                 return EINVAL; /*! @todo Other return code? */
     161                return EINVAL;
    167162        }
    168163
     
    187182
    188183        multim_dev->console_sess = NULL;
    189         multim_dev->fun = fun;
    190184
    191185        //todo Autorepeat?
     
    199193        }
    200194
    201         usb_log_debug("%s function created (handle: %" PRIun ").\n",
    202             NAME, fun->handle);
     195        usb_log_debug(NAME " function created (handle: %" PRIun ").\n",
     196            fun->handle);
    203197
    204198        rc = ddf_fun_add_to_category(fun, "keyboard");
     
    207201                    "Could not add DDF function to category 'keyboard': %s.\n",
    208202                    str_error(rc));
    209                 ddf_fun_destroy(fun);
     203                if (ddf_fun_unbind(fun) != EOK) {
     204                        usb_log_error("Failed to unbind %s, won't destroy.\n",
     205                            fun->name);
     206                } else {
     207                        ddf_fun_destroy(fun);
     208                }
    210209                return rc;
    211210        }
    212211
    213212        /* Save the KBD device structure into the HID device structure. */
    214         *data = multim_dev;
     213        *data = fun;
    215214
    216215        usb_log_debug(NAME " HID/multimedia structure initialized.\n");
    217216        return EOK;
    218217}
    219 
    220 /*----------------------------------------------------------------------------*/
    221 
     218/*----------------------------------------------------------------------------*/
    222219void usb_multimedia_deinit(struct usb_hid_dev *hid_dev, void *data)
    223220{
    224         if (hid_dev == NULL) {
    225                 return;
    226         }
    227 
    228         if (data != NULL) {
    229                 usb_multimedia_t *multim_dev = (usb_multimedia_t *)data;
    230                 // hangup session to the console
    231                 async_hangup(multim_dev->console_sess);
    232                 const int ret = ddf_fun_unbind(multim_dev->fun);
    233                 if (ret != EOK) {
    234                         usb_log_error("Failed to unbind multim function.\n");
     221        ddf_fun_t *fun = data;
     222        if (fun != NULL && fun->driver_data != NULL) {
     223                usb_multimedia_t *multim_dev = fun->driver_data;
     224                /* Hangup session to the console */
     225                if (multim_dev->console_sess)
     226                        async_hangup(multim_dev->console_sess);
     227                if (ddf_fun_unbind(fun) != EOK) {
     228                        usb_log_error("Failed to unbind %s, won't destroy.\n",
     229                            fun->name);
    235230                } else {
    236                         usb_log_debug2("%s unbound.\n", multim_dev->fun->name);
    237                         ddf_fun_destroy(multim_dev->fun);
     231                        usb_log_debug2("%s unbound.\n", fun->name);
     232                        /* This frees multim_dev too as it was stored in
     233                         * fun->data */
     234                        ddf_fun_destroy(fun);
    238235                }
    239         }
    240 }
    241 
    242 /*----------------------------------------------------------------------------*/
    243 
     236        } else {
     237                usb_log_error(
     238                    "Failed to deinit multimedia subdriver, data missing.\n");
     239        }
     240}
     241/*----------------------------------------------------------------------------*/
    244242bool usb_multimedia_polling_callback(struct usb_hid_dev *hid_dev, void *data)
    245243{
    246244        // TODO: checks
    247         if (hid_dev == NULL || data == NULL) {
     245        ddf_fun_t *fun = data;
     246        if (hid_dev == NULL || fun == NULL || fun->driver_data == NULL) {
    248247                return false;
    249248        }
    250249
    251         usb_multimedia_t *multim_dev = (usb_multimedia_t *)data;
     250        usb_multimedia_t *multim_dev = fun->driver_data;
    252251
    253252        usb_hid_report_path_t *path = usb_hid_report_path();
    254         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
     253        if (path == NULL)
     254                return true; /* This might be a temporary failure. */
     255
     256        int ret =
     257            usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
     258        if (ret != EOK) {
     259                usb_hid_report_path_free(path);
     260                return true; /* This might be a temporary failure. */
     261        }
    255262
    256263        usb_hid_report_path_set_report_id(path, hid_dev->report_id);
     
    261268            USB_HID_REPORT_TYPE_INPUT);
    262269
    263         /*! @todo Is this iterating OK if done multiple times?
    264          *  @todo The parsing is not OK
    265          */
     270        //FIXME Is this iterating OK if done multiple times?
     271        //FIXME The parsing is not OK. (what's wrong?)
    266272        while (field != NULL) {
    267                 if(field->value != 0) {
    268                         usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n", 
     273                if (field->value != 0) {
     274                        usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n",
    269275                            field->value, field->usage);
    270                         unsigned int key =
     276                        const unsigned key =
    271277                            usb_multimedia_map_usage(field->usage);
    272                         const char *key_str = 
     278                        const char *key_str =
    273279                            usbhid_multimedia_usage_to_str(field->usage);
    274280                        usb_log_info("Pressed key: %s\n", key_str);
    275                         usb_multimedia_push_ev(hid_dev, multim_dev, KEY_PRESS,
    276                                                key);
     281                        usb_multimedia_push_ev(multim_dev, KEY_PRESS, key);
    277282                }
    278283
    279284                field = usb_hid_report_get_sibling(
    280285                    &hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
    281                     | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
     286                    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    282287                    USB_HID_REPORT_TYPE_INPUT);
    283288        }
     
    287292        return true;
    288293}
    289 
    290294/**
    291295 * @}
Note: See TracChangeset for help on using the changeset viewer.