Merge "package: version up" into develop
[sdk/emulator/qemu.git] / input.c
1 /*
2  * QEMU System Emulator
3  *
4  * Copyright (c) 2003-2008 Fabrice Bellard
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24
25 #include "sysemu.h"
26 #include "net.h"
27 #include "monitor.h"
28 #include "console.h"
29 #include "error.h"
30 #include "qmp-commands.h"
31 #include "tizen/src/debug_ch.h"
32
33 MULTI_DEBUG_CHANNEL(tizen, input);
34
35 static QEMUPutKBDEvent *qemu_put_kbd_event;
36 static void *qemu_put_kbd_event_opaque;
37 static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers = QTAILQ_HEAD_INITIALIZER(led_handlers);
38 static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers =
39     QTAILQ_HEAD_INITIALIZER(mouse_handlers);
40 static NotifierList mouse_mode_notifiers = 
41     NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);
42
43 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
44 {
45     qemu_put_kbd_event_opaque = opaque;
46     qemu_put_kbd_event = func;
47 }
48
49 void qemu_remove_kbd_event_handler(void)
50 {
51     qemu_put_kbd_event_opaque = NULL;
52     qemu_put_kbd_event = NULL;
53 }
54
55 static void check_mode_change(void)
56 {
57     static int current_is_absolute, current_has_absolute;
58     int is_absolute;
59     int has_absolute;
60
61     is_absolute = kbd_mouse_is_absolute();
62     has_absolute = kbd_mouse_has_absolute();
63
64     if (is_absolute != current_is_absolute ||
65         has_absolute != current_has_absolute) {
66         notifier_list_notify(&mouse_mode_notifiers, NULL);
67     }
68
69     current_is_absolute = is_absolute;
70     current_has_absolute = has_absolute;
71 }
72
73 QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
74                                                 void *opaque, int absolute,
75                                                 const char *name)
76 {
77     QEMUPutMouseEntry *s;
78     static int mouse_index = 0;
79
80     s = g_malloc0(sizeof(QEMUPutMouseEntry));
81
82     s->qemu_put_mouse_event = func;
83     s->qemu_put_mouse_event_opaque = opaque;
84     s->qemu_put_mouse_event_absolute = absolute;
85     s->qemu_put_mouse_event_name = g_strdup(name);
86     s->index = mouse_index++;
87
88     QTAILQ_INSERT_TAIL(&mouse_handlers, s, node);
89
90     check_mode_change();
91
92     return s;
93 }
94
95 void qemu_activate_mouse_event_handler(QEMUPutMouseEntry *entry)
96 {
97     QTAILQ_REMOVE(&mouse_handlers, entry, node);
98     QTAILQ_INSERT_HEAD(&mouse_handlers, entry, node);
99
100     check_mode_change();
101 }
102
103 void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry)
104 {
105     QTAILQ_REMOVE(&mouse_handlers, entry, node);
106
107     g_free(entry->qemu_put_mouse_event_name);
108     g_free(entry);
109
110     check_mode_change();
111 }
112
113 QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func,
114                                             void *opaque)
115 {
116     QEMUPutLEDEntry *s;
117
118     s = g_malloc0(sizeof(QEMUPutLEDEntry));
119
120     s->put_led = func;
121     s->opaque = opaque;
122     QTAILQ_INSERT_TAIL(&led_handlers, s, next);
123     return s;
124 }
125
126 void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
127 {
128     if (entry == NULL)
129         return;
130     QTAILQ_REMOVE(&led_handlers, entry, next);
131     g_free(entry);
132 }
133
134 void kbd_put_keycode(int keycode)
135 {
136     if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
137         return;
138     }
139     if (qemu_put_kbd_event) {
140         qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode);
141     }
142 }
143
144 void kbd_put_ledstate(int ledstate)
145 {
146     QEMUPutLEDEntry *cursor;
147
148     QTAILQ_FOREACH(cursor, &led_handlers, next) {
149         cursor->put_led(cursor->opaque, ledstate);
150     }
151 }
152
153 void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
154 {
155     QEMUPutMouseEntry *entry;
156     QEMUPutMouseEvent *mouse_event;
157     void *mouse_event_opaque;
158     int width, height;
159
160     if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
161         return;
162     }
163     if (QTAILQ_EMPTY(&mouse_handlers)) {
164         return;
165     }
166 #if defined (CONFIG_MARU)
167     QTAILQ_FOREACH(entry, &mouse_handlers, node) {
168         /* if mouse event is wheelup ,wheeldown or move
169            then go to ps2 mouse event(index == 0) */
170         if (buttons_state > 3  && entry->index == 0) {
171             //INFO("input device: %s, event: %d\n", entry->qemu_put_mouse_event_name, buttons_state);
172             buttons_state = 0; 
173             mouse_event = entry->qemu_put_mouse_event;
174             mouse_event_opaque = entry->qemu_put_mouse_event_opaque;
175             break;
176         }
177     }
178     /* other events(mouse up, down and drag), go to touch screen */
179     if (!entry) {
180         entry = QTAILQ_FIRST(&mouse_handlers);
181         mouse_event = entry->qemu_put_mouse_event;
182         mouse_event_opaque = entry->qemu_put_mouse_event_opaque;
183         //INFO("input device: %s, event: %d\n", entry->qemu_put_mouse_event_name, buttons_state);
184     }
185 #else
186     entry = QTAILQ_FIRST(&mouse_handlers);
187
188     mouse_event = entry->qemu_put_mouse_event;
189     mouse_event_opaque = entry->qemu_put_mouse_event_opaque;
190 #endif
191     if (mouse_event) {
192         if (entry->qemu_put_mouse_event_absolute) {
193             width = 0x7fff;
194             height = 0x7fff;
195         } else {
196             width = graphic_width - 1;
197             height = graphic_height - 1;
198         }
199
200         switch (graphic_rotate) {
201         case 0:
202             mouse_event(mouse_event_opaque,
203                         dx, dy, dz, buttons_state);
204             break;
205         case 90:
206             mouse_event(mouse_event_opaque,
207                         width - dy, dx, dz, buttons_state);
208             break;
209         case 180:
210             mouse_event(mouse_event_opaque,
211                         width - dx, height - dy, dz, buttons_state);
212             break;
213         case 270:
214             mouse_event(mouse_event_opaque,
215                         dy, height - dx, dz, buttons_state);
216             break;
217         }
218     }
219 }
220
221 int kbd_mouse_is_absolute(void)
222 {
223     if (QTAILQ_EMPTY(&mouse_handlers)) {
224         return 0;
225     }
226
227     return QTAILQ_FIRST(&mouse_handlers)->qemu_put_mouse_event_absolute;
228 }
229
230 int kbd_mouse_has_absolute(void)
231 {
232     QEMUPutMouseEntry *entry;
233
234     QTAILQ_FOREACH(entry, &mouse_handlers, node) {
235         if (entry->qemu_put_mouse_event_absolute) {
236             return 1;
237         }
238     }
239
240     return 0;
241 }
242
243 MouseInfoList *qmp_query_mice(Error **errp)
244 {
245     MouseInfoList *mice_list = NULL;
246     QEMUPutMouseEntry *cursor;
247     bool current = true;
248
249     QTAILQ_FOREACH(cursor, &mouse_handlers, node) {
250         MouseInfoList *info = g_malloc0(sizeof(*info));
251         info->value = g_malloc0(sizeof(*info->value));
252         info->value->name = g_strdup(cursor->qemu_put_mouse_event_name);
253         info->value->index = cursor->index;
254         info->value->absolute = !!cursor->qemu_put_mouse_event_absolute;
255         info->value->current = current;
256
257         current = false;
258
259         info->next = mice_list;
260         mice_list = info;
261     }
262
263     return mice_list;
264 }
265
266 void do_mouse_set(Monitor *mon, const QDict *qdict)
267 {
268     QEMUPutMouseEntry *cursor;
269     int index = qdict_get_int(qdict, "index");
270     int found = 0;
271
272     if (QTAILQ_EMPTY(&mouse_handlers)) {
273         monitor_printf(mon, "No mouse devices connected\n");
274         return;
275     }
276
277     QTAILQ_FOREACH(cursor, &mouse_handlers, node) {
278         if (cursor->index == index) {
279             found = 1;
280             qemu_activate_mouse_event_handler(cursor);
281             break;
282         }
283     }
284
285     if (!found) {
286         monitor_printf(mon, "Mouse at given index not found\n");
287     }
288
289     check_mode_change();
290 }
291
292 void qemu_add_mouse_mode_change_notifier(Notifier *notify)
293 {
294     notifier_list_add(&mouse_mode_notifiers, notify);
295 }
296
297 void qemu_remove_mouse_mode_change_notifier(Notifier *notify)
298 {
299     notifier_remove(notify);
300 }