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/mouse/mousedev.c

    r2e1b9dc r747ef72  
    5555#define ARROWS_PER_SINGLE_WHEEL 3
    5656
    57 #define NAME  "mouse"
     57#define NAME "mouse"
    5858
    5959/*----------------------------------------------------------------------------*/
     
    7777
    7878/*----------------------------------------------------------------------------*/
    79 
    80 enum {
    81         USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE = 63
    82 };
    83 
    84 static const uint8_t USB_MOUSE_BOOT_REPORT_DESCRIPTOR[
    85     USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE] = {
     79static const uint8_t USB_MOUSE_BOOT_REPORT_DESCRIPTOR[] = {
    8680        0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    8781        0x09, 0x02,                    // USAGE (Mouse)
     
    123117    ipc_callid_t icallid, ipc_call_t *icall)
    124118{
    125         usb_mouse_t *mouse_dev = (usb_mouse_t *) fun->driver_data;
     119        usb_mouse_t *mouse_dev = fun->driver_data;
    126120
    127121        if (mouse_dev == NULL) {
    128                 usb_log_debug("default_connection_handler: Missing "
    129                     "parameters.\n");
     122                usb_log_debug("%s: Missing parameters.\n", __FUNCTION__);
    130123                async_answer_0(icallid, EINVAL);
    131124                return;
    132125        }
    133126
    134         usb_log_debug("default_connection_handler: fun->name: %s\n",
    135                       fun->name);
    136         usb_log_debug("default_connection_handler: mouse_sess: %p, "
    137             "wheel_sess: %p\n", mouse_dev->mouse_sess, mouse_dev->wheel_sess);
    138 
    139         async_sess_t **sess_ptr =
    140             (str_cmp(fun->name, HID_MOUSE_FUN_NAME) == 0) ?
     127        usb_log_debug("%s: fun->name: %s\n", __FUNCTION__, fun->name);
     128        usb_log_debug("%s: mouse_sess: %p, wheel_sess: %p\n",
     129            __FUNCTION__, mouse_dev->mouse_sess, mouse_dev->wheel_sess);
     130
     131        async_sess_t **sess_ptr = (fun == mouse_dev->mouse_fun) ?
    141132            &mouse_dev->mouse_sess : &mouse_dev->wheel_sess;
    142133
     
    146137                if (*sess_ptr == NULL) {
    147138                        *sess_ptr = sess;
    148                         usb_log_debug("Console session to mouse set ok (%p).\n",
    149                             sess);
     139                        usb_log_debug("Console session to %s set ok (%p).\n",
     140                            fun->name, sess);
    150141                        async_answer_0(icallid, EOK);
    151142                } else {
    152                         usb_log_debug("default_connection_handler: Console "
    153                             "session to mouse already set.\n");
     143                        usb_log_error("Console session to %s already set.\n",
     144                            fun->name);
    154145                        async_answer_0(icallid, ELIMIT);
    155146                }
    156147        } else {
    157                 usb_log_debug("default_connection_handler: Invalid function.\n");
     148                usb_log_debug("%s: Invalid function.\n", __FUNCTION__);
    158149                async_answer_0(icallid, EINVAL);
    159         }
    160 }
    161 
    162 /*----------------------------------------------------------------------------*/
    163 
    164 static usb_mouse_t *usb_mouse_new(void)
    165 {
    166         usb_mouse_t *mouse = calloc(1, sizeof(usb_mouse_t));
    167         if (mouse == NULL) {
    168                 return NULL;
    169         }
    170         mouse->mouse_sess = NULL;
    171         mouse->wheel_sess = NULL;
    172 
    173         return mouse;
    174 }
    175 
    176 /*----------------------------------------------------------------------------*/
    177 
    178 static void usb_mouse_destroy(usb_mouse_t *mouse_dev)
    179 {
    180         assert(mouse_dev != NULL);
    181 
    182         // hangup session to the console
    183         if (mouse_dev->mouse_sess != NULL)
    184                 async_hangup(mouse_dev->mouse_sess);
    185 
    186         if (mouse_dev->wheel_sess != NULL)
    187                 async_hangup(mouse_dev->wheel_sess);
    188         int ret = ddf_fun_unbind(mouse_dev->mouse_fun);
    189         if (ret != EOK) {
    190                 usb_log_error("Failed to unbind mouse function.\n");
    191         } else {
    192                 ddf_fun_destroy(mouse_dev->mouse_fun);
    193                 /* Prevent double free */
    194                 mouse_dev->wheel_fun->driver_data = NULL;
    195         }
    196 
    197         ret = ddf_fun_unbind(mouse_dev->wheel_fun);
    198         if (ret != EOK) {
    199                 usb_log_error("Failed to unbind wheel function.\n");
    200         } else {
    201                 ddf_fun_destroy(mouse_dev->wheel_fun);
    202150        }
    203151}
     
    215163        }
    216164
    217         int count = ((wheel < 0) ? -wheel : wheel) * ARROWS_PER_SINGLE_WHEEL;
    218         int i;
    219 
    220         for (i = 0; i < count; i++) {
     165        const unsigned count =
     166            ((wheel < 0) ? -wheel : wheel) * ARROWS_PER_SINGLE_WHEEL;
     167        for (unsigned i = 0; i < count; i++) {
    221168                /* Send arrow press and release. */
    222169                usb_log_debug2("Sending key %d to the console\n", key);
     
    267214        }
    268215
    269         int shift_x = get_mouse_axis_move_value(hid_dev->report_id,
     216        const int shift_x = get_mouse_axis_move_value(hid_dev->report_id,
    270217            &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_X);
    271         int shift_y = get_mouse_axis_move_value(hid_dev->report_id,
     218        const int shift_y = get_mouse_axis_move_value(hid_dev->report_id,
    272219            &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_Y);
    273         int wheel = get_mouse_axis_move_value(hid_dev->report_id,
     220        const int wheel = get_mouse_axis_move_value(hid_dev->report_id,
    274221            &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL);
    275222
     
    277224                async_exch_t *exch =
    278225                    async_exchange_begin(mouse_dev->mouse_sess);
    279                 async_req_2_0(exch, MOUSEEV_MOVE_EVENT, shift_x, shift_y);
    280                 async_exchange_end(exch);
     226                if (exch != NULL) {
     227                        async_req_2_0(exch, MOUSEEV_MOVE_EVENT, shift_x, shift_y);
     228                        async_exchange_end(exch);
     229                }
    281230        }
    282231
     
    284233                usb_mouse_send_wheel(mouse_dev, wheel);
    285234
    286         /*
    287          * Buttons
    288          */
     235        /* Buttons */
    289236        usb_hid_report_path_t *path = usb_hid_report_path();
    290         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0);
     237        if (path == NULL) {
     238                usb_log_warning("Failed to create USB HID report path.\n");
     239                return true;
     240        }
     241        int ret =
     242           usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0);
     243        if (ret != EOK) {
     244                usb_hid_report_path_free(path);
     245                usb_log_warning("Failed to add buttons to report path.\n");
     246                return true;
     247        }
    291248        usb_hid_report_path_set_report_id(path, hid_dev->report_id);
    292249
     
    298255                usb_log_debug2(NAME " VALUE(%X) USAGE(%X)\n", field->value,
    299256                    field->usage);
    300                
    301                 if (mouse_dev->buttons[field->usage - field->usage_minimum] == 0
    302                     && field->value != 0) {
     257                assert(field->usage > field->usage_minimum);
     258                const unsigned index = field->usage - field->usage_minimum;
     259                assert(index < mouse_dev->buttons_count);
     260
     261                if (mouse_dev->buttons[index] == 0 && field->value != 0) {
    303262                        async_exch_t *exch =
    304263                            async_exchange_begin(mouse_dev->mouse_sess);
    305                         async_req_2_0(exch, MOUSEEV_BUTTON_EVENT, field->usage, 1);
    306                         async_exchange_end(exch);
    307                        
    308                         mouse_dev->buttons[field->usage - field->usage_minimum]
    309                             = field->value;
    310                 } else if (mouse_dev->buttons[field->usage - field->usage_minimum] != 0
    311                     && field->value == 0) {
     264                        if (exch != NULL) {
     265                                async_req_2_0(exch, MOUSEEV_BUTTON_EVENT,
     266                                    field->usage, 1);
     267                                async_exchange_end(exch);
     268                                mouse_dev->buttons[index] = field->value;
     269                        }
     270
     271                } else if (mouse_dev->buttons[index] != 0 && field->value == 0) {
    312272                        async_exch_t *exch =
    313273                            async_exchange_begin(mouse_dev->mouse_sess);
    314                         async_req_2_0(exch, MOUSEEV_BUTTON_EVENT, field->usage, 0);
    315                         async_exchange_end(exch);
    316 
    317                         mouse_dev->buttons[field->usage - field->usage_minimum] =
    318                            field->value;
     274                        if (exch != NULL) {
     275                                async_req_2_0(exch, MOUSEEV_BUTTON_EVENT,
     276                                    field->usage, 0);
     277                                async_exchange_end(exch);
     278                                mouse_dev->buttons[index] = field->value;
     279                        }
    319280                }
    320281
     
    329290        return true;
    330291}
    331 
    332 /*----------------------------------------------------------------------------*/
    333 
     292/*----------------------------------------------------------------------------*/
     293#define FUN_UNBIND_DESTROY(fun) \
     294if (fun) { \
     295        if (ddf_fun_unbind((fun)) == EOK) { \
     296                (fun)->driver_data = NULL; \
     297                ddf_fun_destroy((fun)); \
     298        } else { \
     299                usb_log_error("Could not unbind function `%s', it " \
     300                    "will not be destroyed.\n", (fun)->name); \
     301        } \
     302} else (void)0
     303/*----------------------------------------------------------------------------*/
    334304static int usb_mouse_create_function(usb_hid_dev_t *hid_dev, usb_mouse_t *mouse)
    335305{
     
    339309        /* Create the exposed function. */
    340310        usb_log_debug("Creating DDF function %s...\n", HID_MOUSE_FUN_NAME);
    341         ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
     311        ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    342312            HID_MOUSE_FUN_NAME);
    343313        if (fun == NULL) {
    344                 usb_log_error("Could not create DDF function node.\n");
     314                usb_log_error("Could not create DDF function node `%s'.\n",
     315                    HID_MOUSE_FUN_NAME);
    345316                return ENOMEM;
    346317        }
     
    351322        int rc = ddf_fun_bind(fun);
    352323        if (rc != EOK) {
    353                 usb_log_error("Could not bind DDF function: %s.\n",
    354                     str_error(rc));
    355                 return rc;
    356         }
    357 
    358         usb_log_debug("Adding DDF function to category %s...\n",
    359             HID_MOUSE_CATEGORY);
     324                usb_log_error("Could not bind DDF function `%s': %s.\n",
     325                    fun->name, str_error(rc));
     326                fun->driver_data = NULL;
     327                ddf_fun_destroy(fun);
     328                return rc;
     329        }
     330
     331        usb_log_debug("Adding DDF function `%s' to category %s...\n",
     332            fun->name, HID_MOUSE_CATEGORY);
    360333        rc = ddf_fun_add_to_category(fun, HID_MOUSE_CATEGORY);
    361334        if (rc != EOK) {
     
    363336                    "Could not add DDF function to category %s: %s.\n",
    364337                    HID_MOUSE_CATEGORY, str_error(rc));
     338                FUN_UNBIND_DESTROY(fun);
    365339                return rc;
    366340        }
     
    370344         * Special function for acting as keyboard (wheel)
    371345         */
    372         usb_log_debug("Creating DDF function %s...\n", 
     346        usb_log_debug("Creating DDF function %s...\n",
    373347                      HID_MOUSE_WHEEL_FUN_NAME);
    374         fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
     348        fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    375349            HID_MOUSE_WHEEL_FUN_NAME);
    376350        if (fun == NULL) {
    377                 usb_log_error("Could not create DDF function node.\n");
     351                usb_log_error("Could not create DDF function node `%s'.\n",
     352                    HID_MOUSE_WHEEL_FUN_NAME);
     353                FUN_UNBIND_DESTROY(mouse->mouse_fun);
     354                mouse->mouse_fun = NULL;
    378355                return ENOMEM;
    379356        }
     
    388365        rc = ddf_fun_bind(fun);
    389366        if (rc != EOK) {
    390                 usb_log_error("Could not bind DDF function: %s.\n",
    391                     str_error(rc));
     367                usb_log_error("Could not bind DDF function `%s': %s.\n",
     368                    fun->name, str_error(rc));
     369                FUN_UNBIND_DESTROY(mouse->mouse_fun);
     370                mouse->mouse_fun = NULL;
     371
     372                fun->driver_data = NULL;
     373                ddf_fun_destroy(fun);
    392374                return rc;
    393375        }
     
    400382                    "Could not add DDF function to category %s: %s.\n",
    401383                    HID_MOUSE_WHEEL_CATEGORY, str_error(rc));
     384
     385                FUN_UNBIND_DESTROY(mouse->mouse_fun);
     386                mouse->mouse_fun = NULL;
     387                FUN_UNBIND_DESTROY(fun);
    402388                return rc;
    403389        }
     
    448434        return highest_button;
    449435}
    450 
    451 /*----------------------------------------------------------------------------*/
    452 
     436/*----------------------------------------------------------------------------*/
    453437int usb_mouse_init(usb_hid_dev_t *hid_dev, void **data)
    454438{
     
    461445        }
    462446
    463         usb_mouse_t *mouse_dev = usb_mouse_new();
     447        usb_mouse_t *mouse_dev = calloc(1, sizeof(usb_mouse_t));
    464448        if (mouse_dev == NULL) {
    465449                usb_log_error("Error while creating USB/HID Mouse device "
     
    484468        }
    485469
    486 
    487         // save the Mouse device structure into the HID device structure
    488         *data = mouse_dev;
    489 
    490470        // set handler for incoming calls
    491471        mouse_dev->ops.default_handler = default_connection_handler;
    492472
    493473        // TODO: how to know if the device supports the request???
    494         usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 
     474        usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    495475            hid_dev->usb_dev->interface_no, IDLE_RATE);
    496476
    497477        int rc = usb_mouse_create_function(hid_dev, mouse_dev);
    498478        if (rc != EOK) {
    499                 usb_mouse_destroy(mouse_dev);
    500                 return rc;
    501         }
     479                free(mouse_dev->buttons);
     480                free(mouse_dev);
     481                return rc;
     482        }
     483
     484        /* Save the Mouse device structure into the HID device structure. */
     485        *data = mouse_dev;
    502486
    503487        return EOK;
    504488}
    505 
    506 /*----------------------------------------------------------------------------*/
    507 
     489/*----------------------------------------------------------------------------*/
    508490bool usb_mouse_polling_callback(usb_hid_dev_t *hid_dev, void *data)
    509491{
    510492        if (hid_dev == NULL || data == NULL) {
    511                 usb_log_error("Missing argument to the mouse polling callback."
    512                     "\n");
     493                usb_log_error(
     494                    "Missing argument to the mouse polling callback.\n");
    513495                return false;
    514496        }
    515497
    516         usb_mouse_t *mouse_dev = (usb_mouse_t *)data;
    517                
     498        usb_mouse_t *mouse_dev = data;
     499
    518500        return usb_mouse_process_report(hid_dev, mouse_dev);
    519501}
    520 
    521 /*----------------------------------------------------------------------------*/
    522 
     502/*----------------------------------------------------------------------------*/
    523503void usb_mouse_deinit(usb_hid_dev_t *hid_dev, void *data)
    524504{
    525         if (data != NULL) {
    526                 usb_mouse_destroy(data);
    527         }
    528 }
    529 
    530 /*----------------------------------------------------------------------------*/
    531 
     505        if (data == NULL)
     506                return;
     507
     508        usb_mouse_t *mouse_dev = data;
     509
     510        /* Hangup session to the console */
     511        if (mouse_dev->mouse_sess != NULL) {
     512                const int ret = async_hangup(mouse_dev->mouse_sess);
     513                if (ret != EOK)
     514                        usb_log_warning("Failed to hang up mouse session: "
     515                            "%p, %s.\n", mouse_dev->mouse_sess, str_error(ret));
     516        }
     517
     518        if (mouse_dev->wheel_sess != NULL) {
     519                const int ret = async_hangup(mouse_dev->wheel_sess);
     520                if (ret != EOK)
     521                        usb_log_warning("Failed to hang up wheel session: "
     522                            "%p, %s.\n", mouse_dev->wheel_sess, str_error(ret));
     523        }
     524
     525        FUN_UNBIND_DESTROY(mouse_dev->mouse_fun);
     526        FUN_UNBIND_DESTROY(mouse_dev->wheel_fun);
     527
     528        free(mouse_dev->buttons);
     529        free(mouse_dev);
     530}
     531/*----------------------------------------------------------------------------*/
    532532int usb_mouse_set_boot_protocol(usb_hid_dev_t *hid_dev)
    533533{
    534534        int rc = usb_hid_parse_report_descriptor(
    535535            &hid_dev->report, USB_MOUSE_BOOT_REPORT_DESCRIPTOR,
    536             USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE);
     536            sizeof(USB_MOUSE_BOOT_REPORT_DESCRIPTOR));
    537537
    538538        if (rc != EOK) {
Note: See TracChangeset for help on using the changeset viewer.