First, credit where credit is due:
* Venky, for putting his time and energy into developing and maintaining the driver for all of us
* Vojtech Pavlik for his eminently readable usbmouse.c HID mouse driver, from which this is derived
I have tested this patch, and know the following to be true:
* This patch fixes the ugly module unload error relating to usb_unlink_urb
* The PAD and the L and R mouse click do not generate lirc events
* The PAD and the L and R mouse click DO generate output on /dev/input/mice
* The PAD and the L and R mouse click DO work under Xorg set to read from /dev/input/mice on my system
Caveats:
* Mouse only works while a lirc client is connected
Some things on my TODO list:
* make the input system hijack lirc events dependent on a module option ( or the mouse/keyboard button)
* allow volume/channel +/- buttons to be used as scroll wheel or additional mouse buttons
* make it possible to have certain other buttons emit keyboard codes (escape, tab, shift+tab, backspace, numbers, etc)
lirc_imon_plus_mouse.patch
- Code: Select all
--- lirc_imon-0.7.1.c 2005-06-21 22:25:08.000000000 -0500
+++ lirc_imon-exp.c 2005-06-21 22:27:14.000000000 -0500
@@ -53,6 +53,7 @@
#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/input.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -161,6 +162,8 @@
atomic_t busy; /* write in progress */
int status; /* status of tx completion */
} tx;
+
+ struct input_dev mouse;
};
#define LOCK_CONTEXT down (&context ->sem)
@@ -616,7 +619,7 @@
LOCK_CONTEXT;
- usb_unlink_urb (context ->rx_urb);
+ usb_kill_urb (context ->rx_urb);
context ->ir_isopen = FALSE;
MOD_DEC_USE_COUNT;
info ("IR port closed");
@@ -700,11 +703,28 @@
#endif
if (context ->ir_onboard_decode) {
-
- /* The signals have been decoded onboard the iMON controller */
-
- lirc_buffer_write_1 (context ->plugin ->rbuf, buf);
- wake_up (&context ->plugin ->rbuf ->wait_poll);
+ if(buf[0] & 0x40) {
+ struct input_dev *mouse = &context->mouse;
+ char rel_x = 0, rel_y = 0;
+ rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 | (buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6;
+ rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 | (buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6;
+ if(buf[0] & 0x02) rel_x |= ~0x10+1;
+ if(buf[0] & 0x01) rel_y |= ~0x10+1;
+
+ input_report_key(mouse, BTN_LEFT, buf[1] & 0x01);
+ input_report_key(mouse, BTN_RIGHT, buf[1] >> 2 & 0x01);
+ /*input_report_key(mouse, BTN_MIDDLE, buf[0] & 0x04);*/
+ /*input_report_key(mouse, BTN_SIDE, buf[0] & 0x08);*/
+ /*input_report_key(mouse, BTN_EXTRA, buf[0] & 0x10);*/
+ input_report_rel(mouse, REL_X, rel_x);
+ input_report_rel(mouse, REL_Y, rel_y);
+ /*input_report_rel(mouse, REL_WHEEL, buf[3]);*/
+ input_sync(mouse);
+ } else {
+ /* The signals have been decoded onboard the iMON controller */
+ lirc_buffer_write_1 (context ->plugin ->rbuf, buf);
+ wake_up (&context ->plugin ->rbuf ->wait_poll);
+ }
return;
}
@@ -1082,6 +1102,22 @@
#endif
}
+ /* register with kernel input system for PAD mouse */
+ context->mouse.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ context->mouse.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+ context->mouse.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ context->mouse.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
+ context->mouse.relbit[0] |= BIT(REL_WHEEL);
+ context->mouse.private = context;
+
+ context->mouse.id.bustype = BUS_USB;
+ context->mouse.id.vendor = le16_to_cpu(dev->descriptor.idVendor);
+ context->mouse.id.product = le16_to_cpu(dev->descriptor.idProduct);
+ context->mouse.id.version = le16_to_cpu(dev->descriptor.bcdDevice);
+ context->mouse.dev = &dev->dev;
+
+ input_register_device(&context->mouse);
+
info ("%s: iMON device on usb<%d:%d> initialized",
__FUNCTION__, dev ->bus ->busnum, dev ->devnum);
@@ -1125,12 +1161,12 @@
context ->dev_present = FALSE;
/* Stop reception */
- usb_unlink_urb (context ->rx_urb);
+ usb_kill_urb (context ->rx_urb);
/* Abort ongoing write */
if (atomic_read (&context ->tx.busy)) {
- usb_unlink_urb (context ->tx_urb);
+ usb_kill_urb (context ->tx_urb);
wait_for_completion (&context ->tx.finished);
}
@@ -1147,6 +1183,8 @@
#endif
}
+ input_unregister_device (&context ->mouse);
+
UNLOCK_CONTEXT;
if (!context ->ir_isopen && !context ->vfd_isopen)
Venky: Do you know how to make this so it's not dependent on a lirc client being connected?
