Ignore:
File:
1 edited

Legend:

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

    r5cc9eba r2b621cb  
    5252#include "../usbhid.h"
    5353
     54/** Number of simulated arrow-key presses for singel wheel step. */
     55#define ARROWS_PER_SINGLE_WHEEL 3
     56
    5457#define NAME "mouse"
    5558
    56 /*----------------------------------------------------------------------------*/
    57 
     59static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
     60
     61static ddf_dev_ops_t ops = { .default_handler = default_connection_handler };
     62
     63/*----------------------------------------------------------------------------*/
    5864const usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description = {
    5965        .transfer_type = USB_TRANSFER_INTERRUPT,
     
    6672
    6773const char *HID_MOUSE_FUN_NAME = "mouse";
     74const char *HID_MOUSE_WHEEL_FUN_NAME = "mouse-wheel";
    6875const char *HID_MOUSE_CATEGORY = "mouse";
     76const char *HID_MOUSE_WHEEL_CATEGORY = "keyboard";
    6977
    7078/** Default idle rate for mouses. */
     
    121129
    122130        usb_log_debug("%s: fun->name: %s\n", __FUNCTION__, fun->name);
    123         usb_log_debug("%s: mouse_sess: %p\n",
    124             __FUNCTION__, mouse_dev->mouse_sess);
     131        usb_log_debug("%s: mouse_sess: %p, wheel_sess: %p\n",
     132            __FUNCTION__, mouse_dev->mouse_sess, mouse_dev->wheel_sess);
     133
     134        async_sess_t **sess_ptr = (fun == mouse_dev->mouse_fun) ?
     135            &mouse_dev->mouse_sess : &mouse_dev->wheel_sess;
    125136
    126137        async_sess_t *sess =
    127138            async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
    128139        if (sess != NULL) {
    129                 if (mouse_dev->mouse_sess == NULL) {
    130                         mouse_dev->mouse_sess = sess;
     140                if (*sess_ptr == NULL) {
     141                        *sess_ptr = sess;
    131142                        usb_log_debug("Console session to %s set ok (%p).\n",
    132143                            fun->name, sess);
     
    136147                            fun->name);
    137148                        async_answer_0(icallid, ELIMIT);
    138                         async_hangup(sess);
    139149                }
    140150        } else {
     
    143153        }
    144154}
    145 /*----------------------------------------------------------------------------*/
     155
     156/*----------------------------------------------------------------------------*/
     157
     158static void usb_mouse_send_wheel(const usb_mouse_t *mouse_dev, int wheel)
     159{
     160        unsigned int key = (wheel > 0) ? KC_UP : KC_DOWN;
     161
     162        if (mouse_dev->wheel_sess == NULL) {
     163                usb_log_warning(
     164                    "Connection to console not ready, wheel roll discarded.\n");
     165                return;
     166        }
     167
     168        const unsigned count =
     169            ((wheel < 0) ? -wheel : wheel) * ARROWS_PER_SINGLE_WHEEL;
     170        for (unsigned i = 0; i < count; i++) {
     171                /* Send arrow press and release. */
     172                usb_log_debug2("Sending key %d to the console\n", key);
     173               
     174                async_exch_t *exch = async_exchange_begin(mouse_dev->wheel_sess);
     175               
     176                async_msg_4(exch, KBDEV_EVENT, KEY_PRESS, key, 0, 0);
     177                async_msg_4(exch, KBDEV_EVENT, KEY_RELEASE, key, 0, 0);
     178               
     179                async_exchange_end(exch);
     180        }
     181}
     182
     183/*----------------------------------------------------------------------------*/
     184
    146185static int get_mouse_axis_move_value(uint8_t rid, usb_hid_report_t *report,
    147186    int32_t usage)
     
    185224            &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL);
    186225
    187         if (shift_x || shift_y || wheel) {
     226        if ((shift_x != 0) || (shift_y != 0)) {
    188227                async_exch_t *exch =
    189228                    async_exchange_begin(mouse_dev->mouse_sess);
    190229                if (exch != NULL) {
    191                         async_msg_3(exch, MOUSEEV_MOVE_EVENT,
    192                             shift_x, shift_y, wheel);
     230                        async_req_2_0(exch, MOUSEEV_MOVE_EVENT, shift_x, shift_y);
    193231                        async_exchange_end(exch);
    194232                }
    195233        }
     234
     235        if (wheel != 0)
     236                usb_mouse_send_wheel(mouse_dev, wheel);
    196237
    197238        /* Buttons */
     
    221262                assert(index < mouse_dev->buttons_count);
    222263
    223                 if (mouse_dev->buttons[index] == 0 && field->value != 0) {
     264                if (mouse_dev->buttons[index] != field->value) {
    224265                        async_exch_t *exch =
    225266                            async_exchange_begin(mouse_dev->mouse_sess);
    226267                        if (exch != NULL) {
    227268                                async_req_2_0(exch, MOUSEEV_BUTTON_EVENT,
    228                                     field->usage, 1);
    229                                 async_exchange_end(exch);
    230                                 mouse_dev->buttons[index] = field->value;
    231                         }
    232 
    233                 } else if (mouse_dev->buttons[index] != 0 && field->value == 0) {
    234                         async_exch_t *exch =
    235                             async_exchange_begin(mouse_dev->mouse_sess);
    236                         if (exch != NULL) {
    237                                 async_req_2_0(exch, MOUSEEV_BUTTON_EVENT,
    238                                     field->usage, 0);
     269                                    field->usage, (field->value != 0) ? 1 : 0);
    239270                                async_exchange_end(exch);
    240271                                mouse_dev->buttons[index] = field->value;
     
    279310        }
    280311
    281         fun->ops = &mouse->ops;
     312        fun->ops = &ops;
    282313        fun->driver_data = mouse;
    283314
     
    303334        mouse->mouse_fun = fun;
    304335
     336        /*
     337         * Special function for acting as keyboard (wheel)
     338         */
     339        usb_log_debug("Creating DDF function %s...\n",
     340                      HID_MOUSE_WHEEL_FUN_NAME);
     341        fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
     342            HID_MOUSE_WHEEL_FUN_NAME);
     343        if (fun == NULL) {
     344                usb_log_error("Could not create DDF function node `%s'.\n",
     345                    HID_MOUSE_WHEEL_FUN_NAME);
     346                FUN_UNBIND_DESTROY(mouse->mouse_fun);
     347                mouse->mouse_fun = NULL;
     348                return ENOMEM;
     349        }
     350
     351        /*
     352         * Store the initialized HID device and HID ops
     353         * to the DDF function.
     354         */
     355        fun->ops = &ops;
     356        fun->driver_data = mouse;
     357
     358        rc = ddf_fun_bind(fun);
     359        if (rc != EOK) {
     360                usb_log_error("Could not bind DDF function `%s': %s.\n",
     361                    fun->name, str_error(rc));
     362                FUN_UNBIND_DESTROY(mouse->mouse_fun);
     363                mouse->mouse_fun = NULL;
     364
     365                fun->driver_data = NULL;
     366                ddf_fun_destroy(fun);
     367                return rc;
     368        }
     369
     370        usb_log_debug("Adding DDF function to category %s...\n",
     371            HID_MOUSE_WHEEL_CATEGORY);
     372        rc = ddf_fun_add_to_category(fun, HID_MOUSE_WHEEL_CATEGORY);
     373        if (rc != EOK) {
     374                usb_log_error(
     375                    "Could not add DDF function to category %s: %s.\n",
     376                    HID_MOUSE_WHEEL_CATEGORY, str_error(rc));
     377
     378                FUN_UNBIND_DESTROY(mouse->mouse_fun);
     379                mouse->mouse_fun = NULL;
     380                FUN_UNBIND_DESTROY(fun);
     381                return rc;
     382        }
     383        mouse->wheel_fun = fun;
     384
    305385        return EOK;
    306386}
     387
     388/*----------------------------------------------------------------------------*/
    307389
    308390/** Get highest index of a button mentioned in given report.
     
    379461        }
    380462
    381         // set handler for incoming calls
    382         mouse_dev->ops.default_handler = default_connection_handler;
    383 
    384463        // TODO: how to know if the device supports the request???
    385464        usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
     
    427506        }
    428507
     508        if (mouse_dev->wheel_sess != NULL) {
     509                const int ret = async_hangup(mouse_dev->wheel_sess);
     510                if (ret != EOK)
     511                        usb_log_warning("Failed to hang up wheel session: "
     512                            "%p, %s.\n", mouse_dev->wheel_sess, str_error(ret));
     513        }
     514
    429515        FUN_UNBIND_DESTROY(mouse_dev->mouse_fun);
     516        FUN_UNBIND_DESTROY(mouse_dev->wheel_fun);
    430517
    431518        free(mouse_dev->buttons);
Note: See TracChangeset for help on using the changeset viewer.