/* (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 Shane Volpe , Andreas Hundt , Sven Neumann and Ville Syrj��. 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 DFB_INPUT_DRIVER( tslib ) typedef struct { CoreInputDevice *device; DirectThread *thread; struct tsdev *ts; } tslibData; #define MAX_TSLIB_DEVICES 16 static int num_devices = 0; static char *device_names[MAX_TSLIB_DEVICES]; static void * tslibEventThread( DirectThread *thread, void *driver_data ) { tslibData *data = (tslibData *) driver_data; struct ts_sample ts_event; int readlen; int old_x = -1; int old_y = -1; unsigned int old_pressure = 0; while ((readlen = ts_read( data->ts, &ts_event, 1 )) >= 0) { DFBInputEvent evt; direct_thread_testcancel( thread ); if (readlen < 1) continue; if (ts_event.pressure) { if (ts_event.x != old_x) { evt.type = DIET_AXISMOTION; evt.flags = DIEF_AXISABS; evt.axis = DIAI_X; evt.axisabs = ts_event.x; dfb_input_dispatch( data->device, &evt ); old_x = ts_event.x; } if (ts_event.y != old_y) { evt.type = DIET_AXISMOTION; evt.flags = DIEF_AXISABS; evt.axis = DIAI_Y; evt.axisabs = ts_event.y; dfb_input_dispatch( data->device, &evt ); old_y = ts_event.y; } } if (!ts_event.pressure != !old_pressure) { evt.type = ts_event.pressure ? DIET_BUTTONPRESS : DIET_BUTTONRELEASE; evt.flags = DIEF_NONE; evt.button = DIBI_LEFT; dfb_input_dispatch( data->device, &evt ); old_pressure = ts_event.pressure; } } if (readlen < 0) D_ERROR( "tslib Input thread died\n" ); return NULL; } static bool check_device( const char *device ) { struct tsdev *ts; ts = ts_open( device, 0 ); if (!ts) return false; if (ts_config( ts )) { ts_close( ts ); return false; } ts_close( ts ); return true; } /* exported symbols */ static int driver_get_available(void) { int i; char *tsdev; /* Use the devices specified in the configuration. */ if (fusion_vector_has_elements( &dfb_config->tslib_devices )) { const char *device; fusion_vector_foreach (device, i, dfb_config->tslib_devices) { if (num_devices >= MAX_TSLIB_DEVICES) break; if (check_device( device )) device_names[num_devices++] = D_STRDUP( device ); } return num_devices; } /* Check for environment variable. */ tsdev = getenv( "TSLIB_TSDEVICE" ); if (tsdev && check_device( tsdev )) device_names[num_devices++] = D_STRDUP( tsdev ); /* Try to guess some (more) devices. */ for (i = 0; i < MAX_TSLIB_DEVICES; i++) { char buf[32]; if (num_devices >= MAX_TSLIB_DEVICES) break; snprintf( buf, 32, "/dev/input/tslib%d", i ); /* Already handled above. */ if (tsdev && !strcmp( tsdev, buf )) continue; if (check_device( buf )) device_names[num_devices++] = D_STRDUP( buf ); } return num_devices; } static void driver_get_info( InputDriverInfo *info ) { /* fill driver info structure */ snprintf( info->name, DFB_INPUT_DRIVER_INFO_NAME_LENGTH, "tslib Input Driver" ); snprintf( info->vendor, DFB_INPUT_DRIVER_INFO_VENDOR_LENGTH, "tslib" ); info->version.major = 0; info->version.minor = 1; } static DFBResult driver_open_device( CoreInputDevice *device, unsigned int number, InputDeviceInfo *info, void **driver_data ) { tslibData *data; struct tsdev *ts; /* open device */ ts = ts_open( device_names[number], 0 ); if (!ts) { D_ERROR( "DirectFB/tslib: Error opening `%s'!\n", device_names[number] ); return DFB_INIT; } /* configure device */ if (ts_config( ts )) { D_ERROR( "DirectFB/tslib: Error configuring `%s'!\n", device_names[number] ); ts_close( ts ); return DFB_INIT; } /* fill device info structure */ snprintf( info->desc.name, DFB_INPUT_DEVICE_DESC_NAME_LENGTH, "tslib touchscreen %d", number ); snprintf( info->desc.vendor, DFB_INPUT_DEVICE_DESC_VENDOR_LENGTH, "tslib" ); info->prefered_id = DIDID_MOUSE; info->desc.type = DIDTF_MOUSE; info->desc.caps = DICAPS_AXES | DICAPS_BUTTONS; info->desc.max_axis = DIAI_Y; info->desc.max_button = DIBI_LEFT; /* allocate and fill private data */ data = D_CALLOC( 1, sizeof(tslibData) ); if (!data) { ts_close( ts ); return D_OOM(); } data->ts = ts; data->device = device; /* start input thread */ data->thread = direct_thread_create( DTT_INPUT, tslibEventThread, data, "tslib 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 void driver_close_device( void *driver_data ) { tslibData *data = (tslibData*) driver_data; /* stop input thread */ direct_thread_cancel( data->thread ); direct_thread_join( data->thread ); direct_thread_destroy( data->thread ); /* close device */ ts_close( data->ts ); /* free private data */ D_FREE( data ); }