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 \