summaryrefslogtreecommitdiff
path: root/Source/DirectFB/inputdrivers/dynapro/dynapro.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/inputdrivers/dynapro/dynapro.c')
-rwxr-xr-xSource/DirectFB/inputdrivers/dynapro/dynapro.c356
1 files changed, 356 insertions, 0 deletions
diff --git a/Source/DirectFB/inputdrivers/dynapro/dynapro.c b/Source/DirectFB/inputdrivers/dynapro/dynapro.c
new file mode 100755
index 0000000..11ab3fb
--- /dev/null
+++ b/Source/DirectFB/inputdrivers/dynapro/dynapro.c
@@ -0,0 +1,356 @@
+/*
+ Written by Pär Degerman <parde@ikp.liu.se>
+
+ 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.
+
+
+ NOTES
+ =====
+ This driver is based heavily on code from two other DirectFB
+ drivers, namely mutouch.c by Simon Ueng and elo.c by Byron
+ Stanoszek and Brandon Reynolds, so a lot of credit should go
+ to those people and not me.
+
+ INSTRUCTIONS
+ ============
+ You should change DYNAPRO_MIN_X and DYNAPRO_MIN_Y to match
+ the orientation of your touchscreen.
+
+*/
+
+#include <config.h>
+
+#include <unistd.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <fcntl.h>
+
+#include <directfb.h>
+
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+
+#include <core/input.h>
+#include <core/system.h>
+
+#include <misc/conf.h>
+
+#include <direct/debug.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/memcpy.h>
+#include <direct/thread.h>
+
+#include <core/input_driver.h>
+
+DFB_INPUT_DRIVER( dynapro )
+
+#define DYNAPRO_DEVICE "/dev/ttyS0"
+#define DYNAPRO_BAUD B9600
+#define DYNAPRO_PACKET_SIZE 5
+
+#define DYNAPRO_SCREENWIDTH 800
+#define DYNAPRO_SCREENHEIGHT 600
+#define DYNAPRO_MINX 800
+#define DYNAPRO_MINY 600
+
+#define DYNAPRO_CMD_TOUCH 0x81
+#define DYNAPRO_CMD_UNTOUCH 0x80
+
+typedef struct __dynaproData__ {
+ int fd;
+ DirectThread *thread;
+ CoreInputDevice *device;
+
+ unsigned short screen_width;
+ unsigned short screen_height;
+ unsigned short min_x;
+ unsigned short min_y;
+
+ unsigned short x;
+ unsigned short y;
+ unsigned char action;
+} dynaproData;
+
+/* Read a packet from touchcontroller */
+static inline unsigned char *dynapro_getpck(int fd)
+{
+ static unsigned char packet[DYNAPRO_PACKET_SIZE];
+ static unsigned int len = 0, start = 0;
+
+ while(1) {
+ if (read(fd, &packet[len++], 1) < 1) {
+ break;
+ }
+
+ if (0 == start) {
+ if (packet[len-1] & 0x80) {
+ /* Packet start found */
+ start = 1;
+ continue;
+ } else {
+ /* Continue searching for packet start */
+ len = 0;
+ start = 0;
+ continue;
+ }
+ } else if (len < DYNAPRO_PACKET_SIZE) {
+ /* Continue until we have a full packet */
+ start = 1;
+ continue;
+ }
+
+ /* A full packet received */
+ len = 0;
+ start = 0;
+ return packet;
+ }
+
+ return NULL;
+}
+
+/* Remove all input translations over tty serial controller.
+ *
+ * set=1: Saves current settings then turns rawmode on.
+ * set=0: Restores controller to previous saved value.
+ */
+static void tty_rawmode(int fd, int set)
+{
+ static struct termios tbuf, termios_save;
+
+ if(set) {
+ tcgetattr(fd, &termios_save);
+ tbuf = termios_save;
+
+ tbuf.c_iflag = 0; /* No input processing */
+ tbuf.c_oflag = 0; /* No output processing */
+ tbuf.c_lflag = 0; /* Disable erase/kill, signals, and echo */
+
+ /* Set baud & 1-char read mode */
+ tbuf.c_cflag = DYNAPRO_BAUD | CS8 | CLOCAL | CREAD;
+
+ tcsetattr(fd, TCSANOW, &tbuf);
+ } else {
+ tcsetattr(fd, TCSANOW, &termios_save);
+ }
+}
+
+/* Open file descriptor to touch device */
+static int dynaproOpenDevice(char *device)
+{
+ int fd;
+
+ if((fd = open(device, O_RDWR|O_NOCTTY)) == -1) {
+ D_PERROR("DirectFB/dynbapro: Error opening '%s'!\n",device);
+ return -1;
+ }
+
+ if((flock(fd, LOCK_EX|LOCK_NB)) == -1) {
+ D_PERROR("DirectFB/dynbapro: Error locking '%s'!\n",device);
+ close(fd);
+ return -1;
+ }
+
+ tty_rawmode(fd,1);
+
+ return fd;
+}
+
+
+static int dynaproGetEvent(dynaproData *event)
+{
+ unsigned char *ptr;
+ unsigned int cmd, x, y;
+
+ /* read packet */
+ if(!(ptr = dynapro_getpck(event->fd))) {
+ return -1;
+ }
+
+ /* Get command (touch/untouch) and coordinates */
+ cmd = ptr[0];
+ x = (event->screen_width * ((ptr[3] << 8) + ptr[4])) / 0x0fff;
+ y = (event->screen_height* ((ptr[1] << 8) + ptr[2])) / 0x0fff;
+
+ if (event->min_x)
+ x = event->min_x - x;
+ if (event->min_y)
+ y = event->min_y - y;
+
+ event->action = cmd;
+ event->x = x;
+ event->y = y;
+
+ return 0;
+}
+
+
+/* The main routine for dynapro */
+static void *dynaproTouchEventThread(DirectThread *thread, void *driver_data)
+{
+ dynaproData *data = (dynaproData *) driver_data;
+
+ /* Read data */
+ while (1) {
+ DFBInputEvent evt;
+
+ if(dynaproGetEvent(data) == -1) {
+ continue;
+ }
+ direct_thread_testcancel(thread);
+
+ /* Dispatch axis */
+ evt.type = DIET_AXISMOTION;
+ evt.flags = DIEF_AXISABS;
+ evt.axis = DIAI_X;
+ evt.axisabs = data->x;
+ dfb_input_dispatch(data->device, &evt);
+
+ evt.type = DIET_AXISMOTION;
+ evt.flags = DIEF_AXISABS;
+ evt.axis = DIAI_Y;
+ evt.axisabs = data->y;
+ dfb_input_dispatch(data->device, &evt);
+
+ /* Dispatch touch event */
+ if (DYNAPRO_CMD_UNTOUCH == data->action)
+ evt.type = DIET_BUTTONRELEASE;
+ else
+ evt.type = DIET_BUTTONPRESS;
+
+ evt.flags = DIEF_NONE;
+ evt.button = DIBI_LEFT;
+
+ dfb_input_dispatch(data->device, &evt);
+ direct_thread_testcancel(thread);
+ }
+
+ return NULL;
+}
+
+
+/* exported symbols */
+static int driver_get_available( void )
+{
+ int fd;
+
+ fd = dynaproOpenDevice(DYNAPRO_DEVICE);
+ if (fd < 0) {
+ return 0;
+ }
+ close(fd);
+
+ return 1;
+}
+
+static void driver_get_info( InputDriverInfo *info )
+{
+ /* fill driver info structure */
+ snprintf(info->name, DFB_INPUT_DRIVER_INFO_NAME_LENGTH,
+ "dynapro" );
+ snprintf(info->vendor, DFB_INPUT_DRIVER_INFO_VENDOR_LENGTH,
+ "3M" );
+
+ info->version.major = 0;
+ info->version.minor = 1;
+}
+
+static DFBResult driver_open_device(CoreInputDevice *device,
+ unsigned int number,
+ InputDeviceInfo *info,
+ void **driver_data)
+{
+ int fd;
+ dynaproData *data;
+
+ /* open device */
+ fd = dynaproOpenDevice(DYNAPRO_DEVICE);
+ if(fd < 0) {
+ D_PERROR("DirectFB/dynapro: Error opening '"DYNAPRO_DEVICE"'!\n");
+ return DFB_INIT;
+ }
+
+ data = D_CALLOC(1, sizeof(dynaproData));
+ if (!data) {
+ tty_rawmode(fd, 0);
+ close(fd);
+ return D_OOM();
+ }
+
+ data->fd = fd;
+ data->device = device;
+
+ /* FIXME! Use settings instead? */
+ data->screen_width = DYNAPRO_SCREENWIDTH;
+ data->screen_height = DYNAPRO_SCREENHEIGHT;
+ data->min_x = DYNAPRO_MINX;
+ data->min_y = DYNAPRO_MINY;
+
+ /* fill device info structure */
+ snprintf(info->desc.name, DFB_INPUT_DEVICE_DESC_NAME_LENGTH,
+ "dynapro");
+ snprintf(info->desc.vendor, DFB_INPUT_DEVICE_DESC_VENDOR_LENGTH,
+ "3M");
+
+ 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;
+
+ /* start input thread */
+ data->thread = direct_thread_create(DTT_INPUT,
+ dynaproTouchEventThread,
+ data,
+ "Dynapro Touch 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)
+{
+ dynaproData *data = (dynaproData *)driver_data;
+
+ /* stop input thread */
+ direct_thread_cancel(data->thread);
+ direct_thread_join(data->thread);
+ direct_thread_destroy(data->thread);
+
+ /* restore termnial settings for the port */
+ tty_rawmode(data->fd, 0);
+
+ /* close device */
+ close(data->fd);
+
+ /* free private data */
+ D_FREE(data);
+}