source: mainline/uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.c@ 9871bca

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

usbhid: Wait for autorepeat fibril during destruction.

Fixes random failure on keyboard unplug.
Add a bunch of debug messages.

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/*
2 * Copyright (c) 2011 Lubos Slovak
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 HID keyboard autorepeat facilities
35 */
36
37#include <fibril_synch.h>
38#include <io/keycode.h>
39#include <io/console.h>
40#include <errno.h>
41
42#include <usb/debug.h>
43
44#include "kbdrepeat.h"
45#include "kbddev.h"
46
47
48
49/*----------------------------------------------------------------------------*/
50/**
51 * Main loop handling the auto-repeat of keys.
52 *
53 * This functions periodically checks if there is some key to be auto-repeated.
54 *
55 * If a new key is to be repeated, it uses the delay before first repeat stored
56 * in the keyboard structure to wait until the key has to start repeating.
57 *
58 * If the same key is still pressed, it uses the delay between repeats stored
59 * in the keyboard structure to wait until the key should be repeated.
60 *
61 * If the currently repeated key is not pressed any more (
62 * usb_kbd_repeat_stop() was called), it stops repeating it and starts
63 * checking again.
64 *
65 * @note For accessing the keyboard device auto-repeat information a fibril
66 * mutex (repeat_mtx) from the @a kbd structure is used.
67 *
68 * @param kbd Keyboard device structure.
69 */
70static void usb_kbd_repeat_loop(usb_kbd_t *kbd)
71{
72 unsigned int delay = 0;
73
74 usb_log_debug("Starting autorepeat loop.\n");
75
76 while (true) {
77 // check if the kbd structure is usable
78 if (!usb_kbd_is_initialized(kbd)) {
79 usb_log_warning("kbd not ready, exiting autorepeat.\n");
80 return;
81 }
82
83 fibril_mutex_lock(&kbd->repeat_mtx);
84
85 if (kbd->repeat.key_new > 0) {
86 if (kbd->repeat.key_new == kbd->repeat.key_repeated) {
87 usb_log_debug2("Repeating key: %u.\n",
88 kbd->repeat.key_repeated);
89 // ugly hack with the NULL
90 usb_kbd_push_ev(NULL, kbd, KEY_PRESS,
91 kbd->repeat.key_repeated);
92 delay = kbd->repeat.delay_between;
93 } else {
94 usb_log_debug2("New key to repeat: %u.\n",
95 kbd->repeat.key_new);
96 kbd->repeat.key_repeated = kbd->repeat.key_new;
97 delay = kbd->repeat.delay_before;
98 }
99 } else {
100 if (kbd->repeat.key_repeated > 0) {
101 usb_log_debug2("Stopping to repeat key: %u.\n",
102 kbd->repeat.key_repeated);
103 kbd->repeat.key_repeated = 0;
104 }
105 delay = CHECK_DELAY;
106 }
107 fibril_mutex_unlock(&kbd->repeat_mtx);
108
109 async_usleep(delay);
110 }
111}
112
113/*----------------------------------------------------------------------------*/
114/**
115 * Main routine to be executed by a fibril for handling auto-repeat.
116 *
117 * Starts the loop for checking changes in auto-repeat.
118 *
119 * @param arg User-specified argument. Expects pointer to the keyboard device
120 * structure representing the keyboard.
121 *
122 * @retval EOK if the routine has finished.
123 * @retval EINVAL if no argument is supplied.
124 */
125int usb_kbd_repeat_fibril(void *arg)
126{
127 usb_log_debug("Autorepeat fibril spawned.\n");
128
129 if (arg == NULL) {
130 usb_log_error("No device!\n");
131 return EINVAL;
132 }
133
134 usb_kbd_t *kbd = (usb_kbd_t *)arg;
135
136 usb_kbd_repeat_loop(kbd);
137
138 return EOK;
139}
140
141/*----------------------------------------------------------------------------*/
142/**
143 * Start repeating particular key.
144 *
145 * @note Only one key is repeated at any time, so calling this function
146 * effectively cancels auto-repeat of the current repeated key (if any)
147 * and 'schedules' another key for auto-repeat.
148 *
149 * @param kbd Keyboard device structure.
150 * @param key Key to start repeating.
151 */
152void usb_kbd_repeat_start(usb_kbd_t *kbd, unsigned int key)
153{
154 fibril_mutex_lock(&kbd->repeat_mtx);
155 kbd->repeat.key_new = key;
156 fibril_mutex_unlock(&kbd->repeat_mtx);
157}
158
159/*----------------------------------------------------------------------------*/
160/**
161 * Stop repeating particular key.
162 *
163 * @note Only one key is repeated at any time, but this function may be called
164 * even with key that is not currently repeated (in that case nothing
165 * happens).
166 *
167 * @param kbd Keyboard device structure.
168 * @param key Key to stop repeating.
169 */
170void usb_kbd_repeat_stop(usb_kbd_t *kbd, unsigned int key)
171{
172 fibril_mutex_lock(&kbd->repeat_mtx);
173 if (key == kbd->repeat.key_new) {
174 kbd->repeat.key_new = 0;
175 }
176 fibril_mutex_unlock(&kbd->repeat_mtx);
177}
178
179/**
180 * @}
181 */
Note: See TracBrowser for help on using the repository browser.