source: mainline/uspace/drv/bus/usb/usbhid/mouse/mousedev.c@ 555499da

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 555499da was 0f12c17, checked in by Jan Vesely <jano.vesely@…>, 14 years ago

usbhid, mouse: Even better error handling.

  • Property mode set to 100644
File size: 17.0 KB
RevLine 
[e9f0348]1/*
2 * Copyright (c) 2011 Lubos Slovak, Vojtech Horky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup drvusbhid
30 * @{
31 */
32/**
33 * @file
34 * USB Mouse driver API.
35 */
36
37#include <usb/debug.h>
38#include <usb/classes/classes.h>
[faa44e58]39#include <usb/hid/hid.h>
40#include <usb/hid/request.h>
41#include <usb/hid/usages/core.h>
[e9f0348]42#include <errno.h>
[79ae36dd]43#include <async.h>
[e9f0348]44#include <str_error.h>
[1875a0c]45#include <ipc/mouseev.h>
[f8e549b]46#include <io/console.h>
47
[5f88293]48#include <ipc/kbdev.h>
[f8e549b]49#include <io/keycode.h>
[e9f0348]50
51#include "mousedev.h"
52#include "../usbhid.h"
53
[a3a2fdb]54/** Number of simulated arrow-key presses for singel wheel step. */
55#define ARROWS_PER_SINGLE_WHEEL 3
56
[e04182d]57#define NAME "mouse"
[30710035]58
[e9f0348]59/*----------------------------------------------------------------------------*/
60
[b803845]61const usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description = {
[e9f0348]62 .transfer_type = USB_TRANSFER_INTERRUPT,
63 .direction = USB_DIRECTION_IN,
64 .interface_class = USB_CLASS_HID,
65 .interface_subclass = USB_HID_SUBCLASS_BOOT,
66 .interface_protocol = USB_HID_PROTOCOL_MOUSE,
67 .flags = 0
68};
69
70const char *HID_MOUSE_FUN_NAME = "mouse";
[f8e549b]71const char *HID_MOUSE_WHEEL_FUN_NAME = "mouse-wheel";
[1dc4a5e]72const char *HID_MOUSE_CATEGORY = "mouse";
73const char *HID_MOUSE_WHEEL_CATEGORY = "keyboard";
[e9f0348]74
75/** Default idle rate for mouses. */
76static const uint8_t IDLE_RATE = 0;
77
78/*----------------------------------------------------------------------------*/
79
80enum {
81 USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE = 63
82};
83
84static const uint8_t USB_MOUSE_BOOT_REPORT_DESCRIPTOR[
85 USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE] = {
86 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
87 0x09, 0x02, // USAGE (Mouse)
88 0xa1, 0x01, // COLLECTION (Application)
89 0x09, 0x01, // USAGE (Pointer)
90 0xa1, 0x00, // COLLECTION (Physical)
91 0x95, 0x03, // REPORT_COUNT (3)
92 0x75, 0x01, // REPORT_SIZE (1)
93 0x05, 0x09, // USAGE_PAGE (Button)
94 0x19, 0x01, // USAGE_MINIMUM (Button 1)
95 0x29, 0x03, // USAGE_MAXIMUM (Button 3)
96 0x15, 0x00, // LOGICAL_MINIMUM (0)
97 0x25, 0x01, // LOGICAL_MAXIMUM (1)
98 0x81, 0x02, // INPUT (Data,Var,Abs)
99 0x95, 0x01, // REPORT_COUNT (1)
100 0x75, 0x05, // REPORT_SIZE (5)
101 0x81, 0x01, // INPUT (Cnst)
102 0x75, 0x08, // REPORT_SIZE (8)
103 0x95, 0x02, // REPORT_COUNT (2)
104 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
105 0x09, 0x30, // USAGE (X)
106 0x09, 0x31, // USAGE (Y)
107 0x15, 0x81, // LOGICAL_MINIMUM (-127)
108 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
109 0x81, 0x06, // INPUT (Data,Var,Rel)
110 0xc0, // END_COLLECTION
111 0xc0 // END_COLLECTION
112};
113
114/*----------------------------------------------------------------------------*/
115
116/** Default handler for IPC methods not handled by DDF.
117 *
118 * @param fun Device function handling the call.
119 * @param icallid Call id.
120 * @param icall Call data.
121 */
122static void default_connection_handler(ddf_fun_t *fun,
123 ipc_callid_t icallid, ipc_call_t *icall)
124{
[e04182d]125 usb_mouse_t *mouse_dev = fun->driver_data;
[cc29622]126
[65b458c4]127 if (mouse_dev == NULL) {
[e04182d]128 usb_log_debug("%s: Missing parameters.\n", __FUNCTION__);
[e9f0348]129 async_answer_0(icallid, EINVAL);
130 return;
131 }
[cc29622]132
[e04182d]133 usb_log_debug("%s: fun->name: %s\n", __FUNCTION__, fun->name);
134 usb_log_debug("%s: mouse_sess: %p, wheel_sess: %p\n",
135 __FUNCTION__, mouse_dev->mouse_sess, mouse_dev->wheel_sess);
[cc29622]136
[e04182d]137 async_sess_t **sess_ptr = (fun == mouse_dev->mouse_fun) ?
[5da7199]138 &mouse_dev->mouse_sess : &mouse_dev->wheel_sess;
[cc29622]139
[5da7199]140 async_sess_t *sess =
141 async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
142 if (sess != NULL) {
143 if (*sess_ptr == NULL) {
144 *sess_ptr = sess;
[e04182d]145 usb_log_debug("Console session to %s set ok (%p).\n",
146 fun->name, sess);
[5da7199]147 async_answer_0(icallid, EOK);
148 } else {
[e04182d]149 usb_log_error("Console session to %s already set.\n",
150 fun->name);
[e9f0348]151 async_answer_0(icallid, ELIMIT);
152 }
[5da7199]153 } else {
[e04182d]154 usb_log_debug("%s: Invalid function.\n", __FUNCTION__);
[5da7199]155 async_answer_0(icallid, EINVAL);
[e9f0348]156 }
157}
158
159/*----------------------------------------------------------------------------*/
160
[f8e549b]161static void usb_mouse_send_wheel(const usb_mouse_t *mouse_dev, int wheel)
162{
[a3a2fdb]163 unsigned int key = (wheel > 0) ? KC_UP : KC_DOWN;
[f8e549b]164
[5da7199]165 if (mouse_dev->wheel_sess == NULL) {
[f8e549b]166 usb_log_warning(
[ae5f77d5]167 "Connection to console not ready, wheel roll discarded.\n");
[f8e549b]168 return;
169 }
[cc29622]170
[e04182d]171 const unsigned count =
172 ((wheel < 0) ? -wheel : wheel) * ARROWS_PER_SINGLE_WHEEL;
173 for (unsigned i = 0; i < count; i++) {
[a3a2fdb]174 /* Send arrow press and release. */
175 usb_log_debug2("Sending key %d to the console\n", key);
[5da7199]176
177 async_exch_t *exch = async_exchange_begin(mouse_dev->wheel_sess);
178
179 async_msg_4(exch, KBDEV_EVENT, KEY_PRESS, key, 0, 0);
180 async_msg_4(exch, KBDEV_EVENT, KEY_RELEASE, key, 0, 0);
181
182 async_exchange_end(exch);
[f8e549b]183 }
184}
185
186/*----------------------------------------------------------------------------*/
187
[a3a2fdb]188static int get_mouse_axis_move_value(uint8_t rid, usb_hid_report_t *report,
189 int32_t usage)
[e9f0348]190{
[a3a2fdb]191 int result = 0;
[30710035]192
193 usb_hid_report_path_t *path = usb_hid_report_path();
[a3a2fdb]194 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_GENERIC_DESKTOP,
195 usage);
[e9f0348]196
[a3a2fdb]197 usb_hid_report_path_set_report_id(path, rid);
[e9f0348]198
[30710035]199 usb_hid_report_field_t *field = usb_hid_report_get_sibling(
[a3a2fdb]200 report, NULL, path, USB_HID_PATH_COMPARE_END,
[30710035]201 USB_HID_REPORT_TYPE_INPUT);
[e9f0348]202
[30710035]203 if (field != NULL) {
[a3a2fdb]204 result = field->value;
[e9f0348]205 }
[30710035]206
207 usb_hid_report_path_free(path);
208
[a3a2fdb]209 return result;
210}
[30710035]211
[a3a2fdb]212static bool usb_mouse_process_report(usb_hid_dev_t *hid_dev,
213 usb_mouse_t *mouse_dev)
214{
215 assert(mouse_dev != NULL);
[cc29622]216
[5da7199]217 if (mouse_dev->mouse_sess == NULL) {
218 usb_log_warning(NAME " No console session.\n");
[a3a2fdb]219 return true;
[e9f0348]220 }
[30710035]221
[e3e0953]222 const int shift_x = get_mouse_axis_move_value(hid_dev->report_id,
[a8c4e871]223 &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_X);
[e3e0953]224 const int shift_y = get_mouse_axis_move_value(hid_dev->report_id,
[a8c4e871]225 &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_Y);
[e3e0953]226 const int wheel = get_mouse_axis_move_value(hid_dev->report_id,
[a8c4e871]227 &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL);
[a3a2fdb]228
[30710035]229 if ((shift_x != 0) || (shift_y != 0)) {
[a8c4e871]230 async_exch_t *exch =
231 async_exchange_begin(mouse_dev->mouse_sess);
[e3e0953]232 if (exch != NULL) {
233 async_req_2_0(exch, MOUSEEV_MOVE_EVENT, shift_x, shift_y);
234 async_exchange_end(exch);
235 }
[e9f0348]236 }
[cc29622]237
[5da7199]238 if (wheel != 0)
[a3a2fdb]239 usb_mouse_send_wheel(mouse_dev, wheel);
[cc29622]240
[e3e0953]241 /* Buttons */
[a3a2fdb]242 usb_hid_report_path_t *path = usb_hid_report_path();
[e3e0953]243 if (path == NULL) {
244 usb_log_warning("Failed to create USB HID report path.\n");
245 return true;
246 }
247 int ret =
248 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0);
249 if (ret != EOK) {
250 usb_hid_report_path_free(path);
251 usb_log_warning("Failed to add buttons to report path.\n");
252 return true;
253 }
[65c3794]254 usb_hid_report_path_set_report_id(path, hid_dev->report_id);
[cc29622]255
[a3a2fdb]256 usb_hid_report_field_t *field = usb_hid_report_get_sibling(
[a8c4e871]257 &hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END
258 | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, USB_HID_REPORT_TYPE_INPUT);
[30710035]259
[310c4df]260 while (field != NULL) {
[ae5f77d5]261 usb_log_debug2(NAME " VALUE(%X) USAGE(%X)\n", field->value,
[30710035]262 field->usage);
[5723ae49]263 assert(field->usage > field->usage_minimum);
264 const unsigned index = field->usage - field->usage_minimum;
265 assert(index < mouse_dev->buttons_count);
[e3e0953]266
[5723ae49]267 if (mouse_dev->buttons[index] == 0 && field->value != 0) {
[5da7199]268 async_exch_t *exch =
269 async_exchange_begin(mouse_dev->mouse_sess);
[e3e0953]270 if (exch != NULL) {
271 async_req_2_0(exch, MOUSEEV_BUTTON_EVENT,
272 field->usage, 1);
273 async_exchange_end(exch);
274 mouse_dev->buttons[index] = field->value;
275 }
276
[5723ae49]277 } else if (mouse_dev->buttons[index] != 0 && field->value == 0) {
[5da7199]278 async_exch_t *exch =
279 async_exchange_begin(mouse_dev->mouse_sess);
[e3e0953]280 if (exch != NULL) {
281 async_req_2_0(exch, MOUSEEV_BUTTON_EVENT,
282 field->usage, 0);
283 async_exchange_end(exch);
284 mouse_dev->buttons[index] = field->value;
285 }
[1875a0c]286 }
[a8c4e871]287
[30710035]288 field = usb_hid_report_get_sibling(
[a8c4e871]289 &hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
290 | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
[30710035]291 USB_HID_REPORT_TYPE_INPUT);
[e9f0348]292 }
[cc29622]293
[30710035]294 usb_hid_report_path_free(path);
[e9f0348]295
296 return true;
297}
298/*----------------------------------------------------------------------------*/
[0f12c17]299#define FUN_UNBIND_DESTROY(fun) \
300if (fun) { \
301 if (ddf_fun_unbind((fun)) == EOK) { \
302 (fun)->driver_data = NULL; \
303 ddf_fun_destroy((fun)); \
304 } else { \
305 usb_log_error("Could not unbind function `%s', it " \
306 "will not be destroyed.\n", (fun)->name); \
307 } \
308} else (void)0
309/*----------------------------------------------------------------------------*/
[65b458c4]310static int usb_mouse_create_function(usb_hid_dev_t *hid_dev, usb_mouse_t *mouse)
[31cfee16]311{
[65b458c4]312 assert(hid_dev != NULL);
313 assert(mouse != NULL);
[cc29622]314
[15f3c3f]315 /* Create the exposed function. */
[31cfee16]316 usb_log_debug("Creating DDF function %s...\n", HID_MOUSE_FUN_NAME);
[0f12c17]317 ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
[31cfee16]318 HID_MOUSE_FUN_NAME);
319 if (fun == NULL) {
[0f12c17]320 usb_log_error("Could not create DDF function node `%s'.\n",
321 HID_MOUSE_FUN_NAME);
[31cfee16]322 return ENOMEM;
323 }
[cc29622]324
[65b458c4]325 fun->ops = &mouse->ops;
[19e0560e]326 fun->driver_data = mouse;
[31cfee16]327
328 int rc = ddf_fun_bind(fun);
329 if (rc != EOK) {
[0f12c17]330 usb_log_error("Could not bind DDF function `%s': %s.\n",
331 fun->name, str_error(rc));
[5723ae49]332 fun->driver_data = NULL;
333 ddf_fun_destroy(fun);
[31cfee16]334 return rc;
335 }
[cc29622]336
[0f12c17]337 usb_log_debug("Adding DDF function `%s' to category %s...\n",
338 fun->name, HID_MOUSE_CATEGORY);
[1dc4a5e]339 rc = ddf_fun_add_to_category(fun, HID_MOUSE_CATEGORY);
[31cfee16]340 if (rc != EOK) {
341 usb_log_error(
[1dc4a5e]342 "Could not add DDF function to category %s: %s.\n",
343 HID_MOUSE_CATEGORY, str_error(rc));
[0f12c17]344 FUN_UNBIND_DESTROY(fun);
[31cfee16]345 return rc;
346 }
[f2964e45]347 mouse->mouse_fun = fun;
[cc29622]348
[f8e549b]349 /*
350 * Special function for acting as keyboard (wheel)
351 */
[5723ae49]352 usb_log_debug("Creating DDF function %s...\n",
[f8e549b]353 HID_MOUSE_WHEEL_FUN_NAME);
[5723ae49]354 fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
[f8e549b]355 HID_MOUSE_WHEEL_FUN_NAME);
356 if (fun == NULL) {
[0f12c17]357 usb_log_error("Could not create DDF function node `%s'.\n",
358 HID_MOUSE_WHEEL_FUN_NAME);
359 FUN_UNBIND_DESTROY(mouse->mouse_fun);
[e3e0953]360 mouse->mouse_fun = NULL;
[f8e549b]361 return ENOMEM;
362 }
[cc29622]363
[f8e549b]364 /*
365 * Store the initialized HID device and HID ops
366 * to the DDF function.
367 */
[65b458c4]368 fun->ops = &mouse->ops;
[19e0560e]369 fun->driver_data = mouse;
[f8e549b]370
371 rc = ddf_fun_bind(fun);
372 if (rc != EOK) {
[0f12c17]373 usb_log_error("Could not bind DDF function `%s': %s.\n",
374 fun->name, str_error(rc));
375 FUN_UNBIND_DESTROY(mouse->mouse_fun);
[e3e0953]376 mouse->mouse_fun = NULL;
[0f12c17]377
[5723ae49]378 fun->driver_data = NULL;
379 ddf_fun_destroy(fun);
[f8e549b]380 return rc;
381 }
[cc29622]382
[1dc4a5e]383 usb_log_debug("Adding DDF function to category %s...\n",
384 HID_MOUSE_WHEEL_CATEGORY);
385 rc = ddf_fun_add_to_category(fun, HID_MOUSE_WHEEL_CATEGORY);
[f8e549b]386 if (rc != EOK) {
387 usb_log_error(
[1dc4a5e]388 "Could not add DDF function to category %s: %s.\n",
389 HID_MOUSE_WHEEL_CATEGORY, str_error(rc));
[0f12c17]390
391 FUN_UNBIND_DESTROY(mouse->mouse_fun);
[e3e0953]392 mouse->mouse_fun = NULL;
[0f12c17]393 FUN_UNBIND_DESTROY(fun);
[f8e549b]394 return rc;
395 }
[f2964e45]396 mouse->wheel_fun = fun;
[cc29622]397
[31cfee16]398 return EOK;
399}
400
401/*----------------------------------------------------------------------------*/
402
[4093b14]403/** Get highest index of a button mentioned in given report.
404 *
405 * @param report HID report.
406 * @param report_id Report id we are interested in.
407 * @return Highest button mentioned in the report.
408 * @retval 1 No button was mentioned.
409 *
410 */
411static size_t usb_mouse_get_highest_button(usb_hid_report_t *report, uint8_t report_id)
412{
413 size_t highest_button = 0;
414
415 usb_hid_report_path_t *path = usb_hid_report_path();
416 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0);
417 usb_hid_report_path_set_report_id(path, report_id);
418
419 usb_hid_report_field_t *field = NULL;
420
421 /* Break from within. */
422 while (1) {
423 field = usb_hid_report_get_sibling(
424 report, field, path,
425 USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
426 USB_HID_REPORT_TYPE_INPUT);
427 /* No more buttons? */
428 if (field == NULL) {
429 break;
430 }
431
432 size_t current_button = field->usage - field->usage_minimum;
433 if (current_button > highest_button) {
434 highest_button = current_button;
435 }
436 }
437
438 usb_hid_report_path_free(path);
439
440 return highest_button;
441}
442/*----------------------------------------------------------------------------*/
[65b458c4]443int usb_mouse_init(usb_hid_dev_t *hid_dev, void **data)
[e9f0348]444{
445 usb_log_debug("Initializing HID/Mouse structure...\n");
[cc29622]446
[e9f0348]447 if (hid_dev == NULL) {
448 usb_log_error("Failed to init keyboard structure: no structure"
449 " given.\n");
450 return EINVAL;
451 }
[cc29622]452
[5723ae49]453 usb_mouse_t *mouse_dev = calloc(1, sizeof(usb_mouse_t));
[e9f0348]454 if (mouse_dev == NULL) {
455 usb_log_error("Error while creating USB/HID Mouse device "
456 "structure.\n");
457 return ENOMEM;
458 }
[cc29622]459
[4093b14]460 // FIXME: This may not be optimal since stupid hardware vendor may
461 // use buttons 1, 2, 3 and 6000 and we would allocate array of
462 // 6001*4B and use only 4 items in it.
463 // Since I doubt that hardware producers would do that, I think
464 // that the current solution is good enough.
465 /* Adding 1 because we will be accessing buttons[highest]. */
[a8c4e871]466 mouse_dev->buttons_count = 1 + usb_mouse_get_highest_button(
467 &hid_dev->report, hid_dev->report_id);
[4093b14]468 mouse_dev->buttons = calloc(mouse_dev->buttons_count, sizeof(int32_t));
[cc29622]469
[30710035]470 if (mouse_dev->buttons == NULL) {
[4093b14]471 usb_log_error(NAME ": out of memory, giving up on device!\n");
[30710035]472 free(mouse_dev);
473 return ENOMEM;
474 }
[4093b14]475
[e9f0348]476 // set handler for incoming calls
[65b458c4]477 mouse_dev->ops.default_handler = default_connection_handler;
[cc29622]478
[e9f0348]479 // TODO: how to know if the device supports the request???
[5723ae49]480 usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
[19e0560e]481 hid_dev->usb_dev->interface_no, IDLE_RATE);
[cc29622]482
[65b458c4]483 int rc = usb_mouse_create_function(hid_dev, mouse_dev);
[31cfee16]484 if (rc != EOK) {
[5723ae49]485 free(mouse_dev->buttons);
486 free(mouse_dev);
[31cfee16]487 return rc;
488 }
[cc29622]489
[5723ae49]490 /* Save the Mouse device structure into the HID device structure. */
491 *data = mouse_dev;
492
[e9f0348]493 return EOK;
494}
495/*----------------------------------------------------------------------------*/
[4d3c13e]496bool usb_mouse_polling_callback(usb_hid_dev_t *hid_dev, void *data)
[e9f0348]497{
[65b458c4]498 if (hid_dev == NULL || data == NULL) {
[e3e0953]499 usb_log_error(
500 "Missing argument to the mouse polling callback.\n");
[e9f0348]501 return false;
502 }
[cc29622]503
[5723ae49]504 usb_mouse_t *mouse_dev = data;
505
[4d3c13e]506 return usb_mouse_process_report(hid_dev, mouse_dev);
[e9f0348]507}
508/*----------------------------------------------------------------------------*/
[65b458c4]509void usb_mouse_deinit(usb_hid_dev_t *hid_dev, void *data)
[e9f0348]510{
[5723ae49]511 if (data == NULL)
512 return;
513
514 usb_mouse_t *mouse_dev = data;
515
516 /* Hangup session to the console */
517 if (mouse_dev->mouse_sess != NULL) {
518 const int ret = async_hangup(mouse_dev->mouse_sess);
519 if (ret != EOK)
520 usb_log_warning("Failed to hang up mouse session: "
521 "%p, %s.\n", mouse_dev->mouse_sess, str_error(ret));
522 }
523
524 if (mouse_dev->wheel_sess != NULL) {
525 const int ret = async_hangup(mouse_dev->wheel_sess);
526 if (ret != EOK)
527 usb_log_warning("Failed to hang up wheel session: "
528 "%p, %s.\n", mouse_dev->wheel_sess, str_error(ret));
529 }
530
[0f12c17]531 FUN_UNBIND_DESTROY(mouse_dev->mouse_fun);
532 FUN_UNBIND_DESTROY(mouse_dev->wheel_fun);
[5723ae49]533
534 free(mouse_dev->buttons);
535 free(mouse_dev);
[e9f0348]536}
537/*----------------------------------------------------------------------------*/
[60c0573]538int usb_mouse_set_boot_protocol(usb_hid_dev_t *hid_dev)
[e9f0348]539{
[a8c4e871]540 int rc = usb_hid_parse_report_descriptor(
541 &hid_dev->report, USB_MOUSE_BOOT_REPORT_DESCRIPTOR,
[e9f0348]542 USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE);
[cc29622]543
[e9f0348]544 if (rc != EOK) {
545 usb_log_error("Failed to parse boot report descriptor: %s\n",
546 str_error(rc));
547 return rc;
548 }
[cc29622]549
[a8c4e871]550 rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe,
[e9f0348]551 hid_dev->usb_dev->interface_no, USB_HID_PROTOCOL_BOOT);
[cc29622]552
[e9f0348]553 if (rc != EOK) {
554 usb_log_warning("Failed to set boot protocol to the device: "
555 "%s\n", str_error(rc));
556 return rc;
557 }
[cc29622]558
[e9f0348]559 return EOK;
560}
561
562/**
563 * @}
564 */
Note: See TracBrowser for help on using the repository browser.