/* (c) Copyright 2000-2002 convergence integrated media GmbH. (c) Copyright 2002 convergence GmbH. All rights reserved. Written by Denis Oliver Kropp , Andreas Hundt and Sven Neumann . 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 "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define DFB_INPUTDRIVER_HAS_AXIS_INFO #include DFB_INPUT_DRIVER( divine ) #define PIPE_PATH "/tmp/divine" /* * declaration of private data */ typedef struct { int fd; CoreInputDevice *device; DirectThread *thread; } DiVineData; /* * Input thread reading from pipe. * Directly passes read events to input core. */ static void* divineEventThread( DirectThread *thread, void *driver_data ) { DiVineData *data = (DiVineData*) driver_data; DFBInputEvent event; struct pollfd pfd; /* fill poll info */ pfd.fd = data->fd; pfd.events = POLLIN; /* wait for the next event */ while (poll( &pfd, 1, -1 ) > 0 || errno == EINTR) { direct_thread_testcancel( thread ); /* read the next event from the pipe */ if (read( data->fd, &event, sizeof(DFBInputEvent) ) == sizeof(DFBInputEvent)) { /* directly dispatch the event */ dfb_input_dispatch( data->device, &event ); } else usleep( 20000 ); /* avoid 100% CPU usage in case poll() doesn't work */ } D_PERROR( "divine thread died\n" ); return NULL; } /* exported symbols */ /* * Return the number of available devices. * Called once during initialization of DirectFB. */ static int driver_get_available() { int fd; /* create the pipe if not already existent */ if (mkfifo( PIPE_PATH, 0660 ) && errno != EEXIST) { D_PERROR( "DirectFB/DiVine: could not create pipe '%s'\n", PIPE_PATH ); return 0; } /* try to open pipe */ fd = open( PIPE_PATH, O_RDONLY | O_NONBLOCK ); if (fd < 0) { D_PERROR( "DirectFB/DiVine: could not open pipe '%s'\n", PIPE_PATH ); return 0; } /* close pipe */ close( fd ); return 1; } /* * Fill out general information about this driver. * Called once during initialization of DirectFB. */ static void driver_get_info( InputDriverInfo *info ) { /* fill driver info structure */ snprintf( info->name, DFB_INPUT_DRIVER_INFO_NAME_LENGTH, "DiVine Driver" ); snprintf( info->vendor, DFB_INPUT_DRIVER_INFO_VENDOR_LENGTH, "Convergence GmbH" ); info->version.major = DIVINE_MAJOR_VERSION; info->version.minor = DIVINE_MINOR_VERSION; } /* * Open the pipe, fill out information about device, * allocate and fill private data, start input thread. * Called during initialization, resuming or taking over mastership. */ static DFBResult driver_open_device( CoreInputDevice *device, unsigned int number, InputDeviceInfo *info, void **driver_data ) { int fd; DiVineData *data; /* open pipe */ fd = open( PIPE_PATH, O_RDONLY | O_NONBLOCK ); if (fd < 0) { D_PERROR( "DirectFB/DiVine: could not open pipe '%s'\n", PIPE_PATH ); return DFB_INIT; } /* set device name */ snprintf( info->desc.name, DFB_INPUT_DEVICE_DESC_NAME_LENGTH, "Virtual Input" ); /* set device vendor */ snprintf( info->desc.vendor, DFB_INPUT_DEVICE_DESC_VENDOR_LENGTH, "DirectFB" ); /* set one of the primary input device IDs */ info->prefered_id = DIDID_ANY; /* set type flags */ info->desc.type = DIDTF_KEYBOARD | DIDTF_MOUSE | DIDTF_JOYSTICK | DIDTF_REMOTE | DIDTF_VIRTUAL; /* set capabilities */ info->desc.caps = DICAPS_ALL; info->desc.max_axis = DIAI_LAST; /* allocate and fill private data */ data = D_CALLOC( 1, sizeof(DiVineData) ); data->fd = fd; data->device = device; /* start input thread */ data->thread = direct_thread_create( DTT_INPUT, divineEventThread, data, "Virtual Input" ); /* set private data pointer */ *driver_data = data; return DFB_OK; } /* * Fetch one entry from the device's keymap if supported. */ static DFBResult driver_get_keymap_entry( CoreInputDevice *device, void *driver_data, DFBInputDeviceKeymapEntry *entry ) { return DFB_UNSUPPORTED; } static DFBResult driver_get_axis_info( CoreInputDevice *device, void *driver_data, DFBInputDeviceAxisIdentifier axis, DFBInputDeviceAxisInfo *ret_info ) { ret_info->flags = DIAIF_ABS_MIN | DIAIF_ABS_MAX; ret_info->abs_min = 0; ret_info->abs_max = 65535; return DFB_OK; } /* * End thread, close device and free private data. */ static void driver_close_device( void *driver_data ) { DiVineData *data = (DiVineData*) driver_data; /* stop input thread */ direct_thread_cancel( data->thread ); direct_thread_join( data->thread ); direct_thread_destroy( data->thread ); /* close pipe */ close( data->fd ); /* free private data */ D_FREE( data ); }