File lirc-imontouch-0.2.4.patch of Package lirc-imontouch

diff -Naur lirc-0.8.5pre2/configure.ac lirc-0.8.5pre2-imontouch-0.2.4/configure.ac
--- lirc-0.8.5pre2/configure.ac	2009-03-31 14:23:00.000000000 -0500
+++ lirc-0.8.5pre2-imontouch-0.2.4/configure.ac	2009-04-18 18:12:08.000000000 -0500
@@ -164,6 +164,7 @@
 	(lirc_dev lirc_igorplugusb) \
 	(lirc_dev lirc_ttusbir) \
 	(lirc_dev lirc_imon) \
+	(lirc_dev lirc_imontouch) \
 	(lirc_dev lirc_it87) \
 	(lirc_dev lirc_ite8709) \
 	(lirc_dev lirc_mceusb) \
@@ -442,7 +443,7 @@
                           hercules_smarttv_stereo, i2cuser,
                           igorplugusb, iguanaIR, imon, imon_24g,
                           imon_knob, imon_lcd, imon_pad, imon_rsc,
-                          irdeo, irdeo_remote, irlink, irman, irreal,
+                          imontouch, irdeo, irdeo_remote, irlink, irman, irreal,
                           it87, ite8709, knc_one, kworld,
                           leadtek_0007, leadtek_0010, leadtek_pvr2000,
                           livedrive_midi, livedrive_seq, logitech,
@@ -599,6 +600,8 @@
 		;;
 	lirc_dev-lirc_imon)
 		;;
+	lirc_dev-lirc_imontouch)
+		;;
 	lirc_dev-lirc_it87)
 		;;
 	lirc_dev-lirc_ite8709)
@@ -1008,6 +1011,10 @@
   lircd_conf="imon/lircd.conf.imon"  
 fi
 
+if test "$driver" = "imontouch"; then
+  lirc_driver="lirc_dev lirc_imontouch"
+  lircd_conf="imon/lircd.conf.imon"  
+fi
 if test "$driver" = "imon_24g"; then
   lirc_driver="lirc_dev lirc_imon"
   lircd_conf="imon/lircd.conf.imon-2.4g"
@@ -1495,6 +1502,7 @@
 	lirc_i2c \
 	lirc_igorplugusb \
 	lirc_imon \
+	lirc_imontouch \
 	lirc_it87 \
 	lirc_ite8709 \
 	lirc_mceusb \
@@ -1771,6 +1779,7 @@
   drivers/lirc_igorplugusb/Makefile
   drivers/lirc_ttusbir/Makefile
   drivers/lirc_imon/Makefile
+  drivers/lirc_imontouch/Makefile
   drivers/lirc_it87/Makefile
   drivers/lirc_ite8709/Makefile
   drivers/lirc_mceusb/Makefile
diff -Naur lirc-0.8.5pre2/drivers/lirc_imon/lirc_imon.c lirc-0.8.5pre2-imontouch-0.2.4/drivers/lirc_imon/lirc_imon.c
--- lirc-0.8.5pre2/drivers/lirc_imon/lirc_imon.c	2009-03-08 14:46:55.000000000 -0500
+++ lirc-0.8.5pre2-imontouch-0.2.4/drivers/lirc_imon/lirc_imon.c	2009-04-18 18:12:08.000000000 -0500
@@ -181,8 +181,6 @@
 	{ USB_DEVICE(0x15c2, 0xffda) },
 	/* iMON USB Control Board (IR & LCD) *and* iMON Knob (IR only) */
 	{ USB_DEVICE(0x15c2, 0xffdc) },
-	/* iMON USB Control Board (IR & LCD) */
-	{ USB_DEVICE(0x15c2, 0x0034) },
 	/* iMON USB Control Board (IR & VFD) */
 	{ USB_DEVICE(0x15c2, 0x0036) },
 	/* iMON USB Control Board (IR & LCD) */
@@ -204,7 +202,6 @@
 static struct usb_device_id display_proto_6p_list[] = {
 	{ USB_DEVICE(0x15c2, 0xffda) },
 	{ USB_DEVICE(0x15c2, 0xffdc) },
-	{ USB_DEVICE(0x15c2, 0x0034) },
 	{ USB_DEVICE(0x15c2, 0x0036) },
 	{ USB_DEVICE(0x15c2, 0x0038) },
 	{ USB_DEVICE(0x15c2, 0x0041) },
@@ -219,7 +216,6 @@
 
 /* newer iMON models use control endpoints */
 static struct usb_device_id ctl_ep_device_list[] = {
-	{ USB_DEVICE(0x15c2, 0x0034) },
 	{ USB_DEVICE(0x15c2, 0x0036) },
 	{ USB_DEVICE(0x15c2, 0x0038) },
 	{ USB_DEVICE(0x15c2, 0x0041) },
@@ -233,7 +229,6 @@
 /* iMON LCD models use a different write op */
 static struct usb_device_id lcd_device_list[] = {
 	{ USB_DEVICE(0x15c2, 0xffdc) },
-	{ USB_DEVICE(0x15c2, 0x0034) },
 	{ USB_DEVICE(0x15c2, 0x0038) },
 	{ USB_DEVICE(0x15c2, 0x0045) },
 	{}
@@ -248,7 +243,6 @@
 /* Newer iMON models decode the signal onboard */
 static struct usb_device_id ir_onboard_decode_list[] = {
 	{ USB_DEVICE(0x15c2, 0xffdc) },
-	{ USB_DEVICE(0x15c2, 0x0034) },
 	{ USB_DEVICE(0x15c2, 0x0036) },
 	{ USB_DEVICE(0x15c2, 0x0038) },
 	{ USB_DEVICE(0x15c2, 0x0041) },
diff -Naur lirc-0.8.5pre2/drivers/lirc_imontouch/lirc_imontouch.c lirc-0.8.5pre2-imontouch-0.2.4/drivers/lirc_imontouch/lirc_imontouch.c
--- lirc-0.8.5pre2/drivers/lirc_imontouch/lirc_imontouch.c	1969-12-31 18:00:00.000000000 -0600
+++ lirc-0.8.5pre2-imontouch-0.2.4/drivers/lirc_imontouch/lirc_imontouch.c	2009-04-18 18:18:59.000000000 -0500
@@ -0,0 +1,813 @@
+/*
+    lirc_imontouch - LIRC plugin and input device driver for the Soundgraph iMON Touch LCD and remote control
+    Copyright (C) 2008 Rene Harder (rehar@saweb.de)
+                 based on lirc_imon by Venky Raju(dev@venky.ws) http://www.venky.ws/projects/imon
+   
+    lirc_imontouch is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+   
+    This program 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 General Public License for more details.
+   
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <linux/version.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include <linux/autoconf.h>
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/usb/input.h>
+#include <linux/timer.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#include <asm/uaccess.h>
+#else
+#include <linux/uaccess.h>
+#endif
+
+#include <linux/usb.h>
+
+#include <drivers/kcompat.h>
+#include <drivers/lirc.h>
+#include <drivers/lirc_dev/lirc_dev.h>
+
+#define MOD_AUTHOR   "Rene Harder <rehar@saweb.de>"
+#define MOD_DESC   "Driver for Soundgraph iMON Touch LCD and Remote Control iMON PAD"
+#define MOD_NAME   "lirc_imontouch"
+#define MOD_VERSION   "0.2.4"
+
+#define BUF_CHUNK_SIZE   8
+#define BUF_SIZE   128
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+#define BIT_MASK(nr) BIT(nr)
+#define BIT_WORD(nr) LONG(nr)
+#endif
+
+#define TRUE       1
+#define FALSE      0
+
+/*Prototypes*/
+
+static int imontouch_probe(struct usb_interface *interface, const struct usb_device_id *id);
+static void imontouch_disconnect(struct usb_interface *interface);
+
+static void usb_rx_callback_intf0(struct urb *urb);
+static void usb_rx_callback_intf1(struct urb *urb);
+
+
+static int lircdev_open(void *data);
+static void lircdev_close(void *data);
+
+/*Module init and exit */
+static int __init imontouch_init(void);
+static void __exit imontouch_exit(void);
+struct mutex lock;
+
+/* Globals*/
+
+
+struct imontouch_context {
+   struct usb_device *dev_intf0; /*display has two USB interfaces*/
+   struct usb_device *dev_intf1;
+   int lirc_isopen;         /* LIRC port open   */
+   int lirc_isassociating;      /* LIRC port open for association */
+   int dev_present_intf0;      /* USB interface 0 presence */
+   int dev_present_intf1;      /* USB interface 1 presence */
+   struct mutex lock;      /* to lock this object */
+
+
+   struct lirc_driver *driver;
+   struct usb_endpoint_descriptor *rx_endpoint_intf0, *rx_endpoint_intf1;
+   struct urb *rx_urb_intf0, *rx_urb_intf1;
+
+   unsigned char usb_rx_buf[8];
+
+   struct rx_data {
+      int count;      /* length of 0 or 1 sequence */
+      int prev_bit;      /* logic level of sequence */
+      int initial_space;   /* initial space flag */
+   } rx;
+   struct input_dev *mouse;
+   struct input_dev *touch;
+   int is_mouse;
+   int touch_x;
+   int touch_y;
+   char name[128];
+   char phys[64];
+   char touch_name[128];
+   char touch_phys[64];
+   struct timer_list timer;
+};
+
+#define LOCK_CONTEXT   mutex_lock(&context->lock)
+#define UNLOCK_CONTEXT   mutex_unlock(&context->lock)
+#define LOCK_DRIVER   mutex_lock(&lock)
+#define UNLOCK_DRIVER   mutex_unlock(&lock)
+#define TOUCH_TIMEOUT 	(HZ/30)
+
+static struct usb_device_id imontouch_usb_id_table[] = {
+   /*SoundGraph iMON Touch LCD 7" */   
+   { USB_DEVICE(0x15c2, 0x0034) },
+   /*SoundGraph iMON Touch LCD 4.3" */   
+   { USB_DEVICE(0x15c2, 0x0035) },
+   {}
+};
+
+/* USB Device data */
+static struct usb_driver imontouch_driver = {
+   LIRC_THIS_MODULE(.owner = THIS_MODULE)
+   .name      = MOD_NAME,
+   .probe      = imontouch_probe,
+   .disconnect   = imontouch_disconnect,
+   .id_table   = imontouch_usb_id_table,
+};
+
+static int debug;
+static int use_lirc;
+static int touch_passthrough;
+static int mouse;
+
+/* Module */
+
+MODULE_AUTHOR(MOD_AUTHOR);
+MODULE_DESCRIPTION(MOD_DESC);
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(usb, imontouch_usb_id_table);
+
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes(default: no)");
+
+/*module_param(use_lirc, int, 1);
+MODULE_PARM_DESC(use_lirc, "Use LIRC device as output for RC and Touchscreen: 0=no, 1=yes(default: yes) (not yet active");*/
+
+module_param(touch_passthrough, int, 0);
+MODULE_PARM_DESC(touch_passthrough, "passtrough the raw touchscreen data, otherwise make a lower resolution matrix for LIRC: 0=no, 1=yes (raw touchscreen data) default:no");
+
+module_param(mouse, int, 0);
+MODULE_PARM_DESC(mouse, "Use the PAD on the remote as mouse pointer after probing the device: 1=yes, 0=no (default: no)");
+
+
+static inline void delete_context(struct imontouch_context *context)
+{
+   
+   lirc_buffer_free(context->driver->rbuf);
+   kfree(context->driver->rbuf);
+   kfree(context->driver);
+   kfree(context);
+   kfree(context->mouse);
+   kfree(context->touch);
+
+   if (debug)
+      printk(KERN_INFO "%s: context deleted\n", __FUNCTION__);
+}
+static inline void deregister_from_lirc(struct imontouch_context *context)
+{
+   int retval;
+   int minor = context->driver->minor;
+
+   retval = lirc_unregister_driver(minor);
+   if (retval)
+      printk(KERN_ERR "%s: unable to deregister from lirc(%d)\n",
+         __FUNCTION__, retval);
+   else
+      printk(KERN_INFO "%s: Deregistered iMON driver(minor:%d)\n", __FUNCTION__, minor);
+
+}
+
+static inline void incoming_lirc_packet(struct imontouch_context *context,  struct urb *urb, int intf){
+   int len = urb->actual_length;
+   unsigned char *buf = urb->transfer_buffer;
+   char rel_x, rel_y;
+
+   if(!context->is_mouse){
+      /* generated PAD key codes:
+         Mouse_N                  0x69 02 81 B7 00 68 1401
+         Mouse_S                  0x68 82 91 B7 00 68 1401
+         Mouse_W                  0x6A 82 81 B7 00 68 1401
+         Mouse_E                  0x68 8A 81 B7 00 68 1401
+         mouse buttons :
+         MouseRightClick          0x68 84 81 B7 00 68 1401
+         MouseLeftClick           0x68 83 81 B7 00 68 1401
+      */
+      if(buf[0] & 0x01  && !buf[1] && len==5){
+      rel_x=buf[2];
+      rel_y=buf[3];
+      len=8;
+         if (abs(abs(rel_x) - abs(rel_y)) < 10)
+            return;   
+         if(rel_x >= 14)
+            {buf[0]=0x68; buf[1]=0x8A;buf[2]=0x1B;buf[3]=0xb7;buf[4]=0x00;buf[5]=0x68;buf[6]=0x14;buf[7]=0x01;}
+         else if (rel_x <= -14)
+            {buf[0]=0x6a; buf[1]=0x82;buf[2]=0x81;buf[3]=0xB7;buf[4]=0x00;buf[5]=0x68;buf[6]=0x14;buf[7]=0x01;}
+         else if (rel_y >= 14)
+            {buf[0]=0x68; buf[1]=0x82;buf[2]=0x91;buf[3]=0xB7;buf[4]=0x00;buf[5]=0x68;buf[6]=0x14;buf[7]=0x01;}
+         else if (rel_y <= -14)
+            {buf[0]=0x69; buf[1]=0x02;buf[2]=0x81;buf[3]=0x70;buf[4]=0x00;buf[5]=0x68;buf[6]=0x14;buf[7]=0x01;}
+      
+        }else if (buf[0] & 0x01  && buf[1]==0x01 && len==5){ //left mouse click
+		len=8;
+		buf[0]=0x68; buf[1]=0x83;buf[2]=0x81;buf[3]=0xB7;buf[4]=0x00;buf[5]=0x68;buf[6]=0x14;buf[7]=0x01;
+	}else if (buf[0] & 0x01  && buf[1]==0x02 && len==5){ //right mouse click
+		len=8;
+		buf[0]=0x68; buf[1]=0x84;buf[2]=0x81;buf[3]=0xB7;buf[4]=0x00;buf[5]=0x68;buf[6]=0x14;buf[7]=0x01;
+	}
+      
+      }
+   if (len == 5) {
+      buf[5]=0x00;
+      buf[6]=0x00;
+      buf[7]=0x00;
+      len=8;
+   }
+   if (len != 8) {
+      printk(KERN_WARNING "%s: invalid incoming packet size(%d)\n",
+           __FUNCTION__, len);
+      return;
+   }
+   if (!buf[1] && !buf[2] && !buf[3] && !buf[4] && !buf[5] && !buf[6]  && !buf[7] && !intf )
+      return;
+   if (((buf[2]>>6) & 0x01) && intf && (buf[7] != 0x86))
+      return;
+   if((buf[6]==0x14 || buf[6]==0x03) && buf[7]==0x86 && intf){ /*handle touchscreen, generate button events for LIRC, in lower resolution */
+      if (!touch_passthrough){
+         /*generate higher resolution touchscreen to generate button events (256 buttons)
+        buf[0]=buf[0]>>4; buf[1]=0x00;buf[2]=buf[2]>>4;buf[3]=0x00;buf[4]=0x00;buf[5]=0x00;buf[6]=0x14;buf[7]=0xff;   */
+
+        /*generate lower resolution touchscreen to generate button events (64 buttons)*/
+        buf[0]=buf[0]>>5; buf[1]=0x00;buf[2]=buf[2]>>5;buf[3]=0x00;buf[4]=0x00;buf[5]=0x00;buf[6]=0x14;buf[7]=0xff;
+      }
+   }
+   lirc_buffer_write(context->driver->rbuf, buf);
+   wake_up(&context->driver->rbuf->wait_poll);
+   return;
+
+
+}
+
+static void display_timeout(struct imontouch_context *context){
+	struct input_dev *touch=NULL;
+
+	touch = context->touch;	
+	if (!context->touch) /*no touchscreen input generated, something went wrong*/
+		return;
+	input_report_abs(touch, ABS_X, context->touch_x);
+	input_report_abs(touch, ABS_Y, context->touch_y);
+	input_report_key(touch, BTN_TOUCH, 0x00);
+	input_sync(touch);
+}
+
+static void usb_rx_callback_intf0(struct urb *urb){
+   struct imontouch_context *context;
+   unsigned char *buf = urb->transfer_buffer;
+     char rel_x, rel_y;
+   int len = urb->actual_length;
+   struct input_dev *mouse=NULL;
+   int i;
+     
+   if (len == 5) {
+      buf[5]=0x00;
+      buf[6]=0x00;
+      buf[7]=0x00;
+      len=8;
+   }
+   if (len != 8) {
+      printk(KERN_WARNING "%s: invalid incoming packet size(%d)\n",
+           __FUNCTION__, len);
+      return;
+   }  
+   if(debug){
+           printk(KERN_INFO "lirc_imontouch %s incomming packet: ",__FUNCTION__ );
+           for(i=0;i<8;i++)
+           {
+                    printk("%02x ",buf[i]);
+           }
+		   printk("\n");
+     }	    
+     if (!urb)
+        return;
+   
+   context = (struct imontouch_context *) urb->context;
+   
+     if (!context){
+      
+        goto exit;
+   }
+   mouse = context->mouse;
+
+   if (!context->mouse){ /*no mouse input generated, something went wrong*/
+      
+        goto exit;
+   }
+   switch (urb->status){
+
+   case -ENOENT:   /* usb unlink*/
+	  if(debug) printk(KERN_WARNING "%s: usb unlink\n",__FUNCTION__);
+      
+      return;
+   case 0:
+
+                       
+      if(buf[0] & 0x01  && context->is_mouse){ /* handle iIMON PAD to generate mouse events*/
+
+         input_report_key(mouse, BTN_LEFT,   buf[1] & 0x01);
+         input_report_key(mouse, BTN_RIGHT,  buf[1] >> 2 & 0x01);
+         rel_x=buf[2];
+         rel_y=buf[3];
+         
+         input_report_rel(mouse, REL_X,     rel_x);
+         input_report_rel(mouse, REL_Y,     rel_y);
+         input_sync(mouse);
+      }else{
+         if (context->lirc_isopen)
+            incoming_lirc_packet(context, urb,0);
+
+         
+      }
+      break;
+   default :
+      printk(KERN_WARNING "%s unknown urb status\n", __FUNCTION__);
+      break;
+   }
+exit:
+   usb_submit_urb(context->rx_urb_intf1, GFP_ATOMIC);
+   usb_submit_urb(context->rx_urb_intf0, GFP_ATOMIC);
+   
+}
+
+static void usb_rx_callback_intf1(struct urb *urb){
+   struct imontouch_context *context;
+   unsigned char *buf = urb->transfer_buffer;
+   int len = urb->actual_length;
+   struct input_dev *touch=NULL;
+   int i;
+   
+   if (len != 8) {
+      printk(KERN_WARNING "%s: invalid incoming packet size(%d)\n",
+           __FUNCTION__, len);
+      return;
+   }   
+      if(debug){
+           printk("lirc_imontouch %s incomming packet: ",__FUNCTION__ );
+           for(i=0;i<8;i++)
+           {
+                    printk("%02x ",buf[i]);
+           }
+		   printk("\n");
+     }
+   if (!urb)
+        return;
+   
+     context = (struct imontouch_context *) urb->context;
+     if (!context){
+      
+        goto exit;
+   }
+   touch = context->touch;   
+   if (!context->touch){ /*no touchscreen input generated, something went wrong*/
+      
+        goto exit;
+   }
+
+   switch (urb->status){
+
+   case -ENOENT:   /* usb unlink*/
+      if(debug) printk(KERN_WARNING "%s: usb unlink\n",__FUNCTION__);
+
+      return;
+   case 0:
+
+      if(buf[0] ==0x29 && buf[1]==0x91 && (buf[2]==0x35 || buf[2]==0x15) && buf[3]==0xb7 && !buf[4] && !buf[5] &&(buf[6]==0x14 || buf[6]==0x03) && buf[7]==0x01 ){ /*switch mouse/keyboard*/
+         context->is_mouse= (~context->is_mouse) & 0x01;
+         if(debug)
+                  printk(KERN_INFO "%s: toggle mouse %d\n",__FUNCTION__,context->is_mouse);
+                  
+         goto exit;
+         
+      }
+      
+      if((buf[6]==0x14 || buf[6]==0x03) && buf[7]==0x86){ /*handle touchscreen, map to input device */
+
+			mod_timer(&context->timer,jiffies+TOUCH_TIMEOUT);
+
+			context->touch_x=buf[0]<<4 | (buf[1]>>4);
+			context->touch_y=0xfff-((buf[2]<<4) | (buf[1]&0xf));
+			
+			input_report_abs(touch, ABS_X, context->touch_x);
+			input_report_abs(touch, ABS_Y, context->touch_y);
+			input_report_key(touch, BTN_TOUCH, 0x01);
+			input_sync(touch);
+      }
+      if (context->lirc_isopen)
+         incoming_lirc_packet(context, urb,1);
+
+         
+      break;
+   default :
+      printk(KERN_WARNING "%s: unknown urb status\n", __FUNCTION__);
+      break;
+   }
+exit:
+   usb_submit_urb(context->rx_urb_intf1, GFP_ATOMIC);
+   usb_submit_urb(context->rx_urb_intf0, GFP_ATOMIC);
+   
+}
+
+
+static int imontouch_probe(struct usb_interface *interface, const struct usb_device_id *id){
+   
+   struct usb_device *dev = NULL;
+   struct usb_host_interface *iface_desc = NULL;
+   struct urb *rx_urb = NULL;
+   struct lirc_driver *driver = NULL;
+   struct lirc_buffer *rbuf = NULL;
+   struct usb_interface *first_if;
+   int ifnum;
+   int err;
+   int lirc_minor=-1;
+   int retval;
+   int minor_first_intf=-1;
+   int num_endpoints;
+   int alloc_status;
+   struct imontouch_context *context = NULL;
+   struct imontouch_context *first_if_context=NULL;
+   
+   dev = usb_get_dev(interface_to_usbdev(interface));
+   iface_desc = interface->cur_altsetting;
+   num_endpoints = iface_desc->desc.bNumEndpoints;
+   ifnum=iface_desc->desc.bInterfaceNumber;
+   printk(KERN_INFO "%s: found iIMON device, %d. interface\n", __FUNCTION__, ifnum);
+   
+   alloc_status=0;
+   if(!ifnum)
+     first_if=usb_ifnum_to_if(dev,1);
+   else
+     first_if=usb_ifnum_to_if(dev,0);
+
+   LOCK_DRIVER;
+
+   first_if_context=(struct imontouch_context *)usb_get_intfdata(first_if);
+   
+   if(!first_if_context){
+      printk(KERN_INFO "%s: first usb interface not yet registered\n", __FUNCTION__);
+      
+      context = kzalloc(sizeof(struct imontouch_context), GFP_KERNEL);
+      if (!context) {
+         printk(KERN_ERR "%s: kzalloc failed for context\n", __FUNCTION__);
+         alloc_status = 1;
+         goto alloc_status_switch;
+      }
+      driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
+      if (!driver) {
+         printk(KERN_ERR "%s: kzalloc failed for lirc_driver\n", __FUNCTION__);
+         alloc_status = 2;
+         goto alloc_status_switch;
+      }
+      rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
+      if (!rbuf) {
+         printk(KERN_ERR "%s: kzalloc failed for lirc_buffer\n", __FUNCTION__);
+         alloc_status = 3;
+         goto alloc_status_switch;
+      }
+      if (lirc_buffer_init(rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) {
+         printk(KERN_ERR "%s: lirc_buffer_init failed", __FUNCTION__);
+         alloc_status = 4;
+         goto alloc_status_switch;
+      }
+      
+      rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+      if (!rx_urb) {
+         printk(KERN_ERR "%s: usb_alloc_urb failed for IR urb\n", __FUNCTION__);
+         alloc_status = 5;
+         goto alloc_status_switch;
+      }
+       
+   
+      memset(context, 0, sizeof(struct imontouch_context));
+      mutex_init(&context->lock);
+
+      memset(driver, 0, sizeof(struct lirc_driver));
+   
+      strcpy(driver->name, MOD_NAME);
+      driver->minor = -1;
+      driver->code_length = 64;
+      driver->sample_rate = 0;
+      driver->features = LIRC_CAN_REC_LIRCCODE;
+      driver->data = context;
+      driver->rbuf = rbuf;
+      driver->set_use_inc = lircdev_open;
+      driver->set_use_dec = lircdev_close;
+      context->lirc_isopen=0;
+      driver->owner = THIS_MODULE;
+      LOCK_CONTEXT;
+      context->driver = driver;
+      context->is_mouse=mouse;
+      init_timer(&context->timer);
+      context->timer.data=(unsigned long)context;
+      context->timer.function=display_timeout;
+      
+      lirc_minor = lirc_register_driver(driver);
+      if (lirc_minor < 0) {
+         printk(KERN_ERR "%s: lirc_register_driver failed\n", __FUNCTION__);
+         alloc_status = 5;
+         UNLOCK_CONTEXT;
+         goto alloc_status_switch;
+      } else
+         printk(KERN_INFO "%s: Registered imontouch driver(minor:%d)\n",__FUNCTION__, lirc_minor);
+
+      driver->minor = lirc_minor;
+      UNLOCK_CONTEXT;
+      
+
+      
+   }else{
+          if(first_if_context->driver){
+         minor_first_intf=first_if_context->driver->minor;
+         printk(KERN_INFO "%s: driver dectected, LIRC minor: %d\n", __FUNCTION__,minor_first_intf);
+         
+         rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+         if (!rx_urb) {
+            printk(KERN_ERR "%s: usb_alloc_urb failed for urb\n", __FUNCTION__);
+            alloc_status = 5;
+            goto alloc_status_switch;
+         }
+         
+         context=first_if_context;
+         
+         }
+   }
+   
+   printk(KERN_INFO "%s: imontouch device connected, minor %d\n", __FUNCTION__, context->driver->minor);
+   LOCK_CONTEXT;
+   if(!ifnum)  {
+      context->dev_intf0 = dev;
+      context->dev_present_intf0 = TRUE;
+      context->rx_urb_intf0 = rx_urb;
+      context->rx_endpoint_intf0= &iface_desc->endpoint[0].desc;
+
+      
+      usb_fill_int_urb(rx_urb, context->dev_intf0, usb_rcvintpipe(context->dev_intf0,   context->rx_endpoint_intf0->bEndpointAddress), context->usb_rx_buf, sizeof(context->usb_rx_buf),usb_rx_callback_intf0, context, context->rx_endpoint_intf0->bInterval);
+      retval = usb_submit_urb(context->rx_urb_intf0, GFP_KERNEL);
+      context->mouse= input_allocate_device();
+      snprintf(context->name, sizeof(context->name), "iMON PAD IR Mouse %04x:%04x", le16_to_cpu(dev->descriptor.idVendor), le16_to_cpu(dev->descriptor.idProduct));
+      usb_make_path(dev, context->phys, sizeof(context->phys));
+      strlcat(context->phys, "/input0", sizeof(context->phys));
+
+      context->mouse->phys=context->phys;
+      context->mouse->name=context->name;
+      context->mouse->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+      context->mouse->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
+      context->mouse->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+      context->mouse->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA);
+      context->mouse->relbit[0] |= BIT_MASK(REL_WHEEL);
+
+      usb_to_input_id(dev, &context->mouse->id);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
+	context->mouse->private = context;
+	context->mouse->cdev.dev = &interface->dev;
+#else
+      input_set_drvdata(context->mouse, context);
+      context->mouse->dev.parent = &interface->dev;
+#endif
+      input_register_device(context->mouse);
+      
+      
+
+   }else{
+      context->dev_intf1 = dev;
+      context->dev_present_intf1 = TRUE;
+      context->rx_urb_intf1 = rx_urb;
+      context->rx_endpoint_intf1= &iface_desc->endpoint[0].desc;
+
+      usb_fill_int_urb(rx_urb, context->dev_intf1, usb_rcvintpipe(context->dev_intf1,   context->rx_endpoint_intf1->bEndpointAddress), context->usb_rx_buf, sizeof(context->usb_rx_buf),usb_rx_callback_intf1, context, context->rx_endpoint_intf1->bInterval);
+      retval = usb_submit_urb(context->rx_urb_intf1, GFP_KERNEL);
+
+      context->touch= input_allocate_device();
+      snprintf(context->touch_name, sizeof(context->touch_name), "USB Touchscreen %04x:%04x", le16_to_cpu(dev->descriptor.idVendor), le16_to_cpu(dev->descriptor.idProduct));
+      usb_make_path(dev, context->touch_phys, sizeof(context->touch_phys));
+      strlcat(context->touch_phys, "/input1", sizeof(context->touch_phys));
+
+      context->touch->phys=context->touch_phys;
+      context->touch->name=context->touch_name;
+      context->touch->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+      context->touch->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+      input_set_abs_params(context->touch, ABS_X, 0x00, 0xfff, 0, 0);
+      input_set_abs_params(context->touch, ABS_Y, 0x00, 0xfff, 0, 0);
+ 
+      usb_to_input_id(dev, &context->touch->id);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
+      context->touch->private = context;
+      context->touch->cdev.dev = &interface->dev;
+#else
+      input_set_drvdata(context->touch, context);
+      context->touch->dev.parent = &interface->dev;
+#endif
+      err=input_register_device(context->touch);
+   
+      if (err) {
+         printk(KERN_ERR "%s: input_register touchscreen failed, err: %d\n", __FUNCTION__, err);
+         
+      }
+   }
+   //context->rx_endpoint = rx_endpoint;
+   
+   if (retval)
+        printk(KERN_ERR "%s: usb_submit_urb failed for module probe (%d)\n",
+             __FUNCTION__, retval);
+     
+
+
+   usb_set_intfdata(interface, context);
+
+   UNLOCK_CONTEXT;
+
+alloc_status_switch:
+
+   switch (alloc_status) {
+   case 5:
+      lirc_buffer_free(rbuf);
+   case 4:
+      kfree(rbuf);
+   case 3:
+      kfree(driver);
+   case 2:
+      kfree(context);
+      context = NULL;
+   case 1:
+      retval = -ENOMEM;
+   case 0:
+      ;
+   }
+
+
+UNLOCK_DRIVER;   
+return 0;   
+}
+
+
+static void imontouch_disconnect(struct usb_interface *interface){
+   struct imontouch_context *context;
+   int ifnum;
+   /* prevent races with ir_open()/vfd_open() */
+   LOCK_DRIVER;
+
+
+   context = usb_get_intfdata(interface);
+   ifnum=interface->cur_altsetting->desc.bInterfaceNumber;
+   LOCK_CONTEXT;
+
+
+   if(!ifnum){
+      
+      context->dev_present_intf0 = FALSE;
+      usb_kill_urb(context->rx_urb_intf0);
+      input_unregister_device (context->mouse);
+      if (context->dev_present_intf1){
+         if(debug)   
+            printk(KERN_INFO "%s: interface 1 still activated\n", __FUNCTION__);
+         
+         UNLOCK_CONTEXT;
+         
+      }else{
+         /* De-register from lirc_dev if IR port is not open */
+         if (!context->lirc_isopen)
+            deregister_from_lirc(context);
+            
+         del_timer_sync(&context->timer);
+         UNLOCK_CONTEXT;
+
+         printk(KERN_INFO "%s: imontouch device disconnected\n", __FUNCTION__);
+      }
+   }else{
+
+      context->dev_present_intf1 = FALSE;
+      usb_kill_urb(context->rx_urb_intf1);
+      input_unregister_device (context->touch);
+      if (context->dev_present_intf0){
+         if(debug)
+            printk(KERN_INFO "%s: interface 0 still activated\n", __FUNCTION__);
+         UNLOCK_CONTEXT;
+         
+      }else{
+         /* De-register from lirc_dev if IR port is not open */
+         if (!context->lirc_isopen)
+            deregister_from_lirc(context);
+            
+         del_timer_sync(&context->timer);                        
+         UNLOCK_CONTEXT;
+
+         printk(KERN_INFO "%s: imontouch device disconnected\n", __FUNCTION__);
+      }
+
+
+
+
+
+   }
+   
+
+   usb_set_intfdata(interface, NULL);   
+   UNLOCK_DRIVER;
+
+}
+
+static int lircdev_open(void *data){
+   struct imontouch_context *context;
+   int retval = 0;
+
+   LOCK_DRIVER;
+   context = (struct imontouch_context *) data;
+   LOCK_CONTEXT;
+
+   if (context->lirc_isopen) {
+      printk(KERN_ERR "%s: LIRC port is already open\n", __FUNCTION__);
+      retval = -EBUSY;
+      goto exit;
+   }
+   /* initial IR protocol decode variables */
+   context->rx.count = 0;
+   context->rx.initial_space = 1;
+   context->rx.prev_bit = 0;
+   MOD_INC_USE_COUNT;
+   context->lirc_isopen = TRUE;
+   printk(KERN_INFO "%s: LIRC port opened\n", __FUNCTION__);
+
+
+exit:
+   UNLOCK_CONTEXT;
+   UNLOCK_DRIVER;
+   return retval;
+
+
+};
+static void lircdev_close(void *data){
+struct imontouch_context *context;
+
+   context = (struct imontouch_context *) data;
+   if (!context) {
+      printk(KERN_ERR "%s: no context for device\n", __FUNCTION__);
+      return;
+   }
+   LOCK_CONTEXT;
+   context->lirc_isopen = FALSE;
+   printk(KERN_INFO "%s: LIRC port closed\n", __FUNCTION__);
+   MOD_DEC_USE_COUNT;
+   
+
+   if (!context->dev_present_intf0 & !context->dev_present_intf1) {
+      /* Device disconnected while LIRC port was
+       * still open. Driver was not deregistered
+       * at disconnect time, so do it now. */
+      usb_kill_urb(context->rx_urb_intf1);
+      input_unregister_device (context->touch);
+      usb_kill_urb(context->rx_urb_intf0);
+      input_unregister_device (context->mouse);
+      deregister_from_lirc(context);
+   }
+
+
+   UNLOCK_CONTEXT;
+   return;
+
+};
+
+static int __init imontouch_init(void)
+{
+   int resource;
+
+   printk(KERN_INFO MOD_DESC ", v" MOD_VERSION "\n");
+   printk(KERN_INFO MOD_AUTHOR "\n");
+   mutex_init(&lock);
+   resource = usb_register(&imontouch_driver);
+   if (resource) {
+      printk(KERN_ERR "%s: usb register failed(%d)\n", __FUNCTION__, resource);
+      return -ENODEV;
+   }
+   return 0;
+}
+
+static void __exit imontouch_exit(void)
+{
+   usb_deregister(&imontouch_driver);
+   printk(KERN_INFO "%s: module removed.\n", __FUNCTION__);
+}
+
+
+module_init(imontouch_init);
+module_exit(imontouch_exit);
diff -Naur lirc-0.8.5pre2/drivers/lirc_imontouch/Makefile.am lirc-0.8.5pre2-imontouch-0.2.4/drivers/lirc_imontouch/Makefile.am
--- lirc-0.8.5pre2/drivers/lirc_imontouch/Makefile.am	1969-12-31 18:00:00.000000000 -0600
+++ lirc-0.8.5pre2-imontouch-0.2.4/drivers/lirc_imontouch/Makefile.am	2009-04-18 18:12:08.000000000 -0500
@@ -0,0 +1,13 @@
+## $Id: Makefile.am,v 1.1 2005/01/26 20:07:28 lirc Exp $
+
+## Process this file with automake to produce Makefile.in
+
+## this is so that Automake includes the C compiling definitions, and
+## includes the source files in the distribution.
+EXTRA_PROGRAMS = automake_dummy
+automake_dummy_SOURCES = lirc_imontouch.c
+
+## there is no *just* object file support in automake.  This is close enough
+module_DATA = lirc_imontouch.o
+
+include ../Makefile.common
diff -Naur lirc-0.8.5pre2/drivers/Makefile.am lirc-0.8.5pre2-imontouch-0.2.4/drivers/Makefile.am
--- lirc-0.8.5pre2/drivers/Makefile.am	2009-03-01 13:22:39.000000000 -0600
+++ lirc-0.8.5pre2-imontouch-0.2.4/drivers/Makefile.am	2009-04-18 18:12:08.000000000 -0500
@@ -15,6 +15,7 @@
 	lirc_i2c \
 	lirc_igorplugusb \
 	lirc_imon \
+	lirc_imontouch \
 	lirc_it87 \
 	lirc_ite8709 \
 	lirc_mceusb \
diff -Naur lirc-0.8.5pre2/setup.data lirc-0.8.5pre2-imontouch-0.2.4/setup.data
--- lirc-0.8.5pre2/setup.data	2009-03-01 13:22:39.000000000 -0600
+++ lirc-0.8.5pre2-imontouch-0.2.4/setup.data	2009-04-18 18:12:08.000000000 -0500
@@ -136,6 +136,7 @@
 	alsa_usb: "Sound Blaster Extigy/Audigy 2 NX (ALSA snd-usb-audio)"
 	imon_24g: "Soundgraph iMON 2.4G DT & LT"
 	imon: "Soundgraph iMON MultiMedian IR/VFD"
+	imontouch: "Soundgraph iMON Touch LCD"
 	imon_lcd: "Soundgraph iMON IR/LCD"
 	imon_knob: "Soundgraph iMON Knob"
 	imon_pad: "Soundgraph iMON PAD IR/VFD"
@@ -228,6 +229,7 @@
 	igorplugusb \
 	iguanaIR \
 	imon \
+	imontouch \
 	imon_lcd \
 	imon_24g \
 	imon_knob \
@@ -301,6 +303,7 @@
 	igorplugusb \
 	iguanaIR \
 	imon \
+	imontouch \
 	imon_lcd \
 	imon_24g \
 	imon_knob \
openSUSE Build Service is sponsored by