source: mainline/uspace/drv/usbhid/kbdrepeat.c@ 41b96b4

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 41b96b4 was 00b13408, checked in by Lubos Slovak <lubos.slovak@…>, 15 years ago

Fixed destroying of KBD structure when polling ended.

The structure must be destroyed in the autorepeat fibril, as there is
no nice way to stop the fibril on demand.

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