1 /*
2 (c) Copyright 2001-2010 The world wide DirectFB Open Source Community (directfb.org)
3 (c) Copyright 2000-2004 Convergence (integrated media) GmbH
4
5 All rights reserved.
6
7 Written by Denis Oliver Kropp <dok@directfb.org>,
8 Andreas Hundt <andi@fischlustig.de>,
9 Sven Neumann <neo@directfb.org>,
10 Ville Syrjälä <syrjala@sci.fi> and
11 Claudio Ciccani <klan@users.sf.net>.
12
13 This library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Lesser General Public
15 License as published by the Free Software Foundation; either
16 version 2 of the License, or (at your option) any later version.
17
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Lesser General Public License for more details.
22
23 You should have received a copy of the GNU Lesser General Public
24 License along with this library; if not, write to the
25 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 Boston, MA 02111-1307, USA.
27 */
28
29 #include <config.h>
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39
40 #include <directfb.h>
41 #include <directfb_keynames.h>
42
43 #include <direct/debug.h>
44 #include <direct/list.h>
45 #include <direct/memcpy.h>
46 #include <direct/messages.h>
47
48
49 #include <fusion/shmalloc.h>
50 #include <fusion/reactor.h>
51 #include <fusion/arena.h>
52
53 #include <core/CoreInputDevice.h>
54
55 #include <core/core.h>
56 #include <core/coredefs.h>
57 #include <core/coretypes.h>
58
59 #include <core/core_parts.h>
60
61 #include <core/gfxcard.h>
62 #include <core/surface.h>
63 #include <core/surface_buffer.h>
64 #include <core/system.h>
65 #include <core/layer_context.h>
66 #include <core/layer_control.h>
67 #include <core/layer_region.h>
68 #include <core/layers.h>
69 #include <core/input.h>
70 #include <core/windows.h>
71 #include <core/windows_internal.h>
72
73 #include <direct/mem.h>
74 #include <direct/memcpy.h>
75 #include <direct/messages.h>
76 #include <direct/modules.h>
77 #include <direct/trace.h>
78
79 #include <fusion/build.h>
80
81 #include <misc/conf.h>
82 #include <misc/util.h>
83
84 #include <gfx/convert.h>
85
86
87 #define CHECK_INTERVAL 20000 // Microseconds
88 #define CHECK_NUMBER 200
89
90
91 D_DEBUG_DOMAIN( Core_Input, "Core/Input", "DirectFB Input Core" );
92 D_DEBUG_DOMAIN( Core_InputEvt, "Core/Input/Evt", "DirectFB Input Core Events & Dispatch" );
93
94
95 DEFINE_MODULE_DIRECTORY( dfb_input_modules, "inputdrivers", DFB_INPUT_DRIVER_ABI_VERSION );
96
97 /**********************************************************************************************************************/
98
99 typedef enum {
100 CIDC_RELOAD_KEYMAP
101 } CoreInputDeviceCommand;
102
103 typedef struct {
104 DirectLink link;
105
106 int magic;
107
108 DirectModuleEntry *module;
109
110 const InputDriverFuncs *funcs;
111
112 InputDriverInfo info;
113
114 int nr_devices;
115 } InputDriver;
116
117 typedef struct {
118 int min_keycode;
119 int max_keycode;
120 int num_entries;
121 DFBInputDeviceKeymapEntry *entries;
122 } InputDeviceKeymap;
123
124 typedef struct {
125 int magic;
126
127 DFBInputDeviceID id; /* unique device id */
128
129 int num;
130
131 InputDeviceInfo device_info;
132
133 InputDeviceKeymap keymap;
134
135 CoreInputDeviceState state;
136
137 DFBInputDeviceKeyIdentifier last_key; /* last key pressed */
138 DFBInputDeviceKeySymbol last_symbol; /* last symbol pressed */
139 bool first_press; /* first press of key */
140
141 FusionReactor *reactor; /* event dispatcher */
142 FusionSkirmish lock;
143
144 unsigned int axis_num;
145 DFBInputDeviceAxisInfo *axis_info;
146 FusionRef ref; /* Ref between shared device & local device */
147
148 FusionCall call;
149 } InputDeviceShared;
150
151 struct __DFB_CoreInputDevice {
152 DirectLink link;
153
154 int magic;
155
156 InputDeviceShared *shared;
157
158 InputDriver *driver;
159 void *driver_data;
160
161 CoreDFB *core;
162 };
163
164 /**********************************************************************************************************************/
165
166 DirectResult
CoreInputDevice_Call(CoreInputDevice * device,FusionCallExecFlags flags,int call_arg,void * ptr,unsigned int length,void * ret_ptr,unsigned int ret_size,unsigned int * ret_length)167 CoreInputDevice_Call( CoreInputDevice *device,
168 FusionCallExecFlags flags,
169 int call_arg,
170 void *ptr,
171 unsigned int length,
172 void *ret_ptr,
173 unsigned int ret_size,
174 unsigned int *ret_length )
175 {
176 D_ASSERT( device != NULL );
177 D_ASSERT( device->shared != NULL );
178
179 return fusion_call_execute3( &device->shared->call, flags, call_arg, ptr, length, ret_ptr, ret_size, ret_length );
180 }
181
182 /**********************************************************************************************************************/
183
184 typedef struct {
185 int magic;
186
187 int num;
188 InputDeviceShared *devices[MAX_INPUTDEVICES];
189 FusionReactor *reactor; /* For input hot-plug event */
190 } DFBInputCoreShared;
191
192 struct __DFB_DFBInputCore {
193 int magic;
194
195 CoreDFB *core;
196
197 DFBInputCoreShared *shared;
198
199 DirectLink *drivers;
200 DirectLink *devices;
201 };
202
203
204 DFB_CORE_PART( input_core, InputCore );
205
206 /**********************************************************************************************************************/
207
208 typedef struct {
209 DFBInputDeviceKeySymbol target;
210 DFBInputDeviceKeySymbol result;
211 } DeadKeyCombo;
212
213 typedef struct {
214 DFBInputDeviceKeySymbol deadkey;
215 const DeadKeyCombo *combos;
216 } DeadKeyMap;
217
218 /* Data struct of input device hotplug event */
219 typedef struct {
220 bool is_plugin; /* Hotplug in or not */
221 int dev_id; /* Input device ID*/
222 struct timeval stamp; /* Time stamp of event */
223 } InputDeviceHotplugEvent;
224
225 /**********************************************************************************************************************/
226
227 static const DeadKeyCombo combos_grave[] = {
228 { DIKS_SPACE, (unsigned char) '`' },
229 { DIKS_SMALL_A, (unsigned char) 0xe0 }, // '�'
230 { DIKS_SMALL_E, (unsigned char) 0xe8 }, // '�'
231 { DIKS_SMALL_I, (unsigned char) 0xec }, // '�'
232 { DIKS_SMALL_O, (unsigned char) 0xf2 }, // '�'
233 { DIKS_SMALL_U, (unsigned char) 0xf9 }, // '�'
234 { DIKS_CAPITAL_A, (unsigned char) 0xc0 }, // '�'
235 { DIKS_CAPITAL_E, (unsigned char) 0xc8 }, // '�'
236 { DIKS_CAPITAL_I, (unsigned char) 0xcc }, // '�'
237 { DIKS_CAPITAL_O, (unsigned char) 0xd2 }, // '�'
238 { DIKS_CAPITAL_U, (unsigned char) 0xd9 }, // '�'
239 { 0, 0 }
240 };
241
242 static const DeadKeyCombo combos_acute[] = {
243 { DIKS_SPACE, (unsigned char) '\'' },
244 { DIKS_SMALL_A, (unsigned char) '�' },
245 { DIKS_SMALL_E, (unsigned char) '�' },
246 { DIKS_SMALL_I, (unsigned char) '�' },
247 { DIKS_SMALL_O, (unsigned char) '�' },
248 { DIKS_SMALL_U, (unsigned char) '�' },
249 { DIKS_SMALL_Y, (unsigned char) '�' },
250 { DIKS_CAPITAL_A, (unsigned char) '�' },
251 { DIKS_CAPITAL_E, (unsigned char) '�' },
252 { DIKS_CAPITAL_I, (unsigned char) '�' },
253 { DIKS_CAPITAL_O, (unsigned char) '�' },
254 { DIKS_CAPITAL_U, (unsigned char) '�' },
255 { DIKS_CAPITAL_Y, (unsigned char) '�' },
256 { 0, 0 }
257 };
258
259 static const DeadKeyCombo combos_circumflex[] = {
260 { DIKS_SPACE, (unsigned char) '^' },
261 { DIKS_SMALL_A, (unsigned char) '�' },
262 { DIKS_SMALL_E, (unsigned char) '�' },
263 { DIKS_SMALL_I, (unsigned char) '�' },
264 { DIKS_SMALL_O, (unsigned char) '�' },
265 { DIKS_SMALL_U, (unsigned char) '�' },
266 { DIKS_CAPITAL_A, (unsigned char) '�' },
267 { DIKS_CAPITAL_E, (unsigned char) '�' },
268 { DIKS_CAPITAL_I, (unsigned char) '�' },
269 { DIKS_CAPITAL_O, (unsigned char) '�' },
270 { DIKS_CAPITAL_U, (unsigned char) '�' },
271 { 0, 0 }
272 };
273
274 static const DeadKeyCombo combos_diaeresis[] = {
275 { DIKS_SPACE, (unsigned char) '�' },
276 { DIKS_SMALL_A, (unsigned char) '�' },
277 { DIKS_SMALL_E, (unsigned char) '�' },
278 { DIKS_SMALL_I, (unsigned char) '�' },
279 { DIKS_SMALL_O, (unsigned char) '�' },
280 { DIKS_SMALL_U, (unsigned char) '�' },
281 { DIKS_CAPITAL_A, (unsigned char) '�' },
282 { DIKS_CAPITAL_E, (unsigned char) '�' },
283 { DIKS_CAPITAL_I, (unsigned char) '�' },
284 { DIKS_CAPITAL_O, (unsigned char) '�' },
285 { DIKS_CAPITAL_U, (unsigned char) '�' },
286 { 0, 0 }
287 };
288
289 static const DeadKeyCombo combos_tilde[] = {
290 { DIKS_SPACE, (unsigned char) '~' },
291 { DIKS_SMALL_A, (unsigned char) '�' },
292 { DIKS_SMALL_N, (unsigned char) '�' },
293 { DIKS_SMALL_O, (unsigned char) '�' },
294 { DIKS_CAPITAL_A, (unsigned char) '�' },
295 { DIKS_CAPITAL_N, (unsigned char) '�' },
296 { DIKS_CAPITAL_O, (unsigned char) '�' },
297 { 0, 0 }
298 };
299
300 static const DeadKeyMap deadkey_maps[] = {
301 { DIKS_DEAD_GRAVE, combos_grave },
302 { DIKS_DEAD_ACUTE, combos_acute },
303 { DIKS_DEAD_CIRCUMFLEX, combos_circumflex },
304 { DIKS_DEAD_DIAERESIS, combos_diaeresis },
305 { DIKS_DEAD_TILDE, combos_tilde }
306 };
307
308 /* define a lookup table to go from key IDs to names.
309 * This is used to look up the names provided in a loaded key table */
310 /* this table is roughly 4Kb in size */
311 DirectFBKeySymbolNames(KeySymbolNames);
312 DirectFBKeyIdentifierNames(KeyIdentifierNames);
313
314 /**********************************************************************************************************************/
315
316 static void init_devices( CoreDFB *core );
317
318 static void allocate_device_keymap( CoreDFB *core, CoreInputDevice *device );
319
320 static DFBInputDeviceKeymapEntry *get_keymap_entry( CoreInputDevice *device,
321 int code );
322
323 static DFBResult set_keymap_entry( CoreInputDevice *device,
324 int code,
325 const DFBInputDeviceKeymapEntry *entry );
326
327 static DFBResult load_keymap( CoreInputDevice *device,
328 char *filename );
329
330 static DFBResult reload_keymap( CoreInputDevice *device );
331
332 static DFBInputDeviceKeySymbol lookup_keysymbol( char *symbolname );
333 static DFBInputDeviceKeyIdentifier lookup_keyidentifier( char *identifiername );
334
335 /**********************************************************************************************************************/
336
337 static bool lookup_from_table( CoreInputDevice *device,
338 DFBInputEvent *event,
339 DFBInputEventFlags lookup );
340
341 static void fixup_key_event ( CoreInputDevice *device,
342 DFBInputEvent *event );
343
344 static void fixup_mouse_event( CoreInputDevice *device,
345 DFBInputEvent *event );
346
347 static void flush_keys ( CoreInputDevice *device );
348
349 static bool core_input_filter( CoreInputDevice *device,
350 DFBInputEvent *event );
351
352 /**********************************************************************************************************************/
353
354 static DFBInputDeviceKeyIdentifier symbol_to_id( DFBInputDeviceKeySymbol symbol );
355
356 static DFBInputDeviceKeySymbol id_to_symbol( DFBInputDeviceKeyIdentifier id,
357 DFBInputDeviceModifierMask modifiers,
358 DFBInputDeviceLockState locks );
359
360 /**********************************************************************************************************************/
361
362 static ReactionResult local_processing_hotplug( const void *msg_data, void *ctx );
363
364 /**********************************************************************************************************************/
365
366 static ReactionFunc dfb_input_globals[MAX_INPUT_GLOBALS+1] = {
367 /* 0 */ _dfb_windowstack_inputdevice_listener,
368 NULL
369 };
370
371 DFBResult
dfb_input_add_global(ReactionFunc func,int * ret_index)372 dfb_input_add_global( ReactionFunc func,
373 int *ret_index )
374 {
375 int i;
376
377 D_DEBUG_AT( Core_Input, "%s( %p, %p )\n", __FUNCTION__, func, ret_index );
378
379 D_ASSERT( func != NULL );
380 D_ASSERT( ret_index != NULL );
381
382 for (i=0; i<MAX_INPUT_GLOBALS; i++) {
383 if (!dfb_input_globals[i]) {
384 dfb_input_globals[i] = func;
385
386 D_DEBUG_AT( Core_Input, " -> index %d\n", i );
387
388 *ret_index = i;
389
390 return DFB_OK;
391 }
392 }
393
394 return DFB_LIMITEXCEEDED;
395 }
396
397 DFBResult
dfb_input_set_global(ReactionFunc func,int index)398 dfb_input_set_global( ReactionFunc func,
399 int index )
400 {
401 D_DEBUG_AT( Core_Input, "%s( %p, %d )\n", __FUNCTION__, func, index );
402
403 D_ASSERT( func != NULL );
404 D_ASSERT( index >= 0 );
405 D_ASSERT( index < MAX_INPUT_GLOBALS );
406
407 D_ASSUME( dfb_input_globals[index] == NULL );
408
409 dfb_input_globals[index] = func;
410
411 return DFB_OK;
412 }
413
414 /**********************************************************************************************************************/
415
416 static DFBInputCore *core_local; /* FIXME */
417 static DFBInputCoreShared *core_input; /* FIXME */
418
419 #if FUSION_BUILD_MULTI
420 static Reaction local_processing_react; /* Local reaction to hot-plug event */
421 #endif
422
423
424 static DFBResult
dfb_input_core_initialize(CoreDFB * core,DFBInputCore * data,DFBInputCoreShared * shared)425 dfb_input_core_initialize( CoreDFB *core,
426 DFBInputCore *data,
427 DFBInputCoreShared *shared )
428 {
429 #if FUSION_BUILD_MULTI
430 DFBResult result = DFB_OK;
431 #endif
432
433 D_DEBUG_AT( Core_Input, "dfb_input_core_initialize( %p, %p, %p )\n", core, data, shared );
434
435 D_ASSERT( data != NULL );
436 D_ASSERT( shared != NULL );
437
438 core_local = data; /* FIXME */
439 core_input = shared; /* FIXME */
440
441 data->core = core;
442 data->shared = shared;
443
444
445 direct_modules_explore_directory( &dfb_input_modules );
446
447 #if FUSION_BUILD_MULTI
448 /* Create the reactor that responds input device hot-plug events. */
449 core_input->reactor = fusion_reactor_new(
450 sizeof( InputDeviceHotplugEvent ),
451 "Input Hotplug",
452 dfb_core_world(core) );
453 if (!core_input->reactor) {
454 D_ERROR( "DirectFB/Input: fusion_reactor_new() failed!\n" );
455 result = DFB_FAILURE;
456 goto errorExit;
457 }
458
459 fusion_reactor_add_permissions( core_input->reactor, 0, FUSION_REACTOR_PERMIT_ATTACH_DETACH );
460
461 /* Attach local process function to the input hot-plug reactor. */
462 result = fusion_reactor_attach(
463 core_input->reactor,
464 local_processing_hotplug,
465 (void*) core,
466 &local_processing_react );
467 if (result) {
468 D_ERROR( "DirectFB/Input: fusion_reactor_attach() failed!\n" );
469 goto errorExit;
470 }
471 #endif
472
473 init_devices( core );
474
475
476 D_MAGIC_SET( data, DFBInputCore );
477 D_MAGIC_SET( shared, DFBInputCoreShared );
478
479 return DFB_OK;
480
481 #if FUSION_BUILD_MULTI
482 errorExit:
483 /* Destroy the hot-plug reactor if it was created. */
484 if (core_input->reactor)
485 fusion_reactor_destroy(core_input->reactor);
486
487 return result;
488 #endif
489 }
490
491 static DFBResult
dfb_input_core_join(CoreDFB * core,DFBInputCore * data,DFBInputCoreShared * shared)492 dfb_input_core_join( CoreDFB *core,
493 DFBInputCore *data,
494 DFBInputCoreShared *shared )
495 {
496 int i;
497 #if FUSION_BUILD_MULTI
498 DFBResult result;
499 #endif
500
501 D_DEBUG_AT( Core_Input, "dfb_input_core_join( %p, %p, %p )\n", core, data, shared );
502
503 D_ASSERT( data != NULL );
504 D_MAGIC_ASSERT( shared, DFBInputCoreShared );
505 D_ASSERT( shared->reactor != NULL );
506
507 core_local = data; /* FIXME */
508 core_input = shared; /* FIXME */
509
510 data->core = core;
511 data->shared = shared;
512
513 #if FUSION_BUILD_MULTI
514 /* Attach the local process function to the input hot-plug reactor. */
515 result = fusion_reactor_attach( core_input->reactor,
516 local_processing_hotplug,
517 (void*) core,
518 &local_processing_react );
519 if (result) {
520 D_ERROR( "DirectFB/Input: fusion_reactor_attach failed!\n" );
521 return result;
522 }
523 #endif
524
525 for (i=0; i<core_input->num; i++) {
526 CoreInputDevice *device;
527
528 device = D_CALLOC( 1, sizeof(CoreInputDevice) );
529 if (!device) {
530 D_OOM();
531 continue;
532 }
533
534 device->shared = core_input->devices[i];
535
536 #if FUSION_BUILD_MULTI
537 /* Increase the reference counter. */
538 fusion_ref_up( &device->shared->ref, false );
539 #endif
540
541 /* add it to the list */
542 direct_list_append( &data->devices, &device->link );
543
544 D_MAGIC_SET( device, CoreInputDevice );
545 }
546
547
548 D_MAGIC_SET( data, DFBInputCore );
549
550 return DFB_OK;
551 }
552
553 static DFBResult
dfb_input_core_shutdown(DFBInputCore * data,bool emergency)554 dfb_input_core_shutdown( DFBInputCore *data,
555 bool emergency )
556 {
557 DFBInputCoreShared *shared;
558 DirectLink *n;
559 CoreInputDevice *device;
560 FusionSHMPoolShared *pool = dfb_core_shmpool( data->core );
561 InputDriver *driver;
562
563 D_DEBUG_AT( Core_Input, "dfb_input_core_shutdown( %p, %semergency )\n", data, emergency ? "" : "no " );
564
565 D_MAGIC_ASSERT( data, DFBInputCore );
566 D_MAGIC_ASSERT( data->shared, DFBInputCoreShared );
567
568 shared = data->shared;
569
570 /* Stop each input provider's hot-plug thread that supports device hot-plugging. */
571 direct_list_foreach_safe (driver, n, core_local->drivers) {
572 if (driver->funcs->GetCapability && driver->funcs->StopHotplug) {
573 if (IDC_HOTPLUG & driver->funcs->GetCapability()) {
574 D_DEBUG_AT( Core_Input, "Stopping hot-plug detection thread "
575 "within %s\n ", driver->module->name );
576 if (driver->funcs->StopHotplug()) {
577 D_ERROR( "DirectFB/Input: StopHotplug() failed with %s\n",
578 driver->module->name );
579 }
580 }
581 }
582 }
583
584 #if FUSION_BUILD_MULTI
585 fusion_reactor_detach( core_input->reactor, &local_processing_react );
586 fusion_reactor_destroy( core_input->reactor );
587 #endif
588
589 direct_list_foreach_safe (device, n, data->devices) {
590 InputDeviceShared *devshared;
591
592 D_MAGIC_ASSERT( device, CoreInputDevice );
593
594 driver = device->driver;
595 D_ASSERT( driver != NULL );
596
597 devshared = device->shared;
598 D_ASSERT( devshared != NULL );
599
600 CoreInputDevice_Deinit_Dispatch( &devshared->call );
601
602 fusion_skirmish_destroy( &devshared->lock );
603
604 if (device->driver_data != NULL) {
605 void *driver_data;
606
607 D_ASSERT( driver->funcs != NULL );
608 D_ASSERT( driver->funcs->CloseDevice != NULL );
609
610 D_DEBUG_AT( Core_Input, " -> closing '%s' (%d) %d.%d (%s)\n",
611 devshared->device_info.desc.name, devshared->num + 1,
612 driver->info.version.major,
613 driver->info.version.minor, driver->info.vendor );
614
615 driver_data = device->driver_data;
616 device->driver_data = NULL;
617 driver->funcs->CloseDevice( driver_data );
618 }
619
620 if (!--driver->nr_devices) {
621 direct_module_unref( driver->module );
622 D_FREE( driver );
623 }
624
625 #if FUSION_BUILD_MULTI
626 fusion_ref_destroy( &device->shared->ref );
627 #endif
628
629 fusion_reactor_free( devshared->reactor );
630
631 if (devshared->keymap.entries)
632 SHFREE( pool, devshared->keymap.entries );
633
634 if (devshared->axis_info)
635 SHFREE( pool, devshared->axis_info );
636
637 SHFREE( pool, devshared );
638
639 D_MAGIC_CLEAR( device );
640
641 D_FREE( device );
642 }
643
644 D_MAGIC_CLEAR( data );
645 D_MAGIC_CLEAR( shared );
646
647 return DFB_OK;
648 }
649
650 static DFBResult
dfb_input_core_leave(DFBInputCore * data,bool emergency)651 dfb_input_core_leave( DFBInputCore *data,
652 bool emergency )
653 {
654 DFBInputCoreShared *shared;
655 DirectLink *n;
656 CoreInputDevice *device;
657
658 D_DEBUG_AT( Core_Input, "dfb_input_core_leave( %p, %semergency )\n", data, emergency ? "" : "no " );
659
660 D_MAGIC_ASSERT( data, DFBInputCore );
661 D_MAGIC_ASSERT( data->shared, DFBInputCoreShared );
662
663 shared = data->shared;
664
665 #if FUSION_BUILD_MULTI
666 fusion_reactor_detach( core_input->reactor, &local_processing_react );
667 #endif
668
669 direct_list_foreach_safe (device, n, data->devices) {
670 D_MAGIC_ASSERT( device, CoreInputDevice );
671
672 #if FUSION_BUILD_MULTI
673 /* Decrease the ref between shared device and local device. */
674 fusion_ref_down( &device->shared->ref, false );
675 #endif
676
677 D_FREE( device );
678 }
679
680
681 D_MAGIC_CLEAR( data );
682
683 return DFB_OK;
684 }
685
686 static DFBResult
dfb_input_core_suspend(DFBInputCore * data)687 dfb_input_core_suspend( DFBInputCore *data )
688 {
689 DFBInputCoreShared *shared;
690 CoreInputDevice *device;
691 InputDriver *driver;
692
693 D_DEBUG_AT( Core_Input, "dfb_input_core_suspend( %p )\n", data );
694
695 D_MAGIC_ASSERT( data, DFBInputCore );
696 D_MAGIC_ASSERT( data->shared, DFBInputCoreShared );
697
698 shared = data->shared;
699
700 D_DEBUG_AT( Core_Input, " -> suspending...\n" );
701
702 /* Go through the drivers list and attempt to suspend all of the drivers that
703 * support the Suspend function.
704 */
705 direct_list_foreach (driver, core_local->drivers) {
706 DFBResult ret;
707
708 D_ASSERT( driver->funcs->Suspend != NULL );
709 ret = driver->funcs->Suspend();
710
711 if (ret != DFB_OK && ret != DFB_UNSUPPORTED) {
712 D_DERROR( ret, "driver->Suspend failed during suspend (%s)\n",
713 driver->info.name );
714 }
715 }
716
717 direct_list_foreach (device, data->devices) {
718 InputDeviceShared *devshared;
719
720 D_MAGIC_ASSERT( device, CoreInputDevice );
721
722 driver = device->driver;
723 D_ASSERT( driver != NULL );
724
725 devshared = device->shared;
726 D_ASSERT( devshared != NULL );
727
728 if (device->driver_data != NULL) {
729 void *driver_data;
730
731 D_ASSERT( driver->funcs != NULL );
732 D_ASSERT( driver->funcs->CloseDevice != NULL );
733
734 D_DEBUG_AT( Core_Input, " -> closing '%s' (%d) %d.%d (%s)\n",
735 devshared->device_info.desc.name, devshared->num + 1,
736 driver->info.version.major,
737 driver->info.version.minor, driver->info.vendor );
738
739 driver_data = device->driver_data;
740 device->driver_data = NULL;
741 driver->funcs->CloseDevice( driver_data );
742 }
743
744 flush_keys( device );
745 }
746
747 D_DEBUG_AT( Core_Input, " -> suspended.\n" );
748
749 return DFB_OK;
750 }
751
752 static DFBResult
dfb_input_core_resume(DFBInputCore * data)753 dfb_input_core_resume( DFBInputCore *data )
754 {
755 DFBInputCoreShared *shared;
756 DFBResult ret;
757 CoreInputDevice *device;
758 InputDriver *driver;
759
760 D_DEBUG_AT( Core_Input, "dfb_input_core_resume( %p )\n", data );
761
762 D_MAGIC_ASSERT( data, DFBInputCore );
763 D_MAGIC_ASSERT( data->shared, DFBInputCoreShared );
764
765 shared = data->shared;
766
767 D_DEBUG_AT( Core_Input, " -> resuming...\n" );
768
769 direct_list_foreach (device, data->devices) {
770 D_MAGIC_ASSERT( device, CoreInputDevice );
771
772 D_DEBUG_AT( Core_Input, " -> reopening '%s' (%d) %d.%d (%s)\n",
773 device->shared->device_info.desc.name, device->shared->num + 1,
774 device->driver->info.version.major,
775 device->driver->info.version.minor,
776 device->driver->info.vendor );
777
778 D_ASSERT( device->driver_data == NULL );
779
780 ret = device->driver->funcs->OpenDevice( device, device->shared->num,
781 &device->shared->device_info,
782 &device->driver_data );
783 if (ret) {
784 D_DERROR( ret, "DirectFB/Input: Failed reopening device "
785 "during resume (%s)!\n", device->shared->device_info.desc.name );
786 device->driver_data = NULL;
787 }
788 }
789
790 /* Go through the drivers list and attempt to resume all of the drivers that
791 * support the Resume function.
792 */
793 direct_list_foreach (driver, core_local->drivers) {
794 D_ASSERT( driver->funcs->Resume != NULL );
795
796 ret = driver->funcs->Resume();
797 if (ret != DFB_OK && ret != DFB_UNSUPPORTED) {
798 D_DERROR( ret, "driver->Resume failed during resume (%s)\n",
799 driver->info.name );
800 }
801 }
802
803 D_DEBUG_AT( Core_Input, " -> resumed.\n" );
804
805 return DFB_OK;
806 }
807
808 void
dfb_input_enumerate_devices(InputDeviceCallback callback,void * ctx,DFBInputDeviceCapabilities caps)809 dfb_input_enumerate_devices( InputDeviceCallback callback,
810 void *ctx,
811 DFBInputDeviceCapabilities caps )
812 {
813 CoreInputDevice *device;
814
815 D_ASSERT( core_input != NULL );
816
817 direct_list_foreach (device, core_local->devices) {
818 DFBInputDeviceCapabilities dev_caps;
819
820 D_MAGIC_ASSERT( device, CoreInputDevice );
821 D_ASSERT( device->shared != NULL );
822
823 dev_caps = device->shared->device_info.desc.caps;
824
825 /* Always match if unclassified */
826 if (!dev_caps)
827 dev_caps = DICAPS_ALL;
828
829 if ((dev_caps & caps) && callback( device, ctx ) == DFENUM_CANCEL)
830 break;
831 }
832 }
833
834 DirectResult
dfb_input_attach(CoreInputDevice * device,ReactionFunc func,void * ctx,Reaction * reaction)835 dfb_input_attach( CoreInputDevice *device,
836 ReactionFunc func,
837 void *ctx,
838 Reaction *reaction )
839 {
840 D_DEBUG_AT( Core_Input, "%s( %p, %p, %p, %p )\n", __FUNCTION__, device, func, ctx, reaction );
841
842 D_MAGIC_ASSERT( device, CoreInputDevice );
843
844 D_ASSERT( core_input != NULL );
845 D_ASSERT( device != NULL );
846 D_ASSERT( device->shared != NULL );
847
848 return fusion_reactor_attach( device->shared->reactor, func, ctx, reaction );
849 }
850
851 DirectResult
dfb_input_detach(CoreInputDevice * device,Reaction * reaction)852 dfb_input_detach( CoreInputDevice *device,
853 Reaction *reaction )
854 {
855 D_DEBUG_AT( Core_Input, "%s( %p, %p )\n", __FUNCTION__, device, reaction );
856
857 D_MAGIC_ASSERT( device, CoreInputDevice );
858
859 D_ASSERT( core_input != NULL );
860 D_ASSERT( device != NULL );
861 D_ASSERT( device->shared != NULL );
862
863 return fusion_reactor_detach( device->shared->reactor, reaction );
864 }
865
866 DirectResult
dfb_input_attach_global(CoreInputDevice * device,int index,void * ctx,GlobalReaction * reaction)867 dfb_input_attach_global( CoreInputDevice *device,
868 int index,
869 void *ctx,
870 GlobalReaction *reaction )
871 {
872 D_DEBUG_AT( Core_Input, "%s( %p, %d, %p, %p )\n", __FUNCTION__, device, index, ctx, reaction );
873
874 D_MAGIC_ASSERT( device, CoreInputDevice );
875
876 D_ASSERT( core_input != NULL );
877 D_ASSERT( device != NULL );
878 D_ASSERT( device->shared != NULL );
879
880 return fusion_reactor_attach_global( device->shared->reactor, index, ctx, reaction );
881 }
882
883 DirectResult
dfb_input_detach_global(CoreInputDevice * device,GlobalReaction * reaction)884 dfb_input_detach_global( CoreInputDevice *device,
885 GlobalReaction *reaction )
886 {
887 D_DEBUG_AT( Core_Input, "%s( %p, %p )\n", __FUNCTION__, device, reaction );
888
889 D_MAGIC_ASSERT( device, CoreInputDevice );
890
891 D_ASSERT( core_input != NULL );
892 D_ASSERT( device != NULL );
893 D_ASSERT( device->shared != NULL );
894
895 return fusion_reactor_detach_global( device->shared->reactor, reaction );
896 }
897
898 const char *
dfb_input_event_type_name(DFBInputEventType type)899 dfb_input_event_type_name( DFBInputEventType type )
900 {
901 switch (type) {
902 case DIET_UNKNOWN:
903 return "UNKNOWN";
904
905 case DIET_KEYPRESS:
906 return "KEYPRESS";
907
908 case DIET_KEYRELEASE:
909 return "KEYRELEASE";
910
911 case DIET_BUTTONPRESS:
912 return "BUTTONPRESS";
913
914 case DIET_BUTTONRELEASE:
915 return "BUTTONRELEASE";
916
917 case DIET_AXISMOTION:
918 return "AXISMOTION";
919
920 default:
921 break;
922 }
923
924 return "<invalid>";
925 }
926
927 void
dfb_input_dispatch(CoreInputDevice * device,DFBInputEvent * event)928 dfb_input_dispatch( CoreInputDevice *device, DFBInputEvent *event )
929 {
930 D_DEBUG_AT( Core_Input, "%s( %p, %p )\n", __FUNCTION__, device, event );
931
932 D_MAGIC_ASSERT( device, CoreInputDevice );
933
934 D_ASSERT( core_input != NULL );
935 D_ASSERT( device != NULL );
936 D_ASSERT( event != NULL );
937
938 /*
939 * When a USB device is hot-removed, it is possible that there are pending events
940 * still being dispatched and the shared field becomes NULL.
941 */
942
943 /*
944 * 0. Sanity checks & debugging...
945 */
946 if (!device->shared) {
947 D_DEBUG_AT( Core_Input, " -> No shared data!\n" );
948 return;
949 }
950
951 D_ASSUME( device->shared->reactor != NULL );
952
953 if (!device->shared->reactor) {
954 D_DEBUG_AT( Core_Input, " -> No reactor!\n" );
955 return;
956 }
957
958 D_DEBUG_AT( Core_InputEvt, " -> (%02x) %s%s%s\n", event->type,
959 dfb_input_event_type_name( event->type ),
960 (event->flags & DIEF_FOLLOW) ? " [FOLLOW]" : "",
961 (event->flags & DIEF_REPEAT) ? " [REPEAT]" : "" );
962
963 #if D_DEBUG_ENABLED
964 if (event->flags & DIEF_TIMESTAMP)
965 D_DEBUG_AT( Core_InputEvt, " -> TIMESTAMP %lu.%06lu\n", event->timestamp.tv_sec, event->timestamp.tv_usec );
966 if (event->flags & DIEF_AXISABS)
967 D_DEBUG_AT( Core_InputEvt, " -> AXISABS %d at %d\n", event->axis, event->axisabs );
968 if (event->flags & DIEF_AXISREL)
969 D_DEBUG_AT( Core_InputEvt, " -> AXISREL %d by %d\n", event->axis, event->axisrel );
970 if (event->flags & DIEF_KEYCODE)
971 D_DEBUG_AT( Core_InputEvt, " -> KEYCODE %d\n", event->key_code );
972 if (event->flags & DIEF_KEYID)
973 D_DEBUG_AT( Core_InputEvt, " -> KEYID 0x%04x\n", event->key_id );
974 if (event->flags & DIEF_KEYSYMBOL)
975 D_DEBUG_AT( Core_InputEvt, " -> KEYSYMBOL 0x%04x\n", event->key_symbol );
976 if (event->flags & DIEF_MODIFIERS)
977 D_DEBUG_AT( Core_InputEvt, " -> MODIFIERS 0x%04x\n", event->modifiers );
978 if (event->flags & DIEF_LOCKS)
979 D_DEBUG_AT( Core_InputEvt, " -> LOCKS 0x%04x\n", event->locks );
980 if (event->flags & DIEF_BUTTONS)
981 D_DEBUG_AT( Core_InputEvt, " -> BUTTONS 0x%04x\n", event->buttons );
982 if (event->flags & DIEF_GLOBAL)
983 D_DEBUG_AT( Core_InputEvt, " -> GLOBAL\n" );
984 #endif
985
986 /*
987 * 1. Fixup event...
988 */
989 event->clazz = DFEC_INPUT;
990 event->device_id = device->shared->id;
991
992 if (!(event->flags & DIEF_TIMESTAMP)) {
993 gettimeofday( &event->timestamp, NULL );
994 event->flags |= DIEF_TIMESTAMP;
995 }
996
997 switch (event->type) {
998 case DIET_BUTTONPRESS:
999 case DIET_BUTTONRELEASE:
1000 D_DEBUG_AT( Core_InputEvt, " -> BUTTON 0x%04x\n", event->button );
1001
1002 if (dfb_config->lefty) {
1003 if (event->button == DIBI_LEFT)
1004 event->button = DIBI_RIGHT;
1005 else if (event->button == DIBI_RIGHT)
1006 event->button = DIBI_LEFT;
1007
1008 D_DEBUG_AT( Core_InputEvt, " -> lefty! => 0x%04x <=\n", event->button );
1009 }
1010 /* fallthru */
1011
1012 case DIET_AXISMOTION:
1013 fixup_mouse_event( device, event );
1014 break;
1015
1016 case DIET_KEYPRESS:
1017 case DIET_KEYRELEASE:
1018 if (dfb_config->capslock_meta) {
1019 if (device->shared->keymap.num_entries && (event->flags & DIEF_KEYCODE))
1020 lookup_from_table( device, event, (DIEF_KEYID |
1021 DIEF_KEYSYMBOL) & ~event->flags );
1022
1023 if (event->key_id == DIKI_CAPS_LOCK || event->key_symbol == DIKS_CAPS_LOCK) {
1024 event->flags |= DIEF_KEYID | DIEF_KEYSYMBOL;
1025 event->key_code = -1;
1026 event->key_id = DIKI_META_L;
1027 event->key_symbol = DIKS_META;
1028 }
1029 }
1030
1031 fixup_key_event( device, event );
1032 break;
1033
1034 default:
1035 ;
1036 }
1037
1038 #if D_DEBUG_ENABLED
1039 if (event->flags & DIEF_TIMESTAMP)
1040 D_DEBUG_AT( Core_InputEvt, " => TIMESTAMP %lu.%06lu\n", event->timestamp.tv_sec, event->timestamp.tv_usec );
1041 if (event->flags & DIEF_AXISABS)
1042 D_DEBUG_AT( Core_InputEvt, " => AXISABS %d at %d\n", event->axis, event->axisabs );
1043 if (event->flags & DIEF_AXISREL)
1044 D_DEBUG_AT( Core_InputEvt, " => AXISREL %d by %d\n", event->axis, event->axisrel );
1045 if (event->flags & DIEF_KEYCODE)
1046 D_DEBUG_AT( Core_InputEvt, " => KEYCODE %d\n", event->key_code );
1047 if (event->flags & DIEF_KEYID)
1048 D_DEBUG_AT( Core_InputEvt, " => KEYID 0x%04x\n", event->key_id );
1049 if (event->flags & DIEF_KEYSYMBOL)
1050 D_DEBUG_AT( Core_InputEvt, " => KEYSYMBOL 0x%04x\n", event->key_symbol );
1051 if (event->flags & DIEF_MODIFIERS)
1052 D_DEBUG_AT( Core_InputEvt, " => MODIFIERS 0x%04x\n", event->modifiers );
1053 if (event->flags & DIEF_LOCKS)
1054 D_DEBUG_AT( Core_InputEvt, " => LOCKS 0x%04x\n", event->locks );
1055 if (event->flags & DIEF_BUTTONS)
1056 D_DEBUG_AT( Core_InputEvt, " => BUTTONS 0x%04x\n", event->buttons );
1057 if (event->flags & DIEF_GLOBAL)
1058 D_DEBUG_AT( Core_InputEvt, " => GLOBAL\n" );
1059 #endif
1060
1061 if (core_input_filter( device, event ))
1062 D_DEBUG_AT( Core_InputEvt, " ****>> FILTERED\n" );
1063 else
1064 fusion_reactor_dispatch( device->shared->reactor, event, true, dfb_input_globals );
1065 }
1066
1067 DFBInputDeviceID
dfb_input_device_id(const CoreInputDevice * device)1068 dfb_input_device_id( const CoreInputDevice *device )
1069 {
1070 D_MAGIC_ASSERT( device, CoreInputDevice );
1071
1072 D_ASSERT( core_input != NULL );
1073 D_ASSERT( device != NULL );
1074 D_ASSERT( device->shared != NULL );
1075
1076 return device->shared->id;
1077 }
1078
1079 CoreInputDevice *
dfb_input_device_at(DFBInputDeviceID id)1080 dfb_input_device_at( DFBInputDeviceID id )
1081 {
1082 CoreInputDevice *device;
1083
1084 D_ASSERT( core_input != NULL );
1085
1086 direct_list_foreach (device, core_local->devices) {
1087 D_MAGIC_ASSERT( device, CoreInputDevice );
1088
1089 if (device->shared->id == id)
1090 return device;
1091 }
1092
1093 return NULL;
1094 }
1095
1096 /* Get an input device's capabilities. */
1097 DFBInputDeviceCapabilities
dfb_input_device_caps(const CoreInputDevice * device)1098 dfb_input_device_caps( const CoreInputDevice *device )
1099 {
1100 D_MAGIC_ASSERT( device, CoreInputDevice );
1101
1102 D_ASSERT( core_input != NULL );
1103 D_ASSERT( device != NULL );
1104 D_ASSERT( device->shared != NULL );
1105
1106 return device->shared->device_info.desc.caps;
1107 }
1108
1109 void
dfb_input_device_description(const CoreInputDevice * device,DFBInputDeviceDescription * desc)1110 dfb_input_device_description( const CoreInputDevice *device,
1111 DFBInputDeviceDescription *desc )
1112 {
1113 D_MAGIC_ASSERT( device, CoreInputDevice );
1114
1115 D_ASSERT( core_input != NULL );
1116 D_ASSERT( device != NULL );
1117 D_ASSERT( device->shared != NULL );
1118
1119 *desc = device->shared->device_info.desc;
1120 }
1121
1122 DFBResult
dfb_input_device_get_keymap_entry(CoreInputDevice * device,int keycode,DFBInputDeviceKeymapEntry * entry)1123 dfb_input_device_get_keymap_entry( CoreInputDevice *device,
1124 int keycode,
1125 DFBInputDeviceKeymapEntry *entry )
1126 {
1127 DFBInputDeviceKeymapEntry *keymap_entry;
1128
1129 D_MAGIC_ASSERT( device, CoreInputDevice );
1130
1131 D_ASSERT( core_input != NULL );
1132 D_ASSERT( device != NULL );
1133 D_ASSERT( entry != NULL );
1134
1135 keymap_entry = get_keymap_entry( device, keycode );
1136 if (!keymap_entry)
1137 return DFB_FAILURE;
1138
1139 *entry = *keymap_entry;
1140
1141 return DFB_OK;
1142 }
1143
1144 DFBResult
dfb_input_device_set_keymap_entry(CoreInputDevice * device,int keycode,const DFBInputDeviceKeymapEntry * entry)1145 dfb_input_device_set_keymap_entry( CoreInputDevice *device,
1146 int keycode,
1147 const DFBInputDeviceKeymapEntry *entry )
1148 {
1149 D_MAGIC_ASSERT( device, CoreInputDevice );
1150
1151 D_ASSERT( core_input != NULL );
1152 D_ASSERT( device != NULL );
1153 D_ASSERT( entry != NULL );
1154
1155 return set_keymap_entry( device, keycode, entry );
1156 }
1157
1158 DFBResult
dfb_input_device_load_keymap(CoreInputDevice * device,char * filename)1159 dfb_input_device_load_keymap ( CoreInputDevice *device,
1160 char *filename )
1161 {
1162 D_MAGIC_ASSERT( device, CoreInputDevice );
1163
1164 D_ASSERT( core_input != NULL );
1165 D_ASSERT( device != NULL );
1166 D_ASSERT( filename != NULL );
1167
1168 return load_keymap( device, filename );
1169 }
1170
1171 DFBResult
dfb_input_device_reload_keymap(CoreInputDevice * device)1172 dfb_input_device_reload_keymap( CoreInputDevice *device )
1173 {
1174 InputDeviceShared *shared;
1175
1176 D_MAGIC_ASSERT( device, CoreInputDevice );
1177
1178 shared = device->shared;
1179 D_ASSERT( shared != NULL );
1180
1181 D_INFO( "DirectFB/Input: Reloading keymap for '%s' [0x%02x]...\n",
1182 shared->device_info.desc.name, shared->id );
1183
1184 return reload_keymap( device );
1185 }
1186
1187 DFBResult
dfb_input_device_get_state(CoreInputDevice * device,CoreInputDeviceState * ret_state)1188 dfb_input_device_get_state( CoreInputDevice *device,
1189 CoreInputDeviceState *ret_state )
1190 {
1191 InputDeviceShared *shared;
1192
1193 D_MAGIC_ASSERT( device, CoreInputDevice );
1194
1195 shared = device->shared;
1196 D_ASSERT( shared != NULL );
1197
1198 *ret_state = shared->state;
1199
1200 return DFB_OK;
1201 }
1202
1203 /** internal **/
1204
1205 static void
input_add_device(CoreInputDevice * device)1206 input_add_device( CoreInputDevice *device )
1207 {
1208 D_DEBUG_AT( Core_Input, "%s( %p )\n", __FUNCTION__, device );
1209
1210 D_MAGIC_ASSERT( device, CoreInputDevice );
1211
1212 D_ASSERT( core_input != NULL );
1213 D_ASSERT( device != NULL );
1214 D_ASSERT( device->shared != NULL );
1215
1216 if (core_input->num == MAX_INPUTDEVICES) {
1217 D_ERROR( "DirectFB/Input: Maximum number of devices reached!\n" );
1218 return;
1219 }
1220
1221 direct_list_append( &core_local->devices, &device->link );
1222
1223 core_input->devices[ core_input->num++ ] = device->shared;
1224 }
1225
1226 static void
allocate_device_keymap(CoreDFB * core,CoreInputDevice * device)1227 allocate_device_keymap( CoreDFB *core, CoreInputDevice *device )
1228 {
1229 int i;
1230 DFBInputDeviceKeymapEntry *entries;
1231 FusionSHMPoolShared *pool = dfb_core_shmpool( core );
1232 InputDeviceShared *shared = device->shared;
1233 DFBInputDeviceDescription *desc = &shared->device_info.desc;
1234 int num_entries = desc->max_keycode -
1235 desc->min_keycode + 1;
1236
1237 D_DEBUG_AT( Core_Input, "%s( %p, %p )\n", __FUNCTION__, core, device );
1238
1239 D_MAGIC_ASSERT( device, CoreInputDevice );
1240
1241 D_ASSERT( core_input != NULL );
1242
1243 entries = SHCALLOC( pool, num_entries, sizeof(DFBInputDeviceKeymapEntry) );
1244 if (!entries) {
1245 D_OOSHM();
1246 return;
1247 }
1248
1249 /* write -1 indicating entry is not fetched yet from driver */
1250 for (i=0; i<num_entries; i++)
1251 entries[i].code = -1;
1252
1253 shared->keymap.min_keycode = desc->min_keycode;
1254 shared->keymap.max_keycode = desc->max_keycode;
1255 shared->keymap.num_entries = num_entries;
1256 shared->keymap.entries = entries;
1257
1258 #if FUSION_BUILD_MULTI
1259 /* we need to fetch the whole map, otherwise a slave would try to */
1260 for (i=desc->min_keycode; i<=desc->max_keycode; i++)
1261 get_keymap_entry( device, i );
1262 #endif
1263 }
1264
1265 static int
make_id(DFBInputDeviceID prefered)1266 make_id( DFBInputDeviceID prefered )
1267 {
1268 CoreInputDevice *device;
1269
1270 D_DEBUG_AT( Core_Input, "%s( 0x%02x )\n", __FUNCTION__, prefered );
1271
1272 D_ASSERT( core_input != NULL );
1273
1274 direct_list_foreach (device, core_local->devices) {
1275 D_MAGIC_ASSERT( device, CoreInputDevice );
1276
1277 if (device->shared->id == prefered)
1278 return make_id( (prefered < DIDID_ANY) ? DIDID_ANY : (prefered + 1) );
1279 }
1280
1281 return prefered;
1282 }
1283
1284 static DFBResult
reload_keymap(CoreInputDevice * device)1285 reload_keymap( CoreInputDevice *device )
1286 {
1287 int i;
1288 InputDeviceShared *shared;
1289
1290 D_DEBUG_AT( Core_Input, "%s( %p )\n", __FUNCTION__, device );
1291
1292 D_MAGIC_ASSERT( device, CoreInputDevice );
1293
1294 shared = device->shared;
1295
1296 D_ASSERT( shared != NULL );
1297
1298 if (shared->device_info.desc.min_keycode < 0 ||
1299 shared->device_info.desc.max_keycode < 0)
1300 return DFB_UNSUPPORTED;
1301
1302 /* write -1 indicating entry is not fetched yet from driver */
1303 for (i=0; i<shared->keymap.num_entries; i++)
1304 shared->keymap.entries[i].code = -1;
1305
1306 /* fetch the whole map */
1307 for (i=shared->keymap.min_keycode; i<=shared->keymap.max_keycode; i++)
1308 get_keymap_entry( device, i );
1309
1310 D_INFO( "DirectFB/Input: Reloaded keymap for '%s' [0x%02x]\n",
1311 shared->device_info.desc.name, shared->id );
1312
1313 return DFB_OK;
1314 }
1315
1316 static DFBResult
init_axes(CoreInputDevice * device)1317 init_axes( CoreInputDevice *device )
1318 {
1319 int i, num;
1320 DFBResult ret;
1321 InputDeviceShared *shared;
1322 const InputDriverFuncs *funcs;
1323
1324 D_DEBUG_AT( Core_Input, "%s( %p )\n", __FUNCTION__, device );
1325
1326 D_MAGIC_ASSERT( device, CoreInputDevice );
1327 D_ASSERT( device->driver != NULL );
1328
1329 funcs = device->driver->funcs;
1330 D_ASSERT( funcs != NULL );
1331
1332 shared = device->shared;
1333 D_ASSERT( shared != NULL );
1334
1335 if (shared->device_info.desc.max_axis < 0)
1336 return DFB_OK;
1337
1338 num = shared->device_info.desc.max_axis + 1;
1339
1340 shared->axis_info = SHCALLOC( dfb_core_shmpool(device->core), num, sizeof(DFBInputDeviceAxisInfo) );
1341 if (!shared->axis_info)
1342 return D_OOSHM();
1343
1344 shared->axis_num = num;
1345
1346 if (funcs->GetAxisInfo) {
1347 for (i=0; i<num; i++) {
1348 ret = funcs->GetAxisInfo( device, device->driver_data, i, &shared->axis_info[i] );
1349 if (ret)
1350 D_DERROR( ret, "Core/Input: GetAxisInfo() failed for '%s' [%d] on axis %d!\n",
1351 shared->device_info.desc.name, shared->id, i );
1352 }
1353 }
1354
1355 return DFB_OK;
1356 }
1357
1358 static void
init_devices(CoreDFB * core)1359 init_devices( CoreDFB *core )
1360 {
1361 DirectLink *next;
1362 DirectModuleEntry *module;
1363 FusionSHMPoolShared *pool = dfb_core_shmpool( core );
1364
1365 D_DEBUG_AT( Core_Input, "%s( %p )\n", __FUNCTION__, core );
1366
1367 D_ASSERT( core_input != NULL );
1368
1369 direct_list_foreach_safe (module, next, dfb_input_modules.entries) {
1370 int n;
1371 InputDriver *driver;
1372 const InputDriverFuncs *funcs;
1373 InputDriverCapability driver_cap;
1374 DFBResult result;
1375
1376 driver_cap = IDC_NONE;
1377
1378 funcs = direct_module_ref( module );
1379 if (!funcs)
1380 continue;
1381
1382 driver = D_CALLOC( 1, sizeof(InputDriver) );
1383 if (!driver) {
1384 D_OOM();
1385 direct_module_unref( module );
1386 continue;
1387 }
1388
1389 D_ASSERT( funcs->GetDriverInfo != NULL );
1390
1391 funcs->GetDriverInfo( &driver->info );
1392
1393 D_DEBUG_AT( Core_Input, " -> probing '%s'...\n", driver->info.name );
1394
1395 driver->nr_devices = funcs->GetAvailable();
1396
1397 /*
1398 * If the input provider supports hot-plug, always load the module.
1399 */
1400 if (!funcs->GetCapability) {
1401 D_DEBUG_AT(Core_Input, "InputDriverFuncs::GetCapability is NULL\n");
1402 }
1403 else {
1404 driver_cap = funcs->GetCapability();
1405 }
1406
1407 if (!driver->nr_devices && !(driver_cap & IDC_HOTPLUG)) {
1408 direct_module_unref( module );
1409 D_FREE( driver );
1410 continue;
1411 }
1412
1413 D_DEBUG_AT( Core_Input, " -> %d available device(s) provided by '%s'.\n",
1414 driver->nr_devices, driver->info.name );
1415
1416 driver->module = module;
1417 driver->funcs = funcs;
1418
1419 direct_list_prepend( &core_local->drivers, &driver->link );
1420
1421
1422 for (n=0; n<driver->nr_devices; n++) {
1423 char buf[128];
1424 CoreInputDevice *device;
1425 InputDeviceInfo device_info;
1426 InputDeviceShared *shared;
1427 void *driver_data;
1428
1429 device = D_CALLOC( 1, sizeof(CoreInputDevice) );
1430 if (!device) {
1431 D_OOM();
1432 continue;
1433 }
1434
1435 shared = SHCALLOC( pool, 1, sizeof(InputDeviceShared) );
1436 if (!shared) {
1437 D_OOSHM();
1438 D_FREE( device );
1439 continue;
1440 }
1441
1442 device->core = core;
1443
1444 memset( &device_info, 0, sizeof(InputDeviceInfo) );
1445
1446 device_info.desc.min_keycode = -1;
1447 device_info.desc.max_keycode = -1;
1448
1449 D_MAGIC_SET( device, CoreInputDevice );
1450
1451 if (funcs->OpenDevice( device, n, &device_info, &driver_data )) {
1452 SHFREE( pool, shared );
1453 D_MAGIC_CLEAR( device );
1454 D_FREE( device );
1455 continue;
1456 }
1457
1458 D_DEBUG_AT( Core_Input, " -> opened '%s' (%d) %d.%d (%s)\n",
1459 device_info.desc.name, n + 1, driver->info.version.major,
1460 driver->info.version.minor, driver->info.vendor );
1461
1462 if (driver->nr_devices > 1)
1463 snprintf( buf, sizeof(buf), "%s (%d)", device_info.desc.name, n+1 );
1464 else
1465 snprintf( buf, sizeof(buf), "%s", device_info.desc.name );
1466
1467 /* init skirmish */
1468 fusion_skirmish_init( &shared->lock, buf, dfb_core_world(core) );
1469
1470 /* create reactor */
1471 shared->reactor = fusion_reactor_new( sizeof(DFBInputEvent), buf, dfb_core_world(core) );
1472
1473 fusion_reactor_add_permissions( shared->reactor, 0, FUSION_REACTOR_PERMIT_ATTACH_DETACH );
1474
1475 fusion_reactor_set_lock( shared->reactor, &shared->lock );
1476
1477 /* init call */
1478 CoreInputDevice_Init_Dispatch( core, device, &shared->call );
1479
1480 /* initialize shared data */
1481 shared->id = make_id(device_info.prefered_id);
1482 shared->num = n;
1483 shared->device_info = device_info;
1484 shared->last_key = DIKI_UNKNOWN;
1485 shared->first_press = true;
1486
1487 /* initialize local data */
1488 device->shared = shared;
1489 device->driver = driver;
1490 device->driver_data = driver_data;
1491
1492 D_INFO( "DirectFB/Input: %s %d.%d (%s)\n",
1493 buf, driver->info.version.major,
1494 driver->info.version.minor, driver->info.vendor );
1495
1496 #if FUSION_BUILD_MULTI
1497 /* Initialize the ref between shared device and local device. */
1498 snprintf( buf, sizeof(buf), "Ref of input device(%d)", shared->id );
1499 fusion_ref_init( &shared->ref, buf, dfb_core_world(core) );
1500
1501 fusion_ref_add_permissions( &shared->ref, 0, FUSION_REF_PERMIT_REF_UNREF_LOCAL );
1502
1503 /* Increase reference counter. */
1504 fusion_ref_up( &shared->ref, false );
1505 #endif
1506
1507 if (device_info.desc.min_keycode > device_info.desc.max_keycode) {
1508 D_BUG("min_keycode > max_keycode");
1509 device_info.desc.min_keycode = -1;
1510 device_info.desc.max_keycode = -1;
1511 }
1512 else if (device_info.desc.min_keycode >= 0 &&
1513 device_info.desc.max_keycode >= 0)
1514 allocate_device_keymap( core, device );
1515
1516 init_axes( device );
1517
1518 /* add it to the list */
1519 input_add_device( device );
1520 }
1521
1522 /*
1523 * If the driver supports hot-plug, launch its hot-plug thread to respond to
1524 * hot-plug events. Failures in launching the hot-plug thread will only
1525 * result in no hot-plug feature being available.
1526 */
1527 if (driver_cap == IDC_HOTPLUG) {
1528 result = funcs->LaunchHotplug(core, (void*) driver);
1529
1530 /* On failure, the input provider can still be used without hot-plug. */
1531 if (result) {
1532 D_INFO( "DirectFB/Input: Failed to enable hot-plug "
1533 "detection with %s\n ", driver->info.name);
1534 }
1535 else {
1536 D_INFO( "DirectFB/Input: Hot-plug detection enabled with %s \n",
1537 driver->info.name);
1538 }
1539 }
1540 }
1541 }
1542
1543 /*
1544 * Create the DFB shared core input device, add the input device into the
1545 * local device list and shared dev array and broadcast the hot-plug in
1546 * message to all slaves.
1547 */
1548 DFBResult
dfb_input_create_device(int device_index,CoreDFB * core_in,void * driver_in)1549 dfb_input_create_device(int device_index, CoreDFB *core_in, void *driver_in)
1550 {
1551 char buf[128];
1552 CoreInputDevice *device;
1553 InputDeviceInfo device_info;
1554 InputDeviceShared *shared;
1555 void *driver_data;
1556 InputDriver *driver = NULL;
1557 const InputDriverFuncs *funcs;
1558 FusionSHMPoolShared *pool;
1559 DFBResult result;
1560
1561 D_DEBUG_AT(Core_Input, "Enter: %s()\n", __FUNCTION__);
1562
1563 driver = (InputDriver *)driver_in;
1564
1565 pool = dfb_core_shmpool(core_in);
1566 funcs = driver->funcs;
1567 if (!funcs) {
1568 D_ERROR("DirectFB/Input: driver->funcs is NULL\n");
1569 goto errorExit;
1570 }
1571
1572 device = D_CALLOC( 1, sizeof(CoreInputDevice) );
1573 if (!device) {
1574 D_OOM();
1575 goto errorExit;
1576 }
1577 shared = SHCALLOC( pool, 1, sizeof(InputDeviceShared) );
1578 if (!shared) {
1579 D_OOM();
1580 D_FREE( device );
1581 goto errorExit;
1582 }
1583
1584 device->core = core_in;
1585
1586 memset( &device_info, 0, sizeof(InputDeviceInfo) );
1587
1588 device_info.desc.min_keycode = -1;
1589 device_info.desc.max_keycode = -1;
1590
1591 D_MAGIC_SET( device, CoreInputDevice );
1592
1593 if (funcs->OpenDevice( device, device_index, &device_info, &driver_data )) {
1594 SHFREE( pool, shared );
1595 D_MAGIC_CLEAR( device );
1596 D_FREE( device );
1597 D_DEBUG_AT( Core_Input,
1598 "DirectFB/Input: Cannot open device in %s, at %d in %s\n",
1599 __FUNCTION__, __LINE__, __FILE__);
1600 goto errorExit;
1601 }
1602
1603 snprintf( buf, sizeof(buf), "%s (%d)", device_info.desc.name, device_index);
1604
1605 /* init skirmish */
1606 result = fusion_skirmish_init( &shared->lock, buf, dfb_core_world(device->core) );
1607 if (result) {
1608 funcs->CloseDevice( driver_data );
1609 SHFREE( pool, shared );
1610 D_MAGIC_CLEAR( device );
1611 D_FREE( device );
1612 D_ERROR("DirectFB/Input: fusion_skirmish_init() failed! in %s, at %d in %s\n",
1613 __FUNCTION__, __LINE__, __FILE__);
1614 goto errorExit;
1615 }
1616
1617 /* create reactor */
1618 shared->reactor = fusion_reactor_new( sizeof(DFBInputEvent),
1619 buf,
1620 dfb_core_world(device->core) );
1621 if (!shared->reactor) {
1622 funcs->CloseDevice( driver_data );
1623 SHFREE( pool, shared );
1624 D_MAGIC_CLEAR( device );
1625 D_FREE( device );
1626 fusion_skirmish_destroy(&shared->lock);
1627 D_ERROR("DirectFB/Input: fusion_reactor_new() failed! in %s, at %d in %s\n",
1628 __FUNCTION__, __LINE__, __FILE__);
1629 goto errorExit;
1630 }
1631
1632 fusion_reactor_add_permissions( shared->reactor, 0, FUSION_REACTOR_PERMIT_ATTACH_DETACH );
1633
1634 fusion_reactor_set_lock( shared->reactor, &shared->lock );
1635
1636 /* init call */
1637 CoreInputDevice_Init_Dispatch( device->core, device, &shared->call );
1638
1639 /* initialize shared data */
1640 shared->id = make_id(device_info.prefered_id);
1641 shared->num = device_index;
1642 shared->device_info = device_info;
1643 shared->last_key = DIKI_UNKNOWN;
1644 shared->first_press = true;
1645
1646 /* initialize local data */
1647 device->shared = shared;
1648 device->driver = driver;
1649 device->driver_data = driver_data;
1650
1651 D_INFO( "DirectFB/Input: %s %d.%d (%s)\n",
1652 buf, driver->info.version.major,
1653 driver->info.version.minor, driver->info.vendor );
1654
1655 #if FUSION_BUILD_MULTI
1656 snprintf( buf, sizeof(buf), "Ref of input device(%d)", shared->id);
1657 fusion_ref_init( &shared->ref, buf, dfb_core_world(core_in));
1658 fusion_ref_add_permissions( &shared->ref, 0, FUSION_REF_PERMIT_REF_UNREF_LOCAL );
1659 fusion_ref_up( &shared->ref, false );
1660 #endif
1661
1662 if (device_info.desc.min_keycode > device_info.desc.max_keycode) {
1663 D_BUG("min_keycode > max_keycode");
1664 device_info.desc.min_keycode = -1;
1665 device_info.desc.max_keycode = -1;
1666 }
1667 else if (device_info.desc.min_keycode >= 0 && device_info.desc.max_keycode >= 0)
1668 allocate_device_keymap( device->core, device );
1669
1670 /* add it into local device list and shared dev array */
1671 D_DEBUG_AT(Core_Input,
1672 "In master, add a new device with dev_id=%d\n",
1673 shared->id);
1674
1675 input_add_device( device );
1676 driver->nr_devices++;
1677
1678 D_DEBUG_AT(Core_Input,
1679 "Successfully added new input device with dev_id=%d in shared array\n",
1680 shared->id);
1681
1682 InputDeviceHotplugEvent message;
1683
1684 /* Setup the hot-plug in message. */
1685 message.is_plugin = true;
1686 message.dev_id = shared->id;
1687 gettimeofday (&message.stamp, NULL);
1688
1689 /* Send the hot-plug in message */
1690 #if FUSION_BUILD_MULTI
1691 fusion_reactor_dispatch(core_input->reactor, &message, true, NULL);
1692 #else
1693 local_processing_hotplug((const void *) &message, (void*) core_in);
1694 #endif
1695 return DFB_OK;
1696
1697 errorExit:
1698 return DFB_FAILURE;
1699 }
1700
1701 /*
1702 * Tell whether the DFB input device handling of the system input device
1703 * indicated by device_index is already created.
1704 */
1705 static CoreInputDevice *
search_device_created(int device_index,void * driver_in)1706 search_device_created(int device_index, void *driver_in)
1707 {
1708 DirectLink *n;
1709 CoreInputDevice *device;
1710
1711 D_ASSERT(driver_in != NULL);
1712
1713 direct_list_foreach_safe(device, n, core_local->devices) {
1714 if (device->driver != driver_in)
1715 continue;
1716
1717 if (device->driver_data == NULL) {
1718 D_DEBUG_AT(Core_Input,
1719 "The device %d has been closed!\n",
1720 device->shared->id);
1721 return NULL;
1722 }
1723
1724 if (device->driver->funcs->IsCreated &&
1725 !device->driver->funcs->IsCreated(device_index, device->driver_data)) {
1726 return device;
1727 }
1728 }
1729
1730 return NULL;
1731 }
1732
1733 /*
1734 * Remove the DFB shared core input device handling of the system input device
1735 * indicated by device_index and broadcast the hot-plug out message to all slaves.
1736 */
1737 DFBResult
dfb_input_remove_device(int device_index,void * driver_in)1738 dfb_input_remove_device(int device_index, void *driver_in)
1739 {
1740 CoreInputDevice *device;
1741 InputDeviceShared *shared;
1742 FusionSHMPoolShared *pool;
1743 int i;
1744 int found = 0;
1745 int device_id;
1746
1747 D_DEBUG_AT(Core_Input, "Enter: %s()\n", __FUNCTION__);
1748
1749 D_ASSERT(driver_in !=NULL);
1750
1751 device = search_device_created(device_index, driver_in);
1752 if (device == NULL) {
1753 D_DEBUG_AT(Core_Input,
1754 "DirectFB/input: Failed to find the device[%d] or the device is "
1755 "closed.\n",
1756 device_index);
1757 goto errorExit;
1758 }
1759
1760 shared = device->shared;
1761 pool = dfb_core_shmpool( device->core );
1762 device_id = shared->id;
1763
1764 D_DEBUG_AT(Core_Input, "Find the device with dev_id=%d\n", device_id);
1765
1766 device->driver->funcs->CloseDevice( device->driver_data );
1767
1768 device->driver->nr_devices--;
1769
1770 InputDeviceHotplugEvent message;
1771
1772 /* Setup the hot-plug out message */
1773 message.is_plugin = false;
1774 message.dev_id = device_id;
1775 gettimeofday (&message.stamp, NULL);
1776
1777 /* Send the hot-plug out message */
1778 #if FUSION_BUILD_MULTI
1779 fusion_reactor_dispatch( core_input->reactor, &message, true, NULL);
1780
1781 int loop = CHECK_NUMBER;
1782
1783 while (--loop) {
1784 if (fusion_ref_zero_trylock( &device->shared->ref ) == DR_OK) {
1785 fusion_ref_unlock(&device->shared->ref);
1786 break;
1787 }
1788
1789 usleep(CHECK_INTERVAL);
1790 }
1791
1792 if (!loop)
1793 D_DEBUG_AT(Core_Input, "Shared device might be connected to by others\n");
1794
1795 fusion_ref_destroy(&device->shared->ref);
1796 #else
1797 local_processing_hotplug((const void*) &message, (void*) device->core);
1798 #endif
1799
1800 /* Remove the device from shared array */
1801 for (i = 0; i < core_input->num; i++) {
1802 if (!found && (core_input->devices[i]->id == shared->id))
1803 found = 1;
1804
1805 if (found)
1806 core_input->devices[i] = core_input->devices[(i + 1) % MAX_INPUTDEVICES];
1807 }
1808 if (found)
1809 core_input->devices[core_input->num -1] = NULL;
1810
1811 core_input->num--;
1812
1813 CoreInputDevice_Deinit_Dispatch( &shared->call );
1814
1815 fusion_skirmish_destroy( &shared->lock );
1816
1817 fusion_reactor_free( shared->reactor );
1818
1819 if (shared->keymap.entries)
1820 SHFREE( pool, shared->keymap.entries );
1821
1822 SHFREE( pool, shared );
1823
1824 D_DEBUG_AT(Core_Input,
1825 "Successfully remove the device with dev_id=%d in shared array\n",
1826 device_id);
1827
1828 return DFB_OK;
1829
1830 errorExit:
1831 return DFB_FAILURE;
1832 }
1833
1834 /*
1835 * Create local input device and add it into the local input devices list.
1836 */
1837 static CoreInputDevice *
add_device_into_local_list(int dev_id)1838 add_device_into_local_list(int dev_id)
1839 {
1840 int i;
1841 D_DEBUG_AT(Core_Input, "Enter: %s()\n", __FUNCTION__);
1842 for (i = 0; i < core_input->num; i++) {
1843 if (core_input->devices[i]->id == dev_id) {
1844 CoreInputDevice *device;
1845
1846 D_DEBUG_AT(Core_Input,
1847 "Find the device with dev_id=%d in shared array, and "
1848 "allocate local device\n",
1849 dev_id);
1850
1851 device = D_CALLOC( 1, sizeof(CoreInputDevice) );
1852 if (!device) {
1853 return NULL;
1854 }
1855
1856 device->shared = core_input->devices[i];
1857
1858 #if FUSION_BUILD_MULTI
1859 /* Increase the reference counter. */
1860 fusion_ref_up( &device->shared->ref, false );
1861 #endif
1862
1863 /* add it to the list */
1864 direct_list_append( &core_local->devices, &device->link );
1865
1866 D_MAGIC_SET( device, CoreInputDevice );
1867 return device;
1868 }
1869 }
1870
1871 return NULL;
1872 }
1873
1874 /*
1875 * Local input device function that handles hot-plug in/out messages.
1876 */
1877 static ReactionResult
local_processing_hotplug(const void * msg_data,void * ctx)1878 local_processing_hotplug( const void *msg_data, void *ctx )
1879 {
1880 const InputDeviceHotplugEvent *message = msg_data;
1881 CoreInputDevice *device = NULL;
1882
1883 D_DEBUG_AT(Core_Input, "Enter: %s()\n", __FUNCTION__);
1884
1885 D_DEBUG_AT(Core_Input,
1886 "<PID:%6d> hotplug-in:%d device_id=%d message!\n",
1887 getpid(),
1888 message->is_plugin,
1889 message->dev_id );
1890
1891 if (message->is_plugin) {
1892
1893 device = dfb_input_device_at(message->dev_id);
1894
1895 if (!device){
1896 /* Update local device list according to shared devices array */
1897 if (!(device = add_device_into_local_list(message->dev_id))) {
1898 D_ERROR("DirectFB/Input: update_local_devices_list() failed\n" );
1899 goto errorExit;
1900 }
1901 }
1902
1903 /* attach the device to event containers */
1904 containers_attach_device( device );
1905 /* attach the device to stack containers */
1906 stack_containers_attach_device( device );
1907 }
1908 else {
1909 device = dfb_input_device_at(message->dev_id);
1910 if (device) {
1911
1912 direct_list_remove(&core_local->devices, &device->link);
1913
1914 containers_detach_device(device);
1915 stack_containers_detach_device(device);
1916
1917 #if FUSION_BUILD_MULTI
1918 /* Decrease reference counter. */
1919 fusion_ref_down( &device->shared->ref, false );
1920 #endif
1921 D_MAGIC_CLEAR( device );
1922 D_FREE(device);
1923 }
1924 else
1925 D_ERROR("DirectFB/Input:Can't find the device to be removed!\n");
1926
1927 }
1928
1929 return DFB_OK;
1930
1931 errorExit:
1932 return DFB_FAILURE;
1933 }
1934
1935 static DFBInputDeviceKeymapEntry *
get_keymap_entry(CoreInputDevice * device,int code)1936 get_keymap_entry( CoreInputDevice *device,
1937 int code )
1938 {
1939 InputDeviceKeymap *map;
1940 DFBInputDeviceKeymapEntry *entry;
1941
1942 D_MAGIC_ASSERT( device, CoreInputDevice );
1943
1944 D_ASSERT( core_input != NULL );
1945 D_ASSERT( device != NULL );
1946 D_ASSERT( device->shared != NULL );
1947
1948 map = &device->shared->keymap;
1949
1950 /* safety check */
1951 if (code < map->min_keycode || code > map->max_keycode)
1952 return NULL;
1953
1954 /* point to right array index */
1955 entry = &map->entries[code - map->min_keycode];
1956
1957 /* need to initialize? */
1958 if (entry->code != code) {
1959 DFBResult ret;
1960 InputDriver *driver = device->driver;
1961
1962 if (!driver) {
1963 D_BUG("seem to be a slave with an empty keymap");
1964 return NULL;
1965 }
1966
1967 /* write keycode to entry */
1968 entry->code = code;
1969
1970 /* fetch entry from driver */
1971 ret = driver->funcs->GetKeymapEntry( device,
1972 device->driver_data, entry );
1973 if (ret)
1974 return NULL;
1975
1976 /* drivers may leave this blank */
1977 if (entry->identifier == DIKI_UNKNOWN)
1978 entry->identifier = symbol_to_id( entry->symbols[DIKSI_BASE] );
1979
1980 if (entry->symbols[DIKSI_BASE_SHIFT] == DIKS_NULL)
1981 entry->symbols[DIKSI_BASE_SHIFT] = entry->symbols[DIKSI_BASE];
1982
1983 if (entry->symbols[DIKSI_ALT] == DIKS_NULL)
1984 entry->symbols[DIKSI_ALT] = entry->symbols[DIKSI_BASE];
1985
1986 if (entry->symbols[DIKSI_ALT_SHIFT] == DIKS_NULL)
1987 entry->symbols[DIKSI_ALT_SHIFT] = entry->symbols[DIKSI_ALT];
1988 }
1989
1990 return entry;
1991 }
1992
1993 /* replace a single keymap entry with the code-entry pair */
1994 static DFBResult
set_keymap_entry(CoreInputDevice * device,int code,const DFBInputDeviceKeymapEntry * entry)1995 set_keymap_entry( CoreInputDevice *device,
1996 int code,
1997 const DFBInputDeviceKeymapEntry *entry )
1998 {
1999 InputDeviceKeymap *map;
2000
2001 D_ASSERT( device->shared != NULL );
2002 D_ASSERT( device->shared->keymap.entries != NULL );
2003
2004 map = &device->shared->keymap;
2005
2006 /* sanity check */
2007 if (code < map->min_keycode || code > map->max_keycode)
2008 return DFB_FAILURE;
2009
2010 /* copy the entry to the map */
2011 map->entries[code - map->min_keycode] = *entry;
2012
2013 return DFB_OK;
2014 }
2015
2016 /* replace the complete current keymap with a keymap from a file.
2017 * the minimum-maximum keycodes of the driver are to be respected.
2018 */
2019 static DFBResult
load_keymap(CoreInputDevice * device,char * filename)2020 load_keymap( CoreInputDevice *device,
2021 char *filename )
2022 {
2023 DFBResult ret = DFB_OK;
2024 InputDeviceKeymap *map = 0;
2025 FILE *file = 0;
2026 DFBInputDeviceLockState lockstate = 0;
2027
2028 D_ASSERT( device->shared != NULL );
2029 D_ASSERT( device->shared->keymap.entries != NULL );
2030
2031 map = &device->shared->keymap;
2032
2033 /* open the file */
2034 file = fopen( filename, "r" );
2035 if( !file )
2036 {
2037 return errno2result( errno );
2038 }
2039
2040 /* read the file, line by line, and consume the mentioned scancodes */
2041 while(1)
2042 {
2043 int i;
2044 int dummy;
2045 char buffer[201];
2046 int keycode;
2047 char diki[201];
2048 char diks[4][201];
2049 char *b;
2050
2051 DFBInputDeviceKeymapEntry entry = { .code = 0 };
2052
2053 b = fgets( buffer, 200, file );
2054 if( !b ) {
2055 if( feof(file) ) {
2056 fclose(file);
2057 return DFB_OK;
2058 }
2059 fclose(file);
2060 return errno2result(errno);
2061 }
2062
2063 /* comment or empty line */
2064 if( buffer[0]=='#' || strcmp(buffer,"\n")==0 )
2065 continue;
2066
2067 /* check for lock state change */
2068 if( !strncmp(buffer,"capslock:",9) ) { lockstate |= DILS_CAPS; continue; }
2069 if( !strncmp(buffer,":capslock",9) ) { lockstate &= ~DILS_CAPS; continue; }
2070 if( !strncmp(buffer,"numlock:",8) ) { lockstate |= DILS_NUM; continue; }
2071 if( !strncmp(buffer,":numlock",8) ) { lockstate &= ~DILS_NUM; continue; }
2072
2073 i = sscanf( buffer, " keycode %i = %s = %s %s %s %s %i\n",
2074 &keycode, diki, diks[0], diks[1], diks[2], diks[3], &dummy );
2075
2076 if( i < 3 || i > 6 ) {
2077 /* we want 1 to 4 key symbols */
2078 D_INFO( "DirectFB/Input: skipped erroneous input line %s\n", buffer );
2079 continue;
2080 }
2081
2082 if( keycode > map->max_keycode || keycode < map->min_keycode ) {
2083 D_INFO( "DirectFB/Input: skipped keycode %d out of range\n", keycode );
2084 continue;
2085 }
2086
2087 entry.code = keycode;
2088 entry.locks = lockstate;
2089 entry.identifier = lookup_keyidentifier( diki );
2090
2091 switch( i ) {
2092 case 6: entry.symbols[3] = lookup_keysymbol( diks[3] );
2093 case 5: entry.symbols[2] = lookup_keysymbol( diks[2] );
2094 case 4: entry.symbols[1] = lookup_keysymbol( diks[1] );
2095 case 3: entry.symbols[0] = lookup_keysymbol( diks[0] );
2096
2097 /* fall through */
2098 }
2099
2100 switch( i ) {
2101 case 3: entry.symbols[1] = entry.symbols[0];
2102 case 4: entry.symbols[2] = entry.symbols[0];
2103 case 5: entry.symbols[3] = entry.symbols[1];
2104
2105 /* fall through */
2106 }
2107
2108 ret = CoreInputDevice_SetKeymapEntry( device, keycode, &entry );
2109 if( ret )
2110 return ret;
2111 }
2112 }
2113
lookup_keysymbol(char * symbolname)2114 static DFBInputDeviceKeySymbol lookup_keysymbol( char *symbolname )
2115 {
2116 int i;
2117
2118 /* we want uppercase */
2119 for( i=0; i<strlen(symbolname); i++ )
2120 if( symbolname[i] >= 'a' && symbolname[i] <= 'z' )
2121 symbolname[i] = symbolname[i] - 'a' + 'A';
2122
2123 for( i=0; i < sizeof (KeySymbolNames) / sizeof (KeySymbolNames[0]); i++ ) {
2124 if( strcmp( symbolname, KeySymbolNames[i].name ) == 0 )
2125 return KeySymbolNames[i].symbol;
2126 }
2127
2128 /* not found, maybe starting with 0x for raw conversion.
2129 * We are already at uppercase.
2130 */
2131 if( symbolname[0]=='0' && symbolname[1]=='X' ) {
2132 int code=0;
2133 symbolname+=2;
2134 while(*symbolname) {
2135 if( *symbolname >= '0' && *symbolname <= '9' ) {
2136 code = code*16 + *symbolname - '0';
2137 } else if( *symbolname >= 'A' && *symbolname <= 'F' ) {
2138 code = code*16 + *symbolname - 'A' + 10;
2139 } else {
2140 /* invalid character */
2141 return DIKS_NULL;
2142 }
2143 symbolname++;
2144 }
2145 return code;
2146 }
2147
2148 return DIKS_NULL;
2149 }
2150
lookup_keyidentifier(char * identifiername)2151 static DFBInputDeviceKeyIdentifier lookup_keyidentifier( char *identifiername )
2152 {
2153 int i;
2154
2155 /* we want uppercase */
2156 for( i=0; i<strlen(identifiername); i++ )
2157 if( identifiername[i] >= 'a' && identifiername[i] <= 'z' )
2158 identifiername[i] = identifiername[i] - 'a' + 'A';
2159
2160 for( i=0; i < sizeof (KeyIdentifierNames) / sizeof (KeyIdentifierNames[0]); i++ ) {
2161 if( strcmp( identifiername, KeyIdentifierNames[i].name ) == 0 )
2162 return KeyIdentifierNames[i].identifier;
2163 }
2164
2165 return DIKI_UNKNOWN;
2166 }
2167
2168 static bool
lookup_from_table(CoreInputDevice * device,DFBInputEvent * event,DFBInputEventFlags lookup)2169 lookup_from_table( CoreInputDevice *device,
2170 DFBInputEvent *event,
2171 DFBInputEventFlags lookup )
2172 {
2173 DFBInputDeviceKeymapEntry *entry;
2174
2175 D_MAGIC_ASSERT( device, CoreInputDevice );
2176
2177 D_ASSERT( core_input != NULL );
2178 D_ASSERT( device != NULL );
2179 D_ASSERT( device->shared != NULL );
2180 D_ASSERT( event != NULL );
2181
2182 /* fetch the entry from the keymap, possibly calling the driver */
2183 entry = get_keymap_entry( device, event->key_code );
2184 if (!entry)
2185 return false;
2186
2187 /* lookup identifier */
2188 if (lookup & DIEF_KEYID)
2189 event->key_id = entry->identifier;
2190
2191 /* lookup symbol */
2192 if (lookup & DIEF_KEYSYMBOL) {
2193 DFBInputDeviceKeymapSymbolIndex index =
2194 (event->modifiers & DIMM_ALTGR) ? DIKSI_ALT : DIKSI_BASE;
2195
2196 if ((event->modifiers & DIMM_SHIFT) || (entry->locks & event->locks))
2197 index++;
2198
2199 /* don't modify modifiers */
2200 if (DFB_KEY_TYPE( entry->symbols[DIKSI_BASE] ) == DIKT_MODIFIER)
2201 event->key_symbol = entry->symbols[DIKSI_BASE];
2202 else
2203 event->key_symbol = entry->symbols[index];
2204 }
2205
2206 return true;
2207 }
2208
2209 static int
find_key_code_by_id(CoreInputDevice * device,DFBInputDeviceKeyIdentifier id)2210 find_key_code_by_id( CoreInputDevice *device,
2211 DFBInputDeviceKeyIdentifier id )
2212 {
2213 int i;
2214 InputDeviceKeymap *map;
2215
2216 D_MAGIC_ASSERT( device, CoreInputDevice );
2217
2218 D_ASSERT( core_input != NULL );
2219 D_ASSERT( device != NULL );
2220 D_ASSERT( device->shared != NULL );
2221
2222 map = &device->shared->keymap;
2223
2224 for (i=0; i<map->num_entries; i++) {
2225 DFBInputDeviceKeymapEntry *entry = &map->entries[i];
2226
2227 if (entry->identifier == id)
2228 return entry->code;
2229 }
2230
2231 return -1;
2232 }
2233
2234 static int
find_key_code_by_symbol(CoreInputDevice * device,DFBInputDeviceKeySymbol symbol)2235 find_key_code_by_symbol( CoreInputDevice *device,
2236 DFBInputDeviceKeySymbol symbol )
2237 {
2238 int i;
2239 InputDeviceKeymap *map;
2240
2241 D_MAGIC_ASSERT( device, CoreInputDevice );
2242
2243 D_ASSERT( core_input != NULL );
2244 D_ASSERT( device != NULL );
2245 D_ASSERT( device->shared != NULL );
2246
2247 map = &device->shared->keymap;
2248
2249 for (i=0; i<map->num_entries; i++) {
2250 int n;
2251 DFBInputDeviceKeymapEntry *entry = &map->entries[i];
2252
2253 for (n=0; n<=DIKSI_LAST; n++)
2254 if (entry->symbols[n] == symbol)
2255 return entry->code;
2256 }
2257
2258 return -1;
2259 }
2260
2261 #define FIXUP_KEY_FIELDS (DIEF_MODIFIERS | DIEF_LOCKS | \
2262 DIEF_KEYCODE | DIEF_KEYID | DIEF_KEYSYMBOL)
2263
2264 /*
2265 * Fill partially missing values for key_code, key_id and key_symbol by
2266 * translating those that are set. Fix modifiers/locks before if not set.
2267 *
2268 *
2269 * There are five valid constellations that give reasonable values.
2270 * (not counting the constellation where everything is set)
2271 *
2272 * Device has no translation table
2273 * 1. key_id is set, key_symbol not
2274 * -> key_code defaults to -1, key_symbol from key_id (up-translation)
2275 * 2. key_symbol is set, key_id not
2276 * -> key_code defaults to -1, key_id from key_symbol (down-translation)
2277 *
2278 * Device has a translation table
2279 * 3. key_code is set
2280 * -> look up key_id and/or key_symbol (key_code being the index)
2281 * 4. key_id is set
2282 * -> look up key_code and possibly key_symbol (key_id being searched for)
2283 * 5. key_symbol is set
2284 * -> look up key_code and key_id (key_symbol being searched for)
2285 *
2286 * Fields remaining will be set to the default, e.g. key_code to -1.
2287 */
2288 static void
fixup_key_event(CoreInputDevice * device,DFBInputEvent * event)2289 fixup_key_event( CoreInputDevice *device, DFBInputEvent *event )
2290 {
2291 int i;
2292 DFBInputEventFlags valid = event->flags & FIXUP_KEY_FIELDS;
2293 DFBInputEventFlags missing = valid ^ FIXUP_KEY_FIELDS;
2294 InputDeviceShared *shared = device->shared;
2295
2296 D_MAGIC_ASSERT( device, CoreInputDevice );
2297
2298 /* Add missing flags */
2299 event->flags |= missing;
2300
2301 /*
2302 * Use cached values for modifiers/locks if they are missing.
2303 */
2304 if (missing & DIEF_MODIFIERS)
2305 event->modifiers = shared->state.modifiers_l | shared->state.modifiers_r;
2306
2307 if (missing & DIEF_LOCKS)
2308 event->locks = shared->state.locks;
2309
2310 /*
2311 * With translation table
2312 */
2313 if (device->shared->keymap.num_entries) {
2314 if (valid & DIEF_KEYCODE) {
2315 lookup_from_table( device, event, missing );
2316
2317 missing &= ~(DIEF_KEYID | DIEF_KEYSYMBOL);
2318 }
2319 else if (valid & DIEF_KEYID) {
2320 event->key_code = find_key_code_by_id( device, event->key_id );
2321
2322 if (event->key_code != -1) {
2323 lookup_from_table( device, event, missing );
2324
2325 missing &= ~(DIEF_KEYCODE | DIEF_KEYSYMBOL);
2326 }
2327 else if (missing & DIEF_KEYSYMBOL) {
2328 event->key_symbol = id_to_symbol( event->key_id,
2329 event->modifiers,
2330 event->locks );
2331 missing &= ~DIEF_KEYSYMBOL;
2332 }
2333 }
2334 else if (valid & DIEF_KEYSYMBOL) {
2335 event->key_code = find_key_code_by_symbol( device,
2336 event->key_symbol );
2337
2338 if (event->key_code != -1) {
2339 lookup_from_table( device, event, missing );
2340
2341 missing &= ~(DIEF_KEYCODE | DIEF_KEYID);
2342 }
2343 else {
2344 event->key_id = symbol_to_id( event->key_symbol );
2345 missing &= ~DIEF_KEYSYMBOL;
2346 }
2347 }
2348 }
2349 else {
2350 /*
2351 * Without translation table
2352 */
2353 if (valid & DIEF_KEYID) {
2354 if (missing & DIEF_KEYSYMBOL) {
2355 event->key_symbol = id_to_symbol( event->key_id,
2356 event->modifiers,
2357 event->locks );
2358 missing &= ~DIEF_KEYSYMBOL;
2359 }
2360 }
2361 else if (valid & DIEF_KEYSYMBOL) {
2362 event->key_id = symbol_to_id( event->key_symbol );
2363 missing &= ~DIEF_KEYID;
2364 }
2365 }
2366
2367 /*
2368 * Clear remaining fields.
2369 */
2370 if (missing & DIEF_KEYCODE)
2371 event->key_code = -1;
2372
2373 if (missing & DIEF_KEYID)
2374 event->key_id = DIKI_UNKNOWN;
2375
2376 if (missing & DIEF_KEYSYMBOL)
2377 event->key_symbol = DIKS_NULL;
2378
2379 /*
2380 * Update cached values for modifiers.
2381 */
2382 if (DFB_KEY_TYPE(event->key_symbol) == DIKT_MODIFIER) {
2383 if (event->type == DIET_KEYPRESS) {
2384 switch (event->key_id) {
2385 case DIKI_SHIFT_L:
2386 shared->state.modifiers_l |= DIMM_SHIFT;
2387 break;
2388 case DIKI_SHIFT_R:
2389 shared->state.modifiers_r |= DIMM_SHIFT;
2390 break;
2391 case DIKI_CONTROL_L:
2392 shared->state.modifiers_l |= DIMM_CONTROL;
2393 break;
2394 case DIKI_CONTROL_R:
2395 shared->state.modifiers_r |= DIMM_CONTROL;
2396 break;
2397 case DIKI_ALT_L:
2398 shared->state.modifiers_l |= DIMM_ALT;
2399 break;
2400 case DIKI_ALT_R:
2401 shared->state.modifiers_r |= (event->key_symbol == DIKS_ALTGR) ? DIMM_ALTGR : DIMM_ALT;
2402 break;
2403 case DIKI_META_L:
2404 shared->state.modifiers_l |= DIMM_META;
2405 break;
2406 case DIKI_META_R:
2407 shared->state.modifiers_r |= DIMM_META;
2408 break;
2409 case DIKI_SUPER_L:
2410 shared->state.modifiers_l |= DIMM_SUPER;
2411 break;
2412 case DIKI_SUPER_R:
2413 shared->state.modifiers_r |= DIMM_SUPER;
2414 break;
2415 case DIKI_HYPER_L:
2416 shared->state.modifiers_l |= DIMM_HYPER;
2417 break;
2418 case DIKI_HYPER_R:
2419 shared->state.modifiers_r |= DIMM_HYPER;
2420 break;
2421 default:
2422 ;
2423 }
2424 }
2425 else {
2426 switch (event->key_id) {
2427 case DIKI_SHIFT_L:
2428 shared->state.modifiers_l &= ~DIMM_SHIFT;
2429 break;
2430 case DIKI_SHIFT_R:
2431 shared->state.modifiers_r &= ~DIMM_SHIFT;
2432 break;
2433 case DIKI_CONTROL_L:
2434 shared->state.modifiers_l &= ~DIMM_CONTROL;
2435 break;
2436 case DIKI_CONTROL_R:
2437 shared->state.modifiers_r &= ~DIMM_CONTROL;
2438 break;
2439 case DIKI_ALT_L:
2440 shared->state.modifiers_l &= ~DIMM_ALT;
2441 break;
2442 case DIKI_ALT_R:
2443 shared->state.modifiers_r &= (event->key_symbol == DIKS_ALTGR) ? ~DIMM_ALTGR : ~DIMM_ALT;
2444 break;
2445 case DIKI_META_L:
2446 shared->state.modifiers_l &= ~DIMM_META;
2447 break;
2448 case DIKI_META_R:
2449 shared->state.modifiers_r &= ~DIMM_META;
2450 break;
2451 case DIKI_SUPER_L:
2452 shared->state.modifiers_l &= ~DIMM_SUPER;
2453 break;
2454 case DIKI_SUPER_R:
2455 shared->state.modifiers_r &= ~DIMM_SUPER;
2456 break;
2457 case DIKI_HYPER_L:
2458 shared->state.modifiers_l &= ~DIMM_HYPER;
2459 break;
2460 case DIKI_HYPER_R:
2461 shared->state.modifiers_r &= ~DIMM_HYPER;
2462 break;
2463 default:
2464 ;
2465 }
2466 }
2467
2468 /* write back to event */
2469 if (missing & DIEF_MODIFIERS)
2470 event->modifiers = shared->state.modifiers_l | shared->state.modifiers_r;
2471 }
2472
2473 /*
2474 * Update cached values for locks.
2475 */
2476 if (event->type == DIET_KEYPRESS) {
2477
2478 /* When we receive a new key press, toggle lock flags */
2479 if (shared->first_press || shared->last_key != event->key_id) {
2480 switch (event->key_id) {
2481 case DIKI_CAPS_LOCK:
2482 shared->state.locks ^= DILS_CAPS;
2483 break;
2484 case DIKI_NUM_LOCK:
2485 shared->state.locks ^= DILS_NUM;
2486 break;
2487 case DIKI_SCROLL_LOCK:
2488 shared->state.locks ^= DILS_SCROLL;
2489 break;
2490 default:
2491 ;
2492 }
2493 }
2494
2495 /* write back to event */
2496 if (missing & DIEF_LOCKS)
2497 event->locks = shared->state.locks;
2498
2499 /* store last pressed key */
2500 shared->last_key = event->key_id;
2501 shared->first_press = false;
2502 }
2503 else if (event->type == DIET_KEYRELEASE) {
2504
2505 shared->first_press = true;
2506 }
2507
2508 /* Handle dead keys. */
2509 if (DFB_KEY_TYPE(shared->last_symbol) == DIKT_DEAD) {
2510 for (i=0; i<D_ARRAY_SIZE(deadkey_maps); i++) {
2511 const DeadKeyMap *map = &deadkey_maps[i];
2512
2513 if (map->deadkey == shared->last_symbol) {
2514 for (i=0; map->combos[i].target; i++) {
2515 if (map->combos[i].target == event->key_symbol) {
2516 event->key_symbol = map->combos[i].result;
2517 break;
2518 }
2519 }
2520 break;
2521 }
2522 }
2523
2524 if (event->type == DIET_KEYRELEASE &&
2525 DFB_KEY_TYPE(event->key_symbol) != DIKT_MODIFIER)
2526 shared->last_symbol = event->key_symbol;
2527 }
2528 else
2529 shared->last_symbol = event->key_symbol;
2530 }
2531
2532 static void
fixup_mouse_event(CoreInputDevice * device,DFBInputEvent * event)2533 fixup_mouse_event( CoreInputDevice *device, DFBInputEvent *event )
2534 {
2535 InputDeviceShared *shared = device->shared;
2536
2537 D_MAGIC_ASSERT( device, CoreInputDevice );
2538
2539 if (event->flags & DIEF_BUTTONS) {
2540 shared->state.buttons = event->buttons;
2541 }
2542 else {
2543 switch (event->type) {
2544 case DIET_BUTTONPRESS:
2545 shared->state.buttons |= (1 << event->button);
2546 break;
2547 case DIET_BUTTONRELEASE:
2548 shared->state.buttons &= ~(1 << event->button);
2549 break;
2550 default:
2551 ;
2552 }
2553
2554 /* Add missing flag */
2555 event->flags |= DIEF_BUTTONS;
2556
2557 event->buttons = shared->state.buttons;
2558 }
2559
2560 switch (event->type) {
2561 case DIET_AXISMOTION:
2562 if ((event->flags & DIEF_AXISABS) && event->axis >= 0 && event->axis < shared->axis_num) {
2563 if (!(event->flags & DIEF_MIN) && (shared->axis_info[event->axis].flags & DIAIF_ABS_MIN)) {
2564 event->min = shared->axis_info[event->axis].abs_min;
2565
2566 event->flags |= DIEF_MIN;
2567 }
2568
2569 if (!(event->flags & DIEF_MAX) && (shared->axis_info[event->axis].flags & DIAIF_ABS_MAX)) {
2570 event->max = shared->axis_info[event->axis].abs_max;
2571
2572 event->flags |= DIEF_MAX;
2573 }
2574 }
2575 break;
2576
2577 default:
2578 break;
2579 }
2580 }
2581
2582 static DFBInputDeviceKeyIdentifier
symbol_to_id(DFBInputDeviceKeySymbol symbol)2583 symbol_to_id( DFBInputDeviceKeySymbol symbol )
2584 {
2585 if (symbol >= 'a' && symbol <= 'z')
2586 return DIKI_A + symbol - 'a';
2587
2588 if (symbol >= 'A' && symbol <= 'Z')
2589 return DIKI_A + symbol - 'A';
2590
2591 if (symbol >= '0' && symbol <= '9')
2592 return DIKI_0 + symbol - '0';
2593
2594 if (symbol >= DIKS_F1 && symbol <= DIKS_F12)
2595 return DIKI_F1 + symbol - DIKS_F1;
2596
2597 switch (symbol) {
2598 case DIKS_ESCAPE:
2599 return DIKI_ESCAPE;
2600
2601 case DIKS_CURSOR_LEFT:
2602 return DIKI_LEFT;
2603
2604 case DIKS_CURSOR_RIGHT:
2605 return DIKI_RIGHT;
2606
2607 case DIKS_CURSOR_UP:
2608 return DIKI_UP;
2609
2610 case DIKS_CURSOR_DOWN:
2611 return DIKI_DOWN;
2612
2613 case DIKS_ALTGR:
2614 return DIKI_ALT_R;
2615
2616 case DIKS_CONTROL:
2617 return DIKI_CONTROL_L;
2618
2619 case DIKS_SHIFT:
2620 return DIKI_SHIFT_L;
2621
2622 case DIKS_ALT:
2623 return DIKI_ALT_L;
2624
2625 case DIKS_META:
2626 return DIKI_META_L;
2627
2628 case DIKS_SUPER:
2629 return DIKI_SUPER_L;
2630
2631 case DIKS_HYPER:
2632 return DIKI_HYPER_L;
2633
2634 case DIKS_TAB:
2635 return DIKI_TAB;
2636
2637 case DIKS_ENTER:
2638 return DIKI_ENTER;
2639
2640 case DIKS_SPACE:
2641 return DIKI_SPACE;
2642
2643 case DIKS_BACKSPACE:
2644 return DIKI_BACKSPACE;
2645
2646 case DIKS_INSERT:
2647 return DIKI_INSERT;
2648
2649 case DIKS_DELETE:
2650 return DIKI_DELETE;
2651
2652 case DIKS_HOME:
2653 return DIKI_HOME;
2654
2655 case DIKS_END:
2656 return DIKI_END;
2657
2658 case DIKS_PAGE_UP:
2659 return DIKI_PAGE_UP;
2660
2661 case DIKS_PAGE_DOWN:
2662 return DIKI_PAGE_DOWN;
2663
2664 case DIKS_CAPS_LOCK:
2665 return DIKI_CAPS_LOCK;
2666
2667 case DIKS_NUM_LOCK:
2668 return DIKI_NUM_LOCK;
2669
2670 case DIKS_SCROLL_LOCK:
2671 return DIKI_SCROLL_LOCK;
2672
2673 case DIKS_PRINT:
2674 return DIKI_PRINT;
2675
2676 case DIKS_PAUSE:
2677 return DIKI_PAUSE;
2678
2679 case DIKS_BACKSLASH:
2680 return DIKI_BACKSLASH;
2681
2682 case DIKS_PERIOD:
2683 return DIKI_PERIOD;
2684
2685 case DIKS_COMMA:
2686 return DIKI_COMMA;
2687
2688 default:
2689 ;
2690 }
2691
2692 return DIKI_UNKNOWN;
2693 }
2694
2695 static DFBInputDeviceKeySymbol
id_to_symbol(DFBInputDeviceKeyIdentifier id,DFBInputDeviceModifierMask modifiers,DFBInputDeviceLockState locks)2696 id_to_symbol( DFBInputDeviceKeyIdentifier id,
2697 DFBInputDeviceModifierMask modifiers,
2698 DFBInputDeviceLockState locks )
2699 {
2700 bool shift = (modifiers & DIMM_SHIFT) || (locks & DILS_CAPS);
2701
2702 if (id >= DIKI_A && id <= DIKI_Z)
2703 return (shift ? DIKS_CAPITAL_A : DIKS_SMALL_A) + id - DIKI_A;
2704
2705 if (id >= DIKI_0 && id <= DIKI_9)
2706 return DIKS_0 + id - DIKI_0;
2707
2708 if (id >= DIKI_KP_0 && id <= DIKI_KP_9)
2709 return DIKS_0 + id - DIKI_KP_0;
2710
2711 if (id >= DIKI_F1 && id <= DIKI_F12)
2712 return DIKS_F1 + id - DIKI_F1;
2713
2714 switch (id) {
2715 case DIKI_ESCAPE:
2716 return DIKS_ESCAPE;
2717
2718 case DIKI_LEFT:
2719 return DIKS_CURSOR_LEFT;
2720
2721 case DIKI_RIGHT:
2722 return DIKS_CURSOR_RIGHT;
2723
2724 case DIKI_UP:
2725 return DIKS_CURSOR_UP;
2726
2727 case DIKI_DOWN:
2728 return DIKS_CURSOR_DOWN;
2729
2730 case DIKI_CONTROL_L:
2731 case DIKI_CONTROL_R:
2732 return DIKS_CONTROL;
2733
2734 case DIKI_SHIFT_L:
2735 case DIKI_SHIFT_R:
2736 return DIKS_SHIFT;
2737
2738 case DIKI_ALT_L:
2739 case DIKI_ALT_R:
2740 return DIKS_ALT;
2741
2742 case DIKI_META_L:
2743 case DIKI_META_R:
2744 return DIKS_META;
2745
2746 case DIKI_SUPER_L:
2747 case DIKI_SUPER_R:
2748 return DIKS_SUPER;
2749
2750 case DIKI_HYPER_L:
2751 case DIKI_HYPER_R:
2752 return DIKS_HYPER;
2753
2754 case DIKI_TAB:
2755 return DIKS_TAB;
2756
2757 case DIKI_ENTER:
2758 return DIKS_ENTER;
2759
2760 case DIKI_SPACE:
2761 return DIKS_SPACE;
2762
2763 case DIKI_BACKSPACE:
2764 return DIKS_BACKSPACE;
2765
2766 case DIKI_INSERT:
2767 return DIKS_INSERT;
2768
2769 case DIKI_DELETE:
2770 return DIKS_DELETE;
2771
2772 case DIKI_HOME:
2773 return DIKS_HOME;
2774
2775 case DIKI_END:
2776 return DIKS_END;
2777
2778 case DIKI_PAGE_UP:
2779 return DIKS_PAGE_UP;
2780
2781 case DIKI_PAGE_DOWN:
2782 return DIKS_PAGE_DOWN;
2783
2784 case DIKI_CAPS_LOCK:
2785 return DIKS_CAPS_LOCK;
2786
2787 case DIKI_NUM_LOCK:
2788 return DIKS_NUM_LOCK;
2789
2790 case DIKI_SCROLL_LOCK:
2791 return DIKS_SCROLL_LOCK;
2792
2793 case DIKI_PRINT:
2794 return DIKS_PRINT;
2795
2796 case DIKI_PAUSE:
2797 return DIKS_PAUSE;
2798
2799 case DIKI_KP_DIV:
2800 return DIKS_SLASH;
2801
2802 case DIKI_KP_MULT:
2803 return DIKS_ASTERISK;
2804
2805 case DIKI_KP_MINUS:
2806 return DIKS_MINUS_SIGN;
2807
2808 case DIKI_KP_PLUS:
2809 return DIKS_PLUS_SIGN;
2810
2811 case DIKI_KP_ENTER:
2812 return DIKS_ENTER;
2813
2814 case DIKI_KP_SPACE:
2815 return DIKS_SPACE;
2816
2817 case DIKI_KP_TAB:
2818 return DIKS_TAB;
2819
2820 case DIKI_KP_EQUAL:
2821 return DIKS_EQUALS_SIGN;
2822
2823 case DIKI_KP_DECIMAL:
2824 return DIKS_PERIOD;
2825
2826 case DIKI_KP_SEPARATOR:
2827 return DIKS_COMMA;
2828
2829 case DIKI_BACKSLASH:
2830 return DIKS_BACKSLASH;
2831
2832 case DIKI_EQUALS_SIGN:
2833 return DIKS_EQUALS_SIGN;
2834
2835 case DIKI_LESS_SIGN:
2836 return DIKS_LESS_THAN_SIGN;
2837
2838 case DIKI_MINUS_SIGN:
2839 return DIKS_MINUS_SIGN;
2840
2841 case DIKI_PERIOD:
2842 return DIKS_PERIOD;
2843
2844 case DIKI_QUOTE_LEFT:
2845 case DIKI_QUOTE_RIGHT:
2846 return DIKS_QUOTATION;
2847
2848 case DIKI_SEMICOLON:
2849 return DIKS_SEMICOLON;
2850
2851 case DIKI_SLASH:
2852 return DIKS_SLASH;
2853
2854 default:
2855 ;
2856 }
2857
2858 return DIKS_NULL;
2859 }
2860
2861 static void
release_key(CoreInputDevice * device,DFBInputDeviceKeyIdentifier id)2862 release_key( CoreInputDevice *device, DFBInputDeviceKeyIdentifier id )
2863 {
2864 DFBInputEvent evt;
2865
2866 D_MAGIC_ASSERT( device, CoreInputDevice );
2867
2868 evt.type = DIET_KEYRELEASE;
2869
2870 if (DFB_KEY_TYPE(id) == DIKT_IDENTIFIER) {
2871 evt.flags = DIEF_KEYID;
2872 evt.key_id = id;
2873 }
2874 else {
2875 evt.flags = DIEF_KEYSYMBOL;
2876 evt.key_symbol = id;
2877 }
2878
2879 dfb_input_dispatch( device, &evt );
2880 }
2881
2882 static void
flush_keys(CoreInputDevice * device)2883 flush_keys( CoreInputDevice *device )
2884 {
2885 D_MAGIC_ASSERT( device, CoreInputDevice );
2886
2887 if (device->shared->state.modifiers_l) {
2888 if (device->shared->state.modifiers_l & DIMM_ALT)
2889 release_key( device, DIKI_ALT_L );
2890
2891 if (device->shared->state.modifiers_l & DIMM_CONTROL)
2892 release_key( device, DIKI_CONTROL_L );
2893
2894 if (device->shared->state.modifiers_l & DIMM_HYPER)
2895 release_key( device, DIKI_HYPER_L );
2896
2897 if (device->shared->state.modifiers_l & DIMM_META)
2898 release_key( device, DIKI_META_L );
2899
2900 if (device->shared->state.modifiers_l & DIMM_SHIFT)
2901 release_key( device, DIKI_SHIFT_L );
2902
2903 if (device->shared->state.modifiers_l & DIMM_SUPER)
2904 release_key( device, DIKI_SUPER_L );
2905 }
2906
2907 if (device->shared->state.modifiers_r) {
2908 if (device->shared->state.modifiers_r & DIMM_ALTGR)
2909 release_key( device, DIKS_ALTGR );
2910
2911 if (device->shared->state.modifiers_r & DIMM_ALT)
2912 release_key( device, DIKI_ALT_R );
2913
2914 if (device->shared->state.modifiers_r & DIMM_CONTROL)
2915 release_key( device, DIKI_CONTROL_R );
2916
2917 if (device->shared->state.modifiers_r & DIMM_HYPER)
2918 release_key( device, DIKI_HYPER_R );
2919
2920 if (device->shared->state.modifiers_r & DIMM_META)
2921 release_key( device, DIKI_META_R );
2922
2923 if (device->shared->state.modifiers_r & DIMM_SHIFT)
2924 release_key( device, DIKI_SHIFT_R );
2925
2926 if (device->shared->state.modifiers_r & DIMM_SUPER)
2927 release_key( device, DIKI_SUPER_R );
2928 }
2929 }
2930
2931 static void
dump_primary_layer_surface(CoreDFB * core)2932 dump_primary_layer_surface( CoreDFB *core )
2933 {
2934 CoreLayer *layer = dfb_layer_at( DLID_PRIMARY );
2935 CoreLayerContext *context;
2936
2937 /* Get the currently active context. */
2938 if (dfb_layer_get_active_context( layer, &context ) == DFB_OK) {
2939 CoreLayerRegion *region;
2940
2941 /* Get the first region. */
2942 if (dfb_layer_context_get_primary_region( context,
2943 false, ®ion ) == DFB_OK)
2944 {
2945 CoreSurface *surface;
2946
2947 /* Lock the region to avoid tearing due to concurrent updates. */
2948 dfb_layer_region_lock( region );
2949
2950 /* Get the surface of the region. */
2951 if (dfb_layer_region_get_surface( region, &surface ) == DFB_OK) {
2952 /* Dump the surface contents. */
2953 dfb_surface_dump_buffer( surface, CSBR_FRONT, dfb_config->screenshot_dir, "dfb" );
2954
2955 /* Release the surface. */
2956 dfb_surface_unref( surface );
2957 }
2958
2959 /* Unlock the region. */
2960 dfb_layer_region_unlock( region );
2961
2962 /* Release the region. */
2963 dfb_layer_region_unref( region );
2964 }
2965
2966 /* Release the context. */
2967 dfb_layer_context_unref( context );
2968 }
2969 }
2970
2971 static bool
core_input_filter(CoreInputDevice * device,DFBInputEvent * event)2972 core_input_filter( CoreInputDevice *device, DFBInputEvent *event )
2973 {
2974 D_MAGIC_ASSERT( device, CoreInputDevice );
2975
2976 if (dfb_system_input_filter( device, event ))
2977 return true;
2978
2979 if (event->type == DIET_KEYPRESS) {
2980 switch (event->key_symbol) {
2981 case DIKS_PRINT:
2982 if (!event->modifiers && dfb_config->screenshot_dir) {
2983 dump_primary_layer_surface( device->core );
2984 return true;
2985 }
2986 break;
2987
2988 case DIKS_BACKSPACE:
2989 if (event->modifiers == DIMM_META)
2990 direct_trace_print_stacks();
2991
2992 break;
2993
2994 case DIKS_ESCAPE:
2995 if (event->modifiers == DIMM_META) {
2996 #if FUSION_BUILD_MULTI
2997 DFBResult ret;
2998 CoreLayer *layer = dfb_layer_at( DLID_PRIMARY );
2999 CoreLayerContext *context;
3000
3001 /* Get primary (shared) context. */
3002 ret = dfb_layer_get_primary_context( layer,
3003 false, &context );
3004 if (ret)
3005 return false;
3006
3007 /* Activate the context. */
3008 dfb_layer_activate_context( layer, context );
3009
3010 /* Release the context. */
3011 dfb_layer_context_unref( context );
3012
3013 #else
3014 kill( 0, SIGINT );
3015 #endif
3016
3017 return true;
3018 }
3019 break;
3020
3021 default:
3022 break;
3023 }
3024 }
3025
3026 return false;
3027 }
3028
3029