Ignore:
File:
1 edited

Legend:

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

    r4093b14 re3c78efc  
    5555#define ARROWS_PER_SINGLE_WHEEL 3
    5656
    57 #define NAME  "mouse"
    58 
    59 /*----------------------------------------------------------------------------*/
    60 
    61 usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description = {
     57#define NAME "mouse"
     58
     59/*----------------------------------------------------------------------------*/
     60
     61const usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description = {
    6262        .transfer_type = USB_TRANSFER_INTERRUPT,
    6363        .direction = USB_DIRECTION_IN,
     
    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;
    126        
     119        usb_mouse_t *mouse_dev = fun->driver_data;
     120
    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        }
    133        
    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) ?
     126
     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;
    142        
     133
    143134        async_sess_t *sess =
    144135            async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
     
    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);
    159150        }
    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);
    188151}
    189152
     
    199162                return;
    200163        }
    201        
    202         int count = ((wheel < 0) ? -wheel : wheel) * ARROWS_PER_SINGLE_WHEEL;
    203         int i;
    204        
    205         for (i = 0; i < count; i++) {
     164
     165        const unsigned count =
     166            ((wheel < 0) ? -wheel : wheel) * ARROWS_PER_SINGLE_WHEEL;
     167        for (unsigned i = 0; i < count; i++) {
    206168                /* Send arrow press and release. */
    207169                usb_log_debug2("Sending key %d to the console\n", key);
     
    246208{
    247209        assert(mouse_dev != NULL);
    248        
     210
    249211        if (mouse_dev->mouse_sess == NULL) {
    250212                usb_log_warning(NAME " No console session.\n");
     
    252214        }
    253215
    254         int shift_x = get_mouse_axis_move_value(hid_dev->report_id,
    255             hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_X);
    256         int shift_y = get_mouse_axis_move_value(hid_dev->report_id,
    257             hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_Y);
    258         int wheel = get_mouse_axis_move_value(hid_dev->report_id,
    259             hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL);
     216        const int shift_x = get_mouse_axis_move_value(hid_dev->report_id,
     217            &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_X);
     218        const int shift_y = get_mouse_axis_move_value(hid_dev->report_id,
     219            &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_Y);
     220        const int wheel = get_mouse_axis_move_value(hid_dev->report_id,
     221            &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL);
    260222
    261223        if ((shift_x != 0) || (shift_y != 0)) {
    262                 async_exch_t *exch = async_exchange_begin(mouse_dev->mouse_sess);
    263                 async_req_2_0(exch, MOUSEEV_MOVE_EVENT, shift_x, shift_y);
    264                 async_exchange_end(exch);
    265         }
    266        
     224                async_exch_t *exch =
     225                    async_exchange_begin(mouse_dev->mouse_sess);
     226                if (exch != NULL) {
     227                        async_req_2_0(exch, MOUSEEV_MOVE_EVENT, shift_x, shift_y);
     228                        async_exchange_end(exch);
     229                }
     230        }
     231
    267232        if (wheel != 0)
    268233                usb_mouse_send_wheel(mouse_dev, wheel);
    269        
    270         /*
    271          * Buttons
    272          */
     234
     235        /* Buttons */
    273236        usb_hid_report_path_t *path = usb_hid_report_path();
    274         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        }
    275248        usb_hid_report_path_set_report_id(path, hid_dev->report_id);
    276        
     249
    277250        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    278             hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END
    279             | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    280             USB_HID_REPORT_TYPE_INPUT);
     251            &hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END
     252            | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, USB_HID_REPORT_TYPE_INPUT);
    281253
    282254        while (field != NULL) {
    283255                usb_log_debug2(NAME " VALUE(%X) USAGE(%X)\n", field->value,
    284256                    field->usage);
    285                
    286                 if (mouse_dev->buttons[field->usage - field->usage_minimum] == 0
    287                     && 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) {
    288262                        async_exch_t *exch =
    289263                            async_exchange_begin(mouse_dev->mouse_sess);
    290                         async_req_2_0(exch, MOUSEEV_BUTTON_EVENT, field->usage, 1);
    291                         async_exchange_end(exch);
    292                        
    293                         mouse_dev->buttons[field->usage - field->usage_minimum]
    294                             = field->value;
    295                 } else if (mouse_dev->buttons[field->usage - field->usage_minimum] != 0
    296                     && 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) {
    297272                        async_exch_t *exch =
    298273                            async_exchange_begin(mouse_dev->mouse_sess);
    299                         async_req_2_0(exch, MOUSEEV_BUTTON_EVENT, field->usage, 0);
    300                         async_exchange_end(exch);
    301                        
    302                         mouse_dev->buttons[field->usage - field->usage_minimum] =
    303                            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                        }
    304280                }
    305                
     281
    306282                field = usb_hid_report_get_sibling(
    307                     hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
    308                     | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
     283                    &hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
     284                    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    309285                    USB_HID_REPORT_TYPE_INPUT);
    310286        }
    311        
     287
    312288        usb_hid_report_path_free(path);
    313289
    314290        return true;
    315291}
    316 
    317 /*----------------------------------------------------------------------------*/
    318 
     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/*----------------------------------------------------------------------------*/
    319304static int usb_mouse_create_function(usb_hid_dev_t *hid_dev, usb_mouse_t *mouse)
    320305{
    321306        assert(hid_dev != NULL);
    322307        assert(mouse != NULL);
    323        
     308
    324309        /* Create the exposed function. */
    325310        usb_log_debug("Creating DDF function %s...\n", HID_MOUSE_FUN_NAME);
    326         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,
    327312            HID_MOUSE_FUN_NAME);
    328313        if (fun == NULL) {
    329                 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);
    330316                return ENOMEM;
    331317        }
    332        
     318
    333319        fun->ops = &mouse->ops;
    334320        fun->driver_data = mouse;
     
    336322        int rc = ddf_fun_bind(fun);
    337323        if (rc != EOK) {
    338                 usb_log_error("Could not bind DDF function: %s.\n",
    339                     str_error(rc));
     324                usb_log_error("Could not bind DDF function `%s': %s.\n",
     325                    fun->name, str_error(rc));
     326                fun->driver_data = NULL;
    340327                ddf_fun_destroy(fun);
    341328                return rc;
    342329        }
    343        
    344         usb_log_debug("Adding DDF function to category %s...\n",
    345             HID_MOUSE_CATEGORY);
     330
     331        usb_log_debug("Adding DDF function `%s' to category %s...\n",
     332            fun->name, HID_MOUSE_CATEGORY);
    346333        rc = ddf_fun_add_to_category(fun, HID_MOUSE_CATEGORY);
    347334        if (rc != EOK) {
     
    349336                    "Could not add DDF function to category %s: %s.\n",
    350337                    HID_MOUSE_CATEGORY, str_error(rc));
    351                 ddf_fun_destroy(fun);
    352                 return rc;
    353         }
    354        
     338                FUN_UNBIND_DESTROY(fun);
     339                return rc;
     340        }
     341        mouse->mouse_fun = fun;
     342
    355343        /*
    356344         * Special function for acting as keyboard (wheel)
    357345         */
    358         usb_log_debug("Creating DDF function %s...\n", 
     346        usb_log_debug("Creating DDF function %s...\n",
    359347                      HID_MOUSE_WHEEL_FUN_NAME);
    360         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,
    361349            HID_MOUSE_WHEEL_FUN_NAME);
    362350        if (fun == NULL) {
    363                 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;
    364355                return ENOMEM;
    365356        }
    366        
     357
    367358        /*
    368359         * Store the initialized HID device and HID ops
     
    374365        rc = ddf_fun_bind(fun);
    375366        if (rc != EOK) {
    376                 usb_log_error("Could not bind DDF function: %s.\n",
    377                     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;
    378373                ddf_fun_destroy(fun);
    379374                return rc;
    380375        }
    381        
     376
    382377        usb_log_debug("Adding DDF function to category %s...\n",
    383378            HID_MOUSE_WHEEL_CATEGORY);
     
    387382                    "Could not add DDF function to category %s: %s.\n",
    388383                    HID_MOUSE_WHEEL_CATEGORY, str_error(rc));
    389                 ddf_fun_destroy(fun);
    390                 return rc;
    391         }
    392        
     384
     385                FUN_UNBIND_DESTROY(mouse->mouse_fun);
     386                mouse->mouse_fun = NULL;
     387                FUN_UNBIND_DESTROY(fun);
     388                return rc;
     389        }
     390        mouse->wheel_fun = fun;
     391
    393392        return EOK;
    394393}
     
    435434        return highest_button;
    436435}
    437 
    438 /*----------------------------------------------------------------------------*/
    439 
     436/*----------------------------------------------------------------------------*/
    440437int usb_mouse_init(usb_hid_dev_t *hid_dev, void **data)
    441438{
    442439        usb_log_debug("Initializing HID/Mouse structure...\n");
    443        
     440
    444441        if (hid_dev == NULL) {
    445442                usb_log_error("Failed to init keyboard structure: no structure"
     
    447444                return EINVAL;
    448445        }
    449        
    450         usb_mouse_t *mouse_dev = usb_mouse_new();
     446
     447        usb_mouse_t *mouse_dev = calloc(1, sizeof(usb_mouse_t));
    451448        if (mouse_dev == NULL) {
    452449                usb_log_error("Error while creating USB/HID Mouse device "
     
    454451                return ENOMEM;
    455452        }
    456        
     453
    457454        // FIXME: This may not be optimal since stupid hardware vendor may
    458455        // use buttons 1, 2, 3 and 6000 and we would allocate array of
     
    461458        // that the current solution is good enough.
    462459        /* Adding 1 because we will be accessing buttons[highest]. */
    463         mouse_dev->buttons_count = usb_mouse_get_highest_button(hid_dev->report,
    464             hid_dev->report_id) + 1;
     460        mouse_dev->buttons_count = 1 + usb_mouse_get_highest_button(
     461            &hid_dev->report, hid_dev->report_id);
    465462        mouse_dev->buttons = calloc(mouse_dev->buttons_count, sizeof(int32_t));
    466        
     463
    467464        if (mouse_dev->buttons == NULL) {
    468465                usb_log_error(NAME ": out of memory, giving up on device!\n");
     
    471468        }
    472469
    473 
    474         // save the Mouse device structure into the HID device structure
    475         *data = mouse_dev;
    476        
    477470        // set handler for incoming calls
    478471        mouse_dev->ops.default_handler = default_connection_handler;
    479        
     472
    480473        // TODO: how to know if the device supports the request???
    481         usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 
     474        usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    482475            hid_dev->usb_dev->interface_no, IDLE_RATE);
    483        
     476
    484477        int rc = usb_mouse_create_function(hid_dev, mouse_dev);
    485478        if (rc != EOK) {
    486                 usb_mouse_destroy(mouse_dev);
    487                 return rc;
    488         }
    489        
     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;
     486
    490487        return EOK;
    491488}
    492 
    493 /*----------------------------------------------------------------------------*/
    494 
     489/*----------------------------------------------------------------------------*/
    495490bool usb_mouse_polling_callback(usb_hid_dev_t *hid_dev, void *data)
    496491{
    497492        if (hid_dev == NULL || data == NULL) {
    498                 usb_log_error("Missing argument to the mouse polling callback."
    499                     "\n");
     493                usb_log_error(
     494                    "Missing argument to the mouse polling callback.\n");
    500495                return false;
    501496        }
    502        
    503         usb_mouse_t *mouse_dev = (usb_mouse_t *)data;
    504                
     497
     498        usb_mouse_t *mouse_dev = data;
     499
    505500        return usb_mouse_process_report(hid_dev, mouse_dev);
    506501}
    507 
    508 /*----------------------------------------------------------------------------*/
    509 
     502/*----------------------------------------------------------------------------*/
    510503void usb_mouse_deinit(usb_hid_dev_t *hid_dev, void *data)
    511504{
    512         if (data != NULL) {
    513                 usb_mouse_destroy((usb_mouse_t *)data);
    514         }
    515 }
    516 
    517 /*----------------------------------------------------------------------------*/
    518 
     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/*----------------------------------------------------------------------------*/
    519532int usb_mouse_set_boot_protocol(usb_hid_dev_t *hid_dev)
    520533{
    521         int rc = usb_hid_parse_report_descriptor(hid_dev->report,
    522             USB_MOUSE_BOOT_REPORT_DESCRIPTOR,
    523             USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE);
    524        
     534        int rc = usb_hid_parse_report_descriptor(
     535            &hid_dev->report, USB_MOUSE_BOOT_REPORT_DESCRIPTOR,
     536            sizeof(USB_MOUSE_BOOT_REPORT_DESCRIPTOR));
     537
    525538        if (rc != EOK) {
    526539                usb_log_error("Failed to parse boot report descriptor: %s\n",
     
    528541                return rc;
    529542        }
    530        
    531         rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe, 
     543
     544        rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe,
    532545            hid_dev->usb_dev->interface_no, USB_HID_PROTOCOL_BOOT);
    533        
     546
    534547        if (rc != EOK) {
    535548                usb_log_warning("Failed to set boot protocol to the device: "
     
    537550                return rc;
    538551        }
    539        
     552
    540553        return EOK;
    541554}
Note: See TracChangeset for help on using the changeset viewer.