From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/DirectFB/wm/unique/device.c | 495 +++++++++++++++++++++++++++++++++++++ 1 file changed, 495 insertions(+) create mode 100755 Source/DirectFB/wm/unique/device.c (limited to 'Source/DirectFB/wm/unique/device.c') diff --git a/Source/DirectFB/wm/unique/device.c b/Source/DirectFB/wm/unique/device.c new file mode 100755 index 0000000..d6b5625 --- /dev/null +++ b/Source/DirectFB/wm/unique/device.c @@ -0,0 +1,495 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include + + +#define MAX_CLASSES 16 + + +D_DEBUG_DOMAIN( UniQuE_Device, "UniQuE/Device", "UniQuE's Devices" ); + + +static const ReactionFunc unique_device_globals[] = { + _unique_input_switch_device_listener, + _unique_cursor_device_listener, + NULL +}; + +/**************************************************************************************************/ + +typedef struct { + DirectLink link; + + int magic; + + DFBInputDeviceID source; + + GlobalReaction reaction; +} DeviceConnection; + +/**************************************************************************************************/ + +static void purge_connection( UniqueDevice *device, + DeviceConnection *connection ); + +/**************************************************************************************************/ + +static const UniqueDeviceClass *classes[MAX_CLASSES] = { NULL }; + +static pthread_mutex_t classes_lock = PTHREAD_MUTEX_INITIALIZER; +static int classes_count = 0; + +/**************************************************************************************************/ + +DFBResult +unique_device_class_register( const UniqueDeviceClass *clazz, + UniqueDeviceClassID *ret_id ) +{ + int i; + + D_DEBUG_AT( UniQuE_Device, "unique_device_class_register( %p )\n", clazz ); + + D_ASSERT( clazz != NULL ); + D_ASSERT( ret_id != NULL ); + + pthread_mutex_lock( &classes_lock ); + + if (classes_count == MAX_CLASSES) { + D_WARN( "too many classes" ); + pthread_mutex_unlock( &classes_lock ); + return DFB_LIMITEXCEEDED; + } + + classes_count++; + + for (i=0; i New class ID is %d.\n", i ); + + D_ASSERT( i < MAX_CLASSES ); + + *ret_id = i; + + pthread_mutex_unlock( &classes_lock ); + + return DFB_OK; +} + +DFBResult +unique_device_class_unregister( UniqueDeviceClassID id ) +{ + D_DEBUG_AT( UniQuE_Device, "unique_device_class_unregister( %d )\n", id ); + + pthread_mutex_lock( &classes_lock ); + + D_ASSERT( id >= 0 ); + D_ASSERT( id < MAX_CLASSES ); + D_ASSERT( classes[id] != NULL ); + + classes[id] = NULL; + + classes_count--; + + pthread_mutex_unlock( &classes_lock ); + + return DFB_OK; +} + +/**************************************************************************************************/ + +DFBResult +unique_device_create( CoreDFB *core, + UniqueContext *context, + UniqueDeviceClassID class_id, + void *ctx, + UniqueDevice **ret_device ) +{ + DFBResult ret; + UniqueDevice *device; + const UniqueDeviceClass *clazz; + + D_DEBUG_AT( UniQuE_Device, "unique_device_create( class %d )\n", class_id ); + + D_MAGIC_ASSERT( context, UniqueContext ); + + D_ASSERT( class_id >= 0 ); + D_ASSERT( class_id < MAX_CLASSES ); + + clazz = classes[class_id]; + + D_ASSERT( clazz != NULL ); + D_ASSERT( ret_device != NULL ); + + /* Allocate device data. */ + device = SHCALLOC( context->shmpool, 1, sizeof(UniqueDevice) ); + if (!device) { + D_WARN( "out of (shared) memory" ); + return D_OOSHM(); + } + + /* Initialize device data. */ + device->context = context; + device->clazz = class_id; + device->ctx = ctx; + + /* Allocate private device data. */ + if (clazz->data_size) { + device->data = SHCALLOC( context->shmpool, 1, clazz->data_size ); + if (!device->data) { + ret = D_OOSHM(); + goto error; + } + } + + /* Create reactor for dispatching generated events. */ + device->reactor = fusion_reactor_new( sizeof(UniqueInputEvent), + "UniQuE Device", dfb_core_world(core) ); + if (!device->reactor) { + ret = DFB_FUSION; + goto error; + } + + fusion_reactor_set_lock( device->reactor, &context->stack->context->lock ); + + D_MAGIC_SET( device, UniqueDevice ); + + if (clazz->Initialize) { + ret = clazz->Initialize( device, device->data, device->ctx ); + if (ret) { + D_MAGIC_CLEAR( device ); + goto error; + } + } + + D_DEBUG_AT( UniQuE_Device, " -> device created (%p)\n", device ); + + *ret_device = device; + + return DFB_OK; + + +error: + if (device->reactor) + fusion_reactor_free( device->reactor ); + + if (device->data) + SHFREE( context->shmpool, device->data ); + + SHFREE( context->shmpool, device ); + + return ret; +} + +DFBResult +unique_device_destroy( UniqueDevice *device ) +{ + DirectLink *n; + DeviceConnection *connection; + UniqueContext *context; + const UniqueDeviceClass *clazz; + + D_MAGIC_ASSERT( device, UniqueDevice ); + + context = device->context; + + D_MAGIC_ASSERT( context, UniqueContext ); + + D_ASSERT( device->clazz >= 0 ); + D_ASSERT( device->clazz < MAX_CLASSES ); + + clazz = classes[device->clazz]; + + D_ASSERT( clazz != NULL ); + + D_DEBUG_AT( UniQuE_Device, "unique_device_destroy( %p )\n", device ); + + direct_list_foreach_safe (connection, n, device->connections) { + D_MAGIC_ASSERT( connection, DeviceConnection ); + + purge_connection( device, connection ); + } + + D_ASSERT( device->connections == NULL ); + + if (clazz->Shutdown) + clazz->Shutdown( device, device->data, device->ctx ); + + fusion_reactor_free( device->reactor ); + + if (device->data) + SHFREE( context->shmpool, device->data ); + + D_MAGIC_CLEAR( device ); + + SHFREE( context->shmpool, device ); + + return DFB_OK; +} + +DFBResult +unique_device_connect( UniqueDevice *device, + CoreInputDevice *source ) +{ + DFBResult ret; + WMShared *shared; + UniqueContext *context; + DeviceConnection *connection; + + D_MAGIC_ASSERT( device, UniqueDevice ); + + D_ASSERT( source != NULL ); + + D_ASSERT( device->clazz >= 0 ); + D_ASSERT( device->clazz < MAX_CLASSES ); + D_ASSERT( classes[device->clazz] != NULL ); + + context = device->context; + + D_MAGIC_ASSERT( context, UniqueContext ); + + shared = context->shared; + + D_MAGIC_ASSERT( shared, WMShared ); + + D_DEBUG_AT( UniQuE_Device, "unique_device_connect( %p, %p, ID %d )\n", + device, source, dfb_input_device_id( source ) ); + + /* Allocate connection structure. */ + connection = SHCALLOC( context->shmpool, 1, sizeof(DeviceConnection) ); + if (!connection) + return D_OOSHM(); + + /* Initialize connection structure. */ + connection->source = dfb_input_device_id( source ); + + /* Attach global reaction for processing events. */ + ret = dfb_input_attach_global( source, shared->device_listener, + device, &connection->reaction ); + if (ret) { + SHFREE( context->shmpool, connection ); + return ret; + } + + /* Add the new connection to the list. */ + direct_list_append( &device->connections, &connection->link ); + + D_MAGIC_SET( connection, DeviceConnection ); + + if (classes[device->clazz]->Connected) + classes[device->clazz]->Connected( device, device->data, device->ctx, source ); + + return DFB_OK; +} + +DFBResult +unique_device_disconnect( UniqueDevice *device, + CoreInputDevice *source ) +{ + DFBInputDeviceID source_id; + DeviceConnection *connection; + + D_MAGIC_ASSERT( device, UniqueDevice ); + + D_ASSERT( source != NULL ); + + D_ASSERT( device->clazz >= 0 ); + D_ASSERT( device->clazz < MAX_CLASSES ); + D_ASSERT( classes[device->clazz] != NULL ); + + source_id = dfb_input_device_id( source ); + + direct_list_foreach (connection, device->connections) { + D_MAGIC_ASSERT( connection, DeviceConnection ); + + if (connection->source == source_id) + break; + } + + if (!connection) { + D_WARN( "source not found amoung connections" ); + return DFB_ITEMNOTFOUND; + } + + purge_connection( device, connection ); + + return DFB_OK; +} + +DFBResult +unique_device_attach( UniqueDevice *device, + ReactionFunc func, + void *ctx, + Reaction *reaction ) +{ + D_MAGIC_ASSERT( device, UniqueDevice ); + + return fusion_reactor_attach( device->reactor, func, ctx, reaction ); +} + +DFBResult +unique_device_detach( UniqueDevice *device, + Reaction *reaction ) +{ + D_MAGIC_ASSERT( device, UniqueDevice ); + + return fusion_reactor_detach( device->reactor, reaction ); +} + +DFBResult +unique_device_attach_global( UniqueDevice *device, + int index, + void *ctx, + GlobalReaction *reaction ) +{ + D_MAGIC_ASSERT( device, UniqueDevice ); + + return fusion_reactor_attach_global( device->reactor, index, ctx, reaction ); +} + +DFBResult +unique_device_detach_global( UniqueDevice *device, + GlobalReaction *reaction ) +{ + D_MAGIC_ASSERT( device, UniqueDevice ); + + return fusion_reactor_detach_global( device->reactor, reaction ); +} + +DFBResult +unique_device_dispatch( UniqueDevice *device, + const UniqueInputEvent *event ) +{ + D_MAGIC_ASSERT( device, UniqueDevice ); + + return fusion_reactor_dispatch( device->reactor, event, true, unique_device_globals ); +} + +bool +unique_device_filter ( UniqueDeviceClassID class_id, + const UniqueInputEvent *event, + const UniqueInputEvent *filter ) +{ + const UniqueDeviceClass *clazz; + + D_ASSERT( class_id >= 0 ); + D_ASSERT( class_id < MAX_CLASSES ); + + D_ASSERT( event != NULL ); + D_ASSERT( filter != NULL ); + + clazz = classes[class_id]; + + D_ASSERT( clazz != NULL ); + + if (clazz->FilterEvent) + return clazz->FilterEvent( event, filter ); + + return false; +} + +/**************************************************************************************************/ + +ReactionResult +_unique_device_listener( const void *msg_data, + void *ctx ) +{ + const DFBInputEvent *event = msg_data; + UniqueDevice *device = ctx; + + D_ASSERT( event != NULL ); + + D_MAGIC_ASSERT( device, UniqueDevice ); + + D_ASSERT( device->clazz >= 0 ); + D_ASSERT( device->clazz < MAX_CLASSES ); + D_ASSERT( classes[device->clazz] != NULL ); + D_ASSERT( classes[device->clazz]->ProcessEvent != NULL ); + + classes[device->clazz]->ProcessEvent( device, device->data, device->ctx, event ); + + return RS_OK; +} + +/**************************************************************************************************/ + +static void +purge_connection( UniqueDevice *device, + DeviceConnection *connection ) +{ + CoreInputDevice *source; + UniqueContext *context; + + D_MAGIC_ASSERT( device, UniqueDevice ); + D_MAGIC_ASSERT( connection, DeviceConnection ); + + context = device->context; + + D_MAGIC_ASSERT( context, UniqueContext ); + + source = dfb_input_device_at( connection->source ); + + D_ASSERT( source != NULL ); + + /* Detach global reaction for processing events. */ + dfb_input_detach_global( source, &connection->reaction ); + + direct_list_remove( &device->connections, &connection->link ); + + if (classes[device->clazz]->Disconnected) + classes[device->clazz]->Disconnected( device, device->data, device->ctx, source ); + + D_MAGIC_CLEAR( connection ); + + SHFREE( context->shmpool, connection ); +} + -- cgit