Commit 7c660b15 authored by Vojtech Pavlik's avatar Vojtech Pavlik

Merge bk://dtor.bkbits.net/input into suse.cz:/home/vojtech/bk/input-dt

parents f83d9e8d f239d297
...@@ -890,8 +890,8 @@ running once the system is up. ...@@ -890,8 +890,8 @@ running once the system is up.
psmouse.rate= [HW,MOUSE] Set desired mouse report rate, in reports psmouse.rate= [HW,MOUSE] Set desired mouse report rate, in reports
per second. per second.
psmouse.resetafter= psmouse.resetafter=
[HW,MOUSE] Try to reset Synaptics Touchpad after so many [HW,MOUSE] Try to reset the device after so many bad packets
bad packets (0 = never). (0 = never).
psmouse.resolution= psmouse.resolution=
[HW,MOUSE] Set desired mouse resolution, in dpi. [HW,MOUSE] Set desired mouse resolution, in dpi.
psmouse.smartscroll= psmouse.smartscroll=
......
...@@ -41,9 +41,16 @@ config INPUT_MOUSEDEV ...@@ -41,9 +41,16 @@ config INPUT_MOUSEDEV
module will be called mousedev. module will be called mousedev.
config INPUT_MOUSEDEV_PSAUX config INPUT_MOUSEDEV_PSAUX
bool "Provide legacy /dev/psaux device" if EMBEDDED bool "Provide legacy /dev/psaux device"
default y default y
depends on INPUT_MOUSEDEV depends on INPUT_MOUSEDEV
---help---
Say Y here if you want your mouse also be accessible as char device
10:1 - /dev/psaux. The data available through /dev/psaux is exactly
the same as the data from /dev/input/mice.
If unsure, say Y.
config INPUT_MOUSEDEV_SCREEN_X config INPUT_MOUSEDEV_SCREEN_X
int "Horizontal screen resolution" int "Horizontal screen resolution"
......
...@@ -106,7 +106,7 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in ...@@ -106,7 +106,7 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
} }
break; break;
case EV_ABS: case EV_ABS:
if (code > ABS_MAX || !test_bit(code, dev->absbit)) if (code > ABS_MAX || !test_bit(code, dev->absbit))
...@@ -144,27 +144,27 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in ...@@ -144,27 +144,27 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
if (code > MSC_MAX || !test_bit(code, dev->mscbit)) if (code > MSC_MAX || !test_bit(code, dev->mscbit))
return; return;
if (dev->event) dev->event(dev, type, code, value); if (dev->event) dev->event(dev, type, code, value);
break; break;
case EV_LED: case EV_LED:
if (code > LED_MAX || !test_bit(code, dev->ledbit) || !!test_bit(code, dev->led) == value) if (code > LED_MAX || !test_bit(code, dev->ledbit) || !!test_bit(code, dev->led) == value)
return; return;
change_bit(code, dev->led); change_bit(code, dev->led);
if (dev->event) dev->event(dev, type, code, value); if (dev->event) dev->event(dev, type, code, value);
break; break;
case EV_SND: case EV_SND:
if (code > SND_MAX || !test_bit(code, dev->sndbit)) if (code > SND_MAX || !test_bit(code, dev->sndbit))
return; return;
if (dev->event) dev->event(dev, type, code, value); if (dev->event) dev->event(dev, type, code, value);
break; break;
case EV_REP: case EV_REP:
...@@ -181,7 +181,7 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in ...@@ -181,7 +181,7 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
break; break;
} }
if (type != EV_SYN) if (type != EV_SYN)
dev->sync = 0; dev->sync = 0;
if (dev->grab) if (dev->grab)
...@@ -282,11 +282,11 @@ static struct input_device_id *input_match_device(struct input_device_id *id, st ...@@ -282,11 +282,11 @@ static struct input_device_id *input_match_device(struct input_device_id *id, st
if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR) if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
if (id->id.vendor != dev->id.vendor) if (id->id.vendor != dev->id.vendor)
continue; continue;
if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT) if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
if (id->id.product != dev->id.product) if (id->id.product != dev->id.product)
continue; continue;
if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION) if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION)
if (id->id.version != dev->id.version) if (id->id.version != dev->id.version)
continue; continue;
...@@ -351,11 +351,11 @@ static void input_call_hotplug(char *verb, struct input_dev *dev) ...@@ -351,11 +351,11 @@ static void input_call_hotplug(char *verb, struct input_dev *dev)
} }
if (in_interrupt()) { if (in_interrupt()) {
printk(KERN_ERR "input.c: calling hotplug from interrupt\n"); printk(KERN_ERR "input.c: calling hotplug from interrupt\n");
return; return;
} }
if (!current->fs->root) { if (!current->fs->root) {
printk(KERN_WARNING "input.c: calling hotplug without valid filesystem\n"); printk(KERN_WARNING "input.c: calling hotplug without valid filesystem\n");
return; return;
} }
if (!(envp = (char **) kmalloc(20 * sizeof(char *), GFP_KERNEL))) { if (!(envp = (char **) kmalloc(20 * sizeof(char *), GFP_KERNEL))) {
printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n"); printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
...@@ -381,17 +381,17 @@ static void input_call_hotplug(char *verb, struct input_dev *dev) ...@@ -381,17 +381,17 @@ static void input_call_hotplug(char *verb, struct input_dev *dev)
envp[i++] = scratch; envp[i++] = scratch;
scratch += sprintf(scratch, "PRODUCT=%x/%x/%x/%x", scratch += sprintf(scratch, "PRODUCT=%x/%x/%x/%x",
dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version) + 1; dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version) + 1;
if (dev->name) { if (dev->name) {
envp[i++] = scratch; envp[i++] = scratch;
scratch += sprintf(scratch, "NAME=%s", dev->name) + 1; scratch += sprintf(scratch, "NAME=%s", dev->name) + 1;
} }
if (dev->phys) { if (dev->phys) {
envp[i++] = scratch; envp[i++] = scratch;
scratch += sprintf(scratch, "PHYS=%s", dev->phys) + 1; scratch += sprintf(scratch, "PHYS=%s", dev->phys) + 1;
} }
SPRINTF_BIT_A(evbit, "EV=", EV_MAX); SPRINTF_BIT_A(evbit, "EV=", EV_MAX);
SPRINTF_BIT_A2(keybit, "KEY=", KEY_MAX, EV_KEY); SPRINTF_BIT_A2(keybit, "KEY=", KEY_MAX, EV_KEY);
...@@ -506,7 +506,7 @@ void input_register_handler(struct input_handler *handler) ...@@ -506,7 +506,7 @@ void input_register_handler(struct input_handler *handler)
input_table[handler->minor >> 5] = handler; input_table[handler->minor >> 5] = handler;
list_add_tail(&handler->node, &input_handler_list); list_add_tail(&handler->node, &input_handler_list);
list_for_each_entry(dev, &input_dev_list, node) list_for_each_entry(dev, &input_dev_list, node)
if (!handler->blacklist || !input_match_device(handler->blacklist, dev)) if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
if ((id = input_match_device(handler->id_table, dev))) if ((id = input_match_device(handler->id_table, dev)))
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/serio.h> #include <linux/serio.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/timer.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("AT and PS/2 keyboard driver"); MODULE_DESCRIPTION("AT and PS/2 keyboard driver");
...@@ -173,22 +172,24 @@ struct atkbd { ...@@ -173,22 +172,24 @@ struct atkbd {
unsigned char keycode[512]; unsigned char keycode[512];
struct input_dev dev; struct input_dev dev;
struct serio *serio; struct serio *serio;
struct timer_list timer;
char name[64]; char name[64];
char phys[32]; char phys[32];
unsigned short id;
unsigned char set;
unsigned int translated:1;
unsigned int extra:1;
unsigned int write:1;
unsigned char cmdbuf[4]; unsigned char cmdbuf[4];
unsigned char cmdcnt; unsigned char cmdcnt;
unsigned char set;
unsigned char extra;
unsigned char release;
int lastkey;
volatile signed char ack; volatile signed char ack;
unsigned char emul; unsigned char emul;
unsigned short id; unsigned int resend:1;
unsigned char write; unsigned int release:1;
unsigned char translated; unsigned int bat_xl:1;
unsigned char resend; unsigned int enabled:1;
unsigned char bat_xl;
unsigned int last; unsigned int last;
unsigned long time; unsigned long time;
}; };
...@@ -248,6 +249,9 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, ...@@ -248,6 +249,9 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
goto out; goto out;
} }
if (!atkbd->enabled)
goto out;
if (atkbd->translated) { if (atkbd->translated) {
if (atkbd->emul || if (atkbd->emul ||
...@@ -300,15 +304,20 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, ...@@ -300,15 +304,20 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
case ATKBD_KEY_NULL: case ATKBD_KEY_NULL:
break; break;
case ATKBD_KEY_UNKNOWN: case ATKBD_KEY_UNKNOWN:
printk(KERN_WARNING "atkbd.c: Unknown key %s (%s set %d, code %#x on %s).\n", if (data == ATKBD_RET_ACK || data == ATKBD_RET_NAK) {
atkbd->release ? "released" : "pressed", printk(KERN_WARNING "atkbd.c: Spurious %s on %s. Some program, "
atkbd->translated ? "translated" : "raw", "like XFree86, might be trying access hardware directly.\n",
atkbd->set, code, serio->phys); data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
if (atkbd->translated && atkbd->set == 2 && code == 0x7a) } else {
printk(KERN_WARNING "atkbd.c: This is an XFree86 bug. It shouldn't access" printk(KERN_WARNING "atkbd.c: Unknown key %s "
" hardware directly.\n"); "(%s set %d, code %#x on %s).\n",
else atkbd->release ? "released" : "pressed",
printk(KERN_WARNING "atkbd.c: Use 'setkeycodes %s%02x <keycode>' to make it known.\n", code & 0x80 ? "e0" : "", code & 0x7f); atkbd->translated ? "translated" : "raw",
atkbd->set, code, serio->phys);
printk(KERN_WARNING "atkbd.c: Use 'setkeycodes %s%02x <keycode>' "
"to make it known.\n",
code & 0x80 ? "e0" : "", code & 0x7f);
}
break; break;
case ATKBD_SCR_1: case ATKBD_SCR_1:
scroll = 1 - atkbd->release * 2; scroll = 1 - atkbd->release * 2;
...@@ -745,6 +754,8 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev) ...@@ -745,6 +754,8 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
atkbd->id = 0xab00; atkbd->id = 0xab00;
} }
atkbd->enabled = 1;
if (atkbd->extra) { if (atkbd->extra) {
atkbd->dev.ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) | BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC); atkbd->dev.ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) | BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC);
sprintf(atkbd->name, "AT Set 2 Extra keyboard"); sprintf(atkbd->name, "AT Set 2 Extra keyboard");
...@@ -809,12 +820,12 @@ static int atkbd_reconnect(struct serio *serio) ...@@ -809,12 +820,12 @@ static int atkbd_reconnect(struct serio *serio)
param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0) param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0)
| (test_bit(LED_NUML, atkbd->dev.led) ? 2 : 0) | (test_bit(LED_NUML, atkbd->dev.led) ? 2 : 0)
| (test_bit(LED_CAPSL, atkbd->dev.led) ? 4 : 0); | (test_bit(LED_CAPSL, atkbd->dev.led) ? 4 : 0);
if (atkbd_probe(atkbd)) if (atkbd_probe(atkbd))
return -1; return -1;
if (atkbd->set != atkbd_set_3(atkbd)) if (atkbd->set != atkbd_set_3(atkbd))
return -1; return -1;
atkbd_enable(atkbd); atkbd_enable(atkbd);
if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS)) if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS))
......
...@@ -41,11 +41,11 @@ static int spkr98_event(struct input_dev *dev, unsigned int type, unsigned int c ...@@ -41,11 +41,11 @@ static int spkr98_event(struct input_dev *dev, unsigned int type, unsigned int c
case SND_BELL: if (value) value = 1000; case SND_BELL: if (value) value = 1000;
case SND_TONE: break; case SND_TONE: break;
default: return -1; default: return -1;
} }
if (value > 20 && value < 32767) if (value > 20 && value < 32767)
count = CLOCK_TICK_RATE / value; count = CLOCK_TICK_RATE / value;
spin_lock_irqsave(&i8253_beep_lock, flags); spin_lock_irqsave(&i8253_beep_lock, flags);
if (count) { if (count) {
......
...@@ -40,11 +40,11 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c ...@@ -40,11 +40,11 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c
case SND_BELL: if (value) value = 1000; case SND_BELL: if (value) value = 1000;
case SND_TONE: break; case SND_TONE: break;
default: return -1; default: return -1;
} }
if (value > 20 && value < 32767) if (value > 20 && value < 32767)
count = CLOCK_TICK_RATE / value; count = CLOCK_TICK_RATE / value;
spin_lock_irqsave(&i8253_beep_lock, flags); spin_lock_irqsave(&i8253_beep_lock, flags);
if (count) { if (count) {
......
...@@ -53,11 +53,11 @@ static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned in ...@@ -53,11 +53,11 @@ static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned in
case SND_BELL: if (value) value = 1000; case SND_BELL: if (value) value = 1000;
case SND_TONE: break; case SND_TONE: break;
default: return -1; default: return -1;
} }
if (value > 20 && value < 32767) if (value > 20 && value < 32767)
count = 1193182 / value; count = 1193182 / value;
spin_lock_irqsave(&beep_lock, flags); spin_lock_irqsave(&beep_lock, flags);
/* EBUS speaker only has on/off state, the frequency does not /* EBUS speaker only has on/off state, the frequency does not
...@@ -108,11 +108,11 @@ static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int ...@@ -108,11 +108,11 @@ static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int
case SND_BELL: if (value) value = 1000; case SND_BELL: if (value) value = 1000;
case SND_TONE: break; case SND_TONE: break;
default: return -1; default: return -1;
} }
if (value > 20 && value < 32767) if (value > 20 && value < 32767)
count = 1193182 / value; count = 1193182 / value;
spin_lock_irqsave(&beep_lock, flags); spin_lock_irqsave(&beep_lock, flags);
if (count) { if (count) {
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
* Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org> * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
* *
* Changes/Revisions: * Changes/Revisions:
* 0.1 20/06/2002 * 0.1 20/06/2002
* - first public version * - first public version
...@@ -68,7 +68,7 @@ static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *eff ...@@ -68,7 +68,7 @@ static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *eff
static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id) static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id)
{ {
return 0; return 0;
} }
static int uinput_create_device(struct uinput_device *udev) static int uinput_create_device(struct uinput_device *udev)
{ {
...@@ -123,7 +123,7 @@ static int uinput_open(struct inode *inode, struct file *file) ...@@ -123,7 +123,7 @@ static int uinput_open(struct inode *inode, struct file *file)
memset(newinput, 0, sizeof(struct input_dev)); memset(newinput, 0, sizeof(struct input_dev));
newdev->dev = newinput; newdev->dev = newinput;
file->private_data = newdev; file->private_data = newdev;
return 0; return 0;
...@@ -137,16 +137,16 @@ static int uinput_validate_absbits(struct input_dev *dev) ...@@ -137,16 +137,16 @@ static int uinput_validate_absbits(struct input_dev *dev)
{ {
unsigned int cnt; unsigned int cnt;
int retval = 0; int retval = 0;
for (cnt = 0; cnt < ABS_MAX; cnt++) { for (cnt = 0; cnt < ABS_MAX; cnt++) {
if (!test_bit(cnt, dev->absbit)) if (!test_bit(cnt, dev->absbit))
continue; continue;
if (/*!dev->absmin[cnt] || !dev->absmax[cnt] || */ if (/*!dev->absmin[cnt] || !dev->absmax[cnt] || */
(dev->absmax[cnt] <= dev->absmin[cnt])) { (dev->absmax[cnt] <= dev->absmin[cnt])) {
printk(KERN_DEBUG printk(KERN_DEBUG
"%s: invalid abs[%02x] min:%d max:%d\n", "%s: invalid abs[%02x] min:%d max:%d\n",
UINPUT_NAME, cnt, UINPUT_NAME, cnt,
dev->absmin[cnt], dev->absmax[cnt]); dev->absmin[cnt], dev->absmax[cnt]);
retval = -EINVAL; retval = -EINVAL;
break; break;
...@@ -154,7 +154,7 @@ static int uinput_validate_absbits(struct input_dev *dev) ...@@ -154,7 +154,7 @@ static int uinput_validate_absbits(struct input_dev *dev)
if ((dev->absflat[cnt] < dev->absmin[cnt]) || if ((dev->absflat[cnt] < dev->absmin[cnt]) ||
(dev->absflat[cnt] > dev->absmax[cnt])) { (dev->absflat[cnt] > dev->absmax[cnt])) {
printk(KERN_DEBUG printk(KERN_DEBUG
"%s: absflat[%02x] out of range: %d " "%s: absflat[%02x] out of range: %d "
"(min:%d/max:%d)\n", "(min:%d/max:%d)\n",
UINPUT_NAME, cnt, dev->absflat[cnt], UINPUT_NAME, cnt, dev->absflat[cnt],
...@@ -190,7 +190,7 @@ static int uinput_alloc_device(struct file *file, const char *buffer, size_t cou ...@@ -190,7 +190,7 @@ static int uinput_alloc_device(struct file *file, const char *buffer, size_t cou
goto exit; goto exit;
} }
if (NULL != dev->name) if (NULL != dev->name)
kfree(dev->name); kfree(dev->name);
size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1; size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1;
...@@ -229,7 +229,7 @@ static int uinput_alloc_device(struct file *file, const char *buffer, size_t cou ...@@ -229,7 +229,7 @@ static int uinput_alloc_device(struct file *file, const char *buffer, size_t cou
static ssize_t uinput_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) static ssize_t uinput_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{ {
struct uinput_device *udev = file->private_data; struct uinput_device *udev = file->private_data;
if (test_bit(UIST_CREATED, &(udev->state))) { if (test_bit(UIST_CREATED, &(udev->state))) {
struct input_event ev; struct input_event ev;
...@@ -247,7 +247,7 @@ static ssize_t uinput_read(struct file *file, char *buffer, size_t count, loff_t ...@@ -247,7 +247,7 @@ static ssize_t uinput_read(struct file *file, char *buffer, size_t count, loff_t
{ {
struct uinput_device *udev = file->private_data; struct uinput_device *udev = file->private_data;
int retval = 0; int retval = 0;
if (!test_bit(UIST_CREATED, &(udev->state))) if (!test_bit(UIST_CREATED, &(udev->state)))
return -ENODEV; return -ENODEV;
...@@ -255,16 +255,16 @@ static ssize_t uinput_read(struct file *file, char *buffer, size_t count, loff_t ...@@ -255,16 +255,16 @@ static ssize_t uinput_read(struct file *file, char *buffer, size_t count, loff_t
return -EAGAIN; return -EAGAIN;
retval = wait_event_interruptible(udev->waitq, retval = wait_event_interruptible(udev->waitq,
(udev->head != udev->tail) || (udev->head != udev->tail) ||
!test_bit(UIST_CREATED, &(udev->state))); !test_bit(UIST_CREATED, &(udev->state)));
if (retval) if (retval)
return retval; return retval;
if (!test_bit(UIST_CREATED, &(udev->state))) if (!test_bit(UIST_CREATED, &(udev->state)))
return -ENODEV; return -ENODEV;
while ((udev->head != udev->tail) && while ((udev->head != udev->tail) &&
(retval + sizeof(struct input_event) <= count)) { (retval + sizeof(struct input_event) <= count)) {
if (copy_to_user(buffer + retval, &(udev->buff[udev->tail]), if (copy_to_user(buffer + retval, &(udev->buff[udev->tail]),
sizeof(struct input_event))) return -EFAULT; sizeof(struct input_event))) return -EFAULT;
...@@ -284,7 +284,7 @@ static unsigned int uinput_poll(struct file *file, poll_table *wait) ...@@ -284,7 +284,7 @@ static unsigned int uinput_poll(struct file *file, poll_table *wait)
if (udev->head != udev->tail) if (udev->head != udev->tail)
return POLLIN | POLLRDNORM; return POLLIN | POLLRDNORM;
return 0; return 0;
} }
static int uinput_burn_device(struct uinput_device *udev) static int uinput_burn_device(struct uinput_device *udev)
...@@ -318,7 +318,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd ...@@ -318,7 +318,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd
case UI_DEV_CREATE: case UI_DEV_CREATE:
retval = uinput_create_device(udev); retval = uinput_create_device(udev);
break; break;
case UI_DEV_DESTROY: case UI_DEV_DESTROY:
retval = uinput_destroy_device(udev); retval = uinput_destroy_device(udev);
break; break;
...@@ -330,7 +330,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd ...@@ -330,7 +330,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd
} }
set_bit(arg, udev->dev->evbit); set_bit(arg, udev->dev->evbit);
break; break;
case UI_SET_KEYBIT: case UI_SET_KEYBIT:
if (arg > KEY_MAX) { if (arg > KEY_MAX) {
retval = -EINVAL; retval = -EINVAL;
...@@ -338,7 +338,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd ...@@ -338,7 +338,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd
} }
set_bit(arg, udev->dev->keybit); set_bit(arg, udev->dev->keybit);
break; break;
case UI_SET_RELBIT: case UI_SET_RELBIT:
if (arg > REL_MAX) { if (arg > REL_MAX) {
retval = -EINVAL; retval = -EINVAL;
...@@ -346,7 +346,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd ...@@ -346,7 +346,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd
} }
set_bit(arg, udev->dev->relbit); set_bit(arg, udev->dev->relbit);
break; break;
case UI_SET_ABSBIT: case UI_SET_ABSBIT:
if (arg > ABS_MAX) { if (arg > ABS_MAX) {
retval = -EINVAL; retval = -EINVAL;
...@@ -354,7 +354,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd ...@@ -354,7 +354,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd
} }
set_bit(arg, udev->dev->absbit); set_bit(arg, udev->dev->absbit);
break; break;
case UI_SET_MSCBIT: case UI_SET_MSCBIT:
if (arg > MSC_MAX) { if (arg > MSC_MAX) {
retval = -EINVAL; retval = -EINVAL;
...@@ -362,7 +362,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd ...@@ -362,7 +362,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd
} }
set_bit(arg, udev->dev->mscbit); set_bit(arg, udev->dev->mscbit);
break; break;
case UI_SET_LEDBIT: case UI_SET_LEDBIT:
if (arg > LED_MAX) { if (arg > LED_MAX) {
retval = -EINVAL; retval = -EINVAL;
...@@ -370,7 +370,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd ...@@ -370,7 +370,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd
} }
set_bit(arg, udev->dev->ledbit); set_bit(arg, udev->dev->ledbit);
break; break;
case UI_SET_SNDBIT: case UI_SET_SNDBIT:
if (arg > SND_MAX) { if (arg > SND_MAX) {
retval = -EINVAL; retval = -EINVAL;
...@@ -378,7 +378,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd ...@@ -378,7 +378,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd
} }
set_bit(arg, udev->dev->sndbit); set_bit(arg, udev->dev->sndbit);
break; break;
case UI_SET_FFBIT: case UI_SET_FFBIT:
if (arg > FF_MAX) { if (arg > FF_MAX) {
retval = -EINVAL; retval = -EINVAL;
...@@ -386,7 +386,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd ...@@ -386,7 +386,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd
} }
set_bit(arg, udev->dev->ffbit); set_bit(arg, udev->dev->ffbit);
break; break;
default: default:
retval = -EFAULT; retval = -EFAULT;
} }
......
...@@ -63,7 +63,6 @@ void ps2pp_process_packet(struct psmouse *psmouse) ...@@ -63,7 +63,6 @@ void ps2pp_process_packet(struct psmouse *psmouse)
packet[0] &= 0x0f; packet[0] &= 0x0f;
packet[1] = 0; packet[1] = 0;
packet[2] = 0; packet[2] = 0;
} }
} }
...@@ -76,18 +75,9 @@ void ps2pp_process_packet(struct psmouse *psmouse) ...@@ -76,18 +75,9 @@ void ps2pp_process_packet(struct psmouse *psmouse)
static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned char command) static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned char command)
{ {
unsigned char d; if (psmouse_sliced_command(psmouse, command))
int i;
if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11))
return -1; return -1;
for (i = 6; i >= 0; i -= 2) {
d = (command >> i) & 3;
if(psmouse_command(psmouse, &d, PSMOUSE_CMD_SETRES))
return -1;
}
if (psmouse_command(psmouse, param, PSMOUSE_CMD_POLL)) if (psmouse_command(psmouse, param, PSMOUSE_CMD_POLL))
return -1; return -1;
...@@ -99,7 +89,7 @@ static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned cha ...@@ -99,7 +89,7 @@ static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned cha
* enabled if we do nothing to it. Of course I put this in because I want it * enabled if we do nothing to it. Of course I put this in because I want it
* disabled :P * disabled :P
* 1 - enabled (if previously disabled, also default) * 1 - enabled (if previously disabled, also default)
* 0/2 - disabled * 0/2 - disabled
*/ */
static void ps2pp_set_smartscroll(struct psmouse *psmouse) static void ps2pp_set_smartscroll(struct psmouse *psmouse)
...@@ -113,14 +103,11 @@ static void ps2pp_set_smartscroll(struct psmouse *psmouse) ...@@ -113,14 +103,11 @@ static void ps2pp_set_smartscroll(struct psmouse *psmouse)
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
if (psmouse_smartscroll == 1) if (psmouse_smartscroll < 2) {
param[0] = 1; /* 0 - disabled, 1 - enabled */
else param[0] = psmouse_smartscroll;
if (psmouse_smartscroll > 2) psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
return; }
/* else leave param[0] == 0 to disable */
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
} }
/* /*
...@@ -138,111 +125,128 @@ void ps2pp_set_800dpi(struct psmouse *psmouse) ...@@ -138,111 +125,128 @@ void ps2pp_set_800dpi(struct psmouse *psmouse)
psmouse_command(psmouse, &param, PSMOUSE_CMD_SETRES); psmouse_command(psmouse, &param, PSMOUSE_CMD_SETRES);
} }
static int is_model_in_list(unsigned char model, int *model_list)
{
int i;
for (i = 0; model_list[i] != -1; i++)
if (model == model_list[i])
return 1;
return 0;
}
/* /*
* Detect the exact model and features of a PS2++ or PS2T++ Logitech mouse or * Set up input device's properties based on the detected mouse model.
* touchpad.
*/ */
static int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param) static void ps2pp_set_properties(struct psmouse *psmouse, unsigned char protocol,
unsigned char model, unsigned char buttons)
{ {
int i;
static int logitech_4btn[] = { 12, 40, 41, 42, 43, 52, 73, 80, -1 }; static int logitech_4btn[] = { 12, 40, 41, 42, 43, 52, 73, 80, -1 };
static int logitech_wheel[] = { 52, 53, 75, 76, 80, 81, 83, 88, 112, -1 }; static int logitech_wheel[] = { 52, 53, 75, 76, 80, 81, 83, 88, 112, -1 };
static int logitech_ps2pp[] = { 12, 13, 40, 41, 42, 43, 50, 51, 52, 53, 73, 75,
76, 80, 81, 83, 88, 96, 97, 112, -1 };
static int logitech_mx[] = { 61, 112, -1 }; static int logitech_mx[] = { 61, 112, -1 };
psmouse->vendor = "Logitech"; psmouse->vendor = "Logitech";
psmouse->model = ((param[0] >> 4) & 0x07) | ((param[0] << 3) & 0x78); psmouse->model = model;
if (param[1] < 3) if (buttons < 3)
clear_bit(BTN_MIDDLE, psmouse->dev.keybit); clear_bit(BTN_MIDDLE, psmouse->dev.keybit);
if (param[1] < 2) if (buttons < 2)
clear_bit(BTN_RIGHT, psmouse->dev.keybit); clear_bit(BTN_RIGHT, psmouse->dev.keybit);
psmouse->type = PSMOUSE_PS2; if (protocol == PSMOUSE_PS2PP) {
for (i = 0; logitech_ps2pp[i] != -1; i++) if (is_model_in_list(model, logitech_4btn))
if (logitech_ps2pp[i] == psmouse->model) set_bit(BTN_SIDE, psmouse->dev.keybit);
psmouse->type = PSMOUSE_PS2PP;
if (psmouse->type == PSMOUSE_PS2PP) { if (is_model_in_list(model, logitech_wheel)) {
set_bit(REL_WHEEL, psmouse->dev.relbit);
psmouse->name = "Wheel Mouse";
}
for (i = 0; logitech_4btn[i] != -1; i++) if (is_model_in_list(model, logitech_mx)) {
if (logitech_4btn[i] == psmouse->model) set_bit(BTN_SIDE, psmouse->dev.keybit);
set_bit(BTN_SIDE, psmouse->dev.keybit); set_bit(BTN_EXTRA, psmouse->dev.keybit);
set_bit(BTN_BACK, psmouse->dev.keybit);
set_bit(BTN_FORWARD, psmouse->dev.keybit);
set_bit(BTN_TASK, psmouse->dev.keybit);
psmouse->name = "MX Mouse";
}
}
for (i = 0; logitech_wheel[i] != -1; i++) if (protocol == PSMOUSE_PS2TPP) {
if (logitech_wheel[i] == psmouse->model) { set_bit(REL_WHEEL, psmouse->dev.relbit);
set_bit(REL_WHEEL, psmouse->dev.relbit); set_bit(REL_HWHEEL, psmouse->dev.relbit);
psmouse->name = "Wheel Mouse"; psmouse->name = "TouchPad 3";
} }
}
for (i = 0; logitech_mx[i] != -1; i++)
if (logitech_mx[i] == psmouse->model) {
set_bit(BTN_SIDE, psmouse->dev.keybit);
set_bit(BTN_EXTRA, psmouse->dev.keybit);
set_bit(BTN_BACK, psmouse->dev.keybit);
set_bit(BTN_FORWARD, psmouse->dev.keybit);
set_bit(BTN_TASK, psmouse->dev.keybit);
psmouse->name = "MX Mouse";
}
/* /*
* Do Logitech PS2++ / PS2T++ magic init. * Logitech magic init. Detect whether the mouse is a Logitech one
* and its exact model and try turning on extended protocol for ones
* that support it.
*/ */
if (psmouse->model == 97) { /* TouchPad 3 */ int ps2pp_init(struct psmouse *psmouse, int set_properties)
{
static int logitech_ps2pp[] = { 12, 13, 40, 41, 42, 43, 50, 51, 52, 53, 73, 75,
76, 80, 81, 83, 88, 96, 97, 112, -1 };
unsigned char param[4];
unsigned char protocol = PSMOUSE_PS2;
unsigned char model, buttons;
param[0] = 0;
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11);
psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11);
psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11);
param[1] = 0;
psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
set_bit(REL_WHEEL, psmouse->dev.relbit); if (param[1] != 0) {
set_bit(REL_HWHEEL, psmouse->dev.relbit); model = ((param[0] >> 4) & 0x07) | ((param[0] << 3) & 0x78);
buttons = param[1];
/*
* Do Logitech PS2++ / PS2T++ magic init.
*/
if (model == 97) { /* Touch Pad 3 */
param[0] = 0x11; param[1] = 0x04; param[2] = 0x68; /* Unprotect RAM */ /* Unprotect RAM */
param[0] = 0x11; param[1] = 0x04; param[2] = 0x68;
psmouse_command(psmouse, param, 0x30d1); psmouse_command(psmouse, param, 0x30d1);
param[0] = 0x11; param[1] = 0x05; param[2] = 0x0b; /* Enable features */ /* Enable features */
param[0] = 0x11; param[1] = 0x05; param[2] = 0x0b;
psmouse_command(psmouse, param, 0x30d1); psmouse_command(psmouse, param, 0x30d1);
param[0] = 0x11; param[1] = 0x09; param[2] = 0xc3; /* Enable PS2++ */ /* Enable PS2++ */
param[0] = 0x11; param[1] = 0x09; param[2] = 0xc3;
psmouse_command(psmouse, param, 0x30d1); psmouse_command(psmouse, param, 0x30d1);
param[0] = 0; param[0] = 0;
if (!psmouse_command(psmouse, param, 0x13d1) && if (!psmouse_command(psmouse, param, 0x13d1) &&
param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14) { param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14) {
psmouse->name = "TouchPad 3"; protocol = PSMOUSE_PS2TPP;
return PSMOUSE_PS2TPP;
} }
} else { } else if (is_model_in_list(model, logitech_ps2pp)) {
param[0] = param[1] = param[2] = 0; param[0] = param[1] = param[2] = 0;
ps2pp_cmd(psmouse, param, 0x39); /* Magic knock */ ps2pp_cmd(psmouse, param, 0x39); /* Magic knock */
ps2pp_cmd(psmouse, param, 0xDB); ps2pp_cmd(psmouse, param, 0xDB);
if ((param[0] & 0x78) == 0x48 && (param[1] & 0xf3) == 0xc2 && if ((param[0] & 0x78) == 0x48 &&
(param[2] & 3) == ((param[1] >> 2) & 3)) { (param[1] & 0xf3) == 0xc2 &&
ps2pp_set_smartscroll(psmouse); (param[2] & 0x03) == ((param[1] >> 2) & 3)) {
return PSMOUSE_PS2PP; ps2pp_set_smartscroll(psmouse);
protocol = PSMOUSE_PS2PP;
} }
} }
}
return 0; if (set_properties)
} ps2pp_set_properties(psmouse, protocol, model, buttons);
}
/*
* Logitech magic init.
*/
int ps2pp_detect(struct psmouse *psmouse)
{
unsigned char param[4];
param[0] = 0;
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11);
psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11);
psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11);
param[1] = 0;
psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
return param[1] != 0 ? ps2pp_detect_model(psmouse, param) : 0; return protocol;
} }
...@@ -10,8 +10,9 @@ ...@@ -10,8 +10,9 @@
#ifndef _LOGIPS2PP_H #ifndef _LOGIPS2PP_H
#define _LOGIPS2PP_H #define _LOGIPS2PP_H
struct psmouse;
void ps2pp_process_packet(struct psmouse *psmouse); void ps2pp_process_packet(struct psmouse *psmouse);
void ps2pp_set_800dpi(struct psmouse *psmouse); void ps2pp_set_800dpi(struct psmouse *psmouse);
int ps2pp_detect(struct psmouse *psmouse); int ps2pp_init(struct psmouse *psmouse, int set_properties);
#endif #endif
...@@ -43,9 +43,9 @@ int psmouse_smartscroll = 1; ...@@ -43,9 +43,9 @@ int psmouse_smartscroll = 1;
module_param_named(smartscroll, psmouse_smartscroll, bool, 0); module_param_named(smartscroll, psmouse_smartscroll, bool, 0);
MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");
unsigned int psmouse_resetafter; static unsigned int psmouse_resetafter;
module_param_named(resetafter, psmouse_resetafter, uint, 0); module_param_named(resetafter, psmouse_resetafter, uint, 0);
MODULE_PARM_DESC(resetafter, "Reset Synaptics Touchpad after so many bad packets (0 = never)."); MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
__obsolete_setup("psmouse_noext"); __obsolete_setup("psmouse_noext");
__obsolete_setup("psmouse_resolution="); __obsolete_setup("psmouse_resolution=");
...@@ -56,15 +56,22 @@ __obsolete_setup("psmouse_rate="); ...@@ -56,15 +56,22 @@ __obsolete_setup("psmouse_rate=");
static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2"}; static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2"};
/* /*
* psmouse_process_packet() analyzes the PS/2 mouse packet contents and * psmouse_process_byte() analyzes the PS/2 data stream and reports
* reports relevant events to the input module. * relevant events to the input module once full packet has arrived.
*/ */
static void psmouse_process_packet(struct psmouse *psmouse, struct pt_regs *regs) static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
{ {
struct input_dev *dev = &psmouse->dev; struct input_dev *dev = &psmouse->dev;
unsigned char *packet = psmouse->packet; unsigned char *packet = psmouse->packet;
if (psmouse->pktcnt < 3 + (psmouse->type >= PSMOUSE_GENPS))
return PSMOUSE_GOOD_DATA;
/*
* Full packet accumulated, process it
*/
input_regs(dev, regs); input_regs(dev, regs);
/* /*
...@@ -112,6 +119,8 @@ static void psmouse_process_packet(struct psmouse *psmouse, struct pt_regs *regs ...@@ -112,6 +119,8 @@ static void psmouse_process_packet(struct psmouse *psmouse, struct pt_regs *regs
input_report_rel(dev, REL_Y, packet[2] ? (int) ((packet[0] << 3) & 0x100) - (int) packet[2] : 0); input_report_rel(dev, REL_Y, packet[2] ? (int) ((packet[0] << 3) & 0x100) - (int) packet[2] : 0);
input_sync(dev); input_sync(dev);
return PSMOUSE_FULL_PACKET;
} }
/* /*
...@@ -123,6 +132,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, ...@@ -123,6 +132,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
unsigned char data, unsigned int flags, struct pt_regs *regs) unsigned char data, unsigned int flags, struct pt_regs *regs)
{ {
struct psmouse *psmouse = serio->private; struct psmouse *psmouse = serio->private;
psmouse_ret_t rc;
if (psmouse->state == PSMOUSE_IGNORE) if (psmouse->state == PSMOUSE_IGNORE)
goto out; goto out;
...@@ -180,7 +190,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, ...@@ -180,7 +190,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
if (psmouse->pktcnt == 2) { if (psmouse->pktcnt == 2) {
if (psmouse->packet[1] == PSMOUSE_RET_ID) { if (psmouse->packet[1] == PSMOUSE_RET_ID) {
psmouse->state = PSMOUSE_IGNORE; psmouse->state = PSMOUSE_IGNORE;
serio_rescan(serio); serio_reconnect(serio);
goto out; goto out;
} }
if (psmouse->type == PSMOUSE_SYNAPTICS) { if (psmouse->type == PSMOUSE_SYNAPTICS) {
...@@ -193,19 +203,32 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, ...@@ -193,19 +203,32 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
} }
} }
if (psmouse->type == PSMOUSE_SYNAPTICS) { rc = psmouse->protocol_handler(psmouse, regs);
/*
* The synaptics driver has its own resync logic,
* so it needs to receive all bytes one at a time.
*/
synaptics_process_byte(psmouse, regs);
goto out;
}
if (psmouse->pktcnt == 3 + (psmouse->type >= PSMOUSE_GENPS)) { switch (rc) {
psmouse_process_packet(psmouse, regs); case PSMOUSE_BAD_DATA:
psmouse->pktcnt = 0; printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n",
goto out; psmouse->name, psmouse->phys, psmouse->pktcnt);
psmouse->pktcnt = 0;
if (++psmouse->out_of_sync == psmouse_resetafter) {
psmouse->state = PSMOUSE_IGNORE;
printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n");
serio_reconnect(psmouse->serio);
}
break;
case PSMOUSE_FULL_PACKET:
psmouse->pktcnt = 0;
if (psmouse->out_of_sync) {
psmouse->out_of_sync = 0;
printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n",
psmouse->name, psmouse->phys);
}
break;
case PSMOUSE_GOOD_DATA:
break;
} }
out: out:
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -288,6 +311,30 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command) ...@@ -288,6 +311,30 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
} }
/*
* psmouse_sliced_command() sends an extended PS/2 command to the mouse
* using sliced syntax, understood by advanced devices, such as Logitech
* or Synaptics touchpads. The command is encoded as:
* 0xE6 0xE8 rr 0xE8 ss 0xE8 tt 0xE8 uu where (rr*64)+(ss*16)+(tt*4)+uu
* is the command.
*/
int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command)
{
int i;
if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11))
return -1;
for (i = 6; i >= 0; i -= 2) {
unsigned char d = (command >> i) & 3;
if (psmouse_command(psmouse, &d, PSMOUSE_CMD_SETRES))
return -1;
}
return 0;
}
/* /*
* psmouse_reset() resets the mouse into power-on state. * psmouse_reset() resets the mouse into power-on state.
*/ */
...@@ -363,23 +410,23 @@ static int im_explorer_detect(struct psmouse *psmouse) ...@@ -363,23 +410,23 @@ static int im_explorer_detect(struct psmouse *psmouse)
* the mouse may have. * the mouse may have.
*/ */
static int psmouse_extensions(struct psmouse *psmouse) static int psmouse_extensions(struct psmouse *psmouse,
unsigned int max_proto, int set_properties)
{ {
int synaptics_hardware = 0; int synaptics_hardware = 0;
psmouse->vendor = "Generic";
psmouse->name = "Mouse";
psmouse->model = 0;
/* /*
* Try Synaptics TouchPad * Try Synaptics TouchPad
*/ */
if (psmouse_max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse)) { if (max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse)) {
synaptics_hardware = 1; synaptics_hardware = 1;
psmouse->vendor = "Synaptics";
psmouse->name = "TouchPad";
if (psmouse_max_proto > PSMOUSE_IMEX) { if (set_properties) {
psmouse->vendor = "Synaptics";
psmouse->name = "TouchPad";
}
if (max_proto > PSMOUSE_IMEX) {
if (synaptics_init(psmouse) == 0) if (synaptics_init(psmouse) == 0)
return PSMOUSE_SYNAPTICS; return PSMOUSE_SYNAPTICS;
/* /*
...@@ -387,7 +434,7 @@ static int psmouse_extensions(struct psmouse *psmouse) ...@@ -387,7 +434,7 @@ static int psmouse_extensions(struct psmouse *psmouse)
* Unfortunately Logitech/Genius probes confuse some firmware versions so * Unfortunately Logitech/Genius probes confuse some firmware versions so
* we'll have to skip them. * we'll have to skip them.
*/ */
psmouse_max_proto = PSMOUSE_IMEX; max_proto = PSMOUSE_IMEX;
} }
/* /*
* Make sure that touchpad is in relative mode, gestures (taps) are enabled * Make sure that touchpad is in relative mode, gestures (taps) are enabled
...@@ -395,35 +442,45 @@ static int psmouse_extensions(struct psmouse *psmouse) ...@@ -395,35 +442,45 @@ static int psmouse_extensions(struct psmouse *psmouse)
synaptics_reset(psmouse); synaptics_reset(psmouse);
} }
if (psmouse_max_proto > PSMOUSE_IMEX && genius_detect(psmouse)) { if (max_proto > PSMOUSE_IMEX && genius_detect(psmouse)) {
set_bit(BTN_EXTRA, psmouse->dev.keybit);
set_bit(BTN_SIDE, psmouse->dev.keybit); if (set_properties) {
set_bit(REL_WHEEL, psmouse->dev.relbit); set_bit(BTN_EXTRA, psmouse->dev.keybit);
set_bit(BTN_SIDE, psmouse->dev.keybit);
set_bit(REL_WHEEL, psmouse->dev.relbit);
psmouse->vendor = "Genius";
psmouse->name = "Wheel Mouse";
}
psmouse->vendor = "Genius";
psmouse->name = "Wheel Mouse";
return PSMOUSE_GENPS; return PSMOUSE_GENPS;
} }
if (psmouse_max_proto > PSMOUSE_IMEX) { if (max_proto > PSMOUSE_IMEX) {
int type = ps2pp_detect(psmouse); int type = ps2pp_init(psmouse, set_properties);
if (type) if (type > PSMOUSE_PS2)
return type; return type;
} }
if (psmouse_max_proto >= PSMOUSE_IMPS && intellimouse_detect(psmouse)) { if (max_proto >= PSMOUSE_IMPS && intellimouse_detect(psmouse)) {
set_bit(REL_WHEEL, psmouse->dev.relbit);
if (psmouse_max_proto >= PSMOUSE_IMEX && if (set_properties) {
im_explorer_detect(psmouse)) { set_bit(REL_WHEEL, psmouse->dev.relbit);
set_bit(BTN_SIDE, psmouse->dev.keybit); if (!psmouse->name)
set_bit(BTN_EXTRA, psmouse->dev.keybit); psmouse->name = "Wheel Mouse";
}
if (max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse)) {
if (!set_properties) {
set_bit(BTN_SIDE, psmouse->dev.keybit);
set_bit(BTN_EXTRA, psmouse->dev.keybit);
if (!psmouse->name)
psmouse->name = "Explorer Mouse";
}
psmouse->name = "Explorer Mouse";
return PSMOUSE_IMEX; return PSMOUSE_IMEX;
} }
psmouse->name = "Wheel Mouse";
return PSMOUSE_IMPS; return PSMOUSE_IMPS;
} }
...@@ -473,12 +530,7 @@ static int psmouse_probe(struct psmouse *psmouse) ...@@ -473,12 +530,7 @@ static int psmouse_probe(struct psmouse *psmouse)
if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_RESET_DIS)) if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_RESET_DIS))
printk(KERN_WARNING "psmouse.c: Failed to reset mouse on %s\n", psmouse->serio->phys); printk(KERN_WARNING "psmouse.c: Failed to reset mouse on %s\n", psmouse->serio->phys);
/* return 0;
* And here we try to determine if it has any extensions over the
* basic PS/2 3-button mouse.
*/
return psmouse->type = psmouse_extensions(psmouse);
} }
/* /*
...@@ -616,7 +668,6 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev) ...@@ -616,7 +668,6 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
psmouse->state = PSMOUSE_CMD_MODE; psmouse->state = PSMOUSE_CMD_MODE;
psmouse->serio = serio; psmouse->serio = serio;
psmouse->dev.private = psmouse; psmouse->dev.private = psmouse;
...@@ -628,13 +679,21 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev) ...@@ -628,13 +679,21 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
return; return;
} }
if (psmouse_probe(psmouse) <= 0) { if (psmouse_probe(psmouse) < 0) {
serio_close(serio); serio_close(serio);
kfree(psmouse); kfree(psmouse);
serio->private = NULL; serio->private = NULL;
return; return;
} }
psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1);
if (!psmouse->vendor)
psmouse->vendor = "Generic";
if (!psmouse->name)
psmouse->name = "Mouse";
if (!psmouse->protocol_handler)
psmouse->protocol_handler = psmouse_process_byte;
sprintf(psmouse->devname, "%s %s %s", sprintf(psmouse->devname, "%s %s %s",
psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name); psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name);
sprintf(psmouse->phys, "%s/input0", sprintf(psmouse->phys, "%s/input0",
...@@ -668,27 +727,24 @@ static int psmouse_reconnect(struct serio *serio) ...@@ -668,27 +727,24 @@ static int psmouse_reconnect(struct serio *serio)
{ {
struct psmouse *psmouse = serio->private; struct psmouse *psmouse = serio->private;
struct serio_dev *dev = serio->dev; struct serio_dev *dev = serio->dev;
int old_type;
if (!dev || !psmouse) { if (!dev || !psmouse) {
printk(KERN_DEBUG "psmouse: reconnect request, but serio is disconnected, ignoring...\n"); printk(KERN_DEBUG "psmouse: reconnect request, but serio is disconnected, ignoring...\n");
return -1; return -1;
} }
old_type = psmouse->type;
psmouse->state = PSMOUSE_CMD_MODE; psmouse->state = PSMOUSE_CMD_MODE;
psmouse->type = psmouse->acking = psmouse->cmdcnt = psmouse->pktcnt = 0; psmouse->acking = psmouse->cmdcnt = psmouse->pktcnt = psmouse->out_of_sync = 0;
if (psmouse->reconnect) { if (psmouse->reconnect) {
if (psmouse->reconnect(psmouse)) if (psmouse->reconnect(psmouse))
return -1; return -1;
} else if (psmouse_probe(psmouse) != old_type) } else if (psmouse_probe(psmouse) < 0 ||
psmouse->type != psmouse_extensions(psmouse, psmouse_max_proto, 0))
return -1; return -1;
/* ok, the device type (and capabilities) match the old one, /* ok, the device type (and capabilities) match the old one,
* we can continue using it, complete intialization * we can continue using it, complete intialization
*/ */
psmouse->type = old_type;
psmouse_initialize(psmouse); psmouse_initialize(psmouse);
if (psmouse->ptport) { if (psmouse->ptport) {
......
...@@ -22,6 +22,13 @@ ...@@ -22,6 +22,13 @@
#define PSMOUSE_ACTIVATED 1 #define PSMOUSE_ACTIVATED 1
#define PSMOUSE_IGNORE 2 #define PSMOUSE_IGNORE 2
/* psmouse protocol handler return codes */
typedef enum {
PSMOUSE_BAD_DATA,
PSMOUSE_GOOD_DATA,
PSMOUSE_FULL_PACKET
} psmouse_ret_t;
struct psmouse; struct psmouse;
struct psmouse_ptport { struct psmouse_ptport {
...@@ -45,6 +52,7 @@ struct psmouse { ...@@ -45,6 +52,7 @@ struct psmouse {
unsigned char type; unsigned char type;
unsigned char model; unsigned char model;
unsigned long last; unsigned long last;
unsigned long out_of_sync;
unsigned char state; unsigned char state;
char acking; char acking;
volatile char ack; volatile char ack;
...@@ -52,6 +60,7 @@ struct psmouse { ...@@ -52,6 +60,7 @@ struct psmouse {
char devname[64]; char devname[64];
char phys[32]; char phys[32];
psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs);
int (*reconnect)(struct psmouse *psmouse); int (*reconnect)(struct psmouse *psmouse);
void (*disconnect)(struct psmouse *psmouse); void (*disconnect)(struct psmouse *psmouse);
}; };
...@@ -65,10 +74,10 @@ struct psmouse { ...@@ -65,10 +74,10 @@ struct psmouse {
#define PSMOUSE_SYNAPTICS 7 #define PSMOUSE_SYNAPTICS 7
int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command); int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command);
int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command);
int psmouse_reset(struct psmouse *psmouse); int psmouse_reset(struct psmouse *psmouse);
extern int psmouse_smartscroll; extern int psmouse_smartscroll;
extern unsigned int psmouse_rate; extern unsigned int psmouse_rate;
extern unsigned int psmouse_resetafter;
#endif /* _PSMOUSE_H */ #endif /* _PSMOUSE_H */
This diff is collapsed.
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#ifndef _SYNAPTICS_H #ifndef _SYNAPTICS_H
#define _SYNAPTICS_H #define _SYNAPTICS_H
extern void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs);
extern int synaptics_detect(struct psmouse *psmouse); extern int synaptics_detect(struct psmouse *psmouse);
extern int synaptics_init(struct psmouse *psmouse); extern int synaptics_init(struct psmouse *psmouse);
extern void synaptics_reset(struct psmouse *psmouse); extern void synaptics_reset(struct psmouse *psmouse);
...@@ -44,13 +43,14 @@ extern void synaptics_reset(struct psmouse *psmouse); ...@@ -44,13 +43,14 @@ extern void synaptics_reset(struct psmouse *psmouse);
/* synaptics capability bits */ /* synaptics capability bits */
#define SYN_CAP_EXTENDED(c) ((c) & (1 << 23)) #define SYN_CAP_EXTENDED(c) ((c) & (1 << 23))
#define SYN_CAP_MIDDLE_BUTTON(c) ((c) & (1 << 18))
#define SYN_CAP_PASS_THROUGH(c) ((c) & (1 << 7)) #define SYN_CAP_PASS_THROUGH(c) ((c) & (1 << 7))
#define SYN_CAP_SLEEP(c) ((c) & (1 << 4)) #define SYN_CAP_SLEEP(c) ((c) & (1 << 4))
#define SYN_CAP_FOUR_BUTTON(c) ((c) & (1 << 3)) #define SYN_CAP_FOUR_BUTTON(c) ((c) & (1 << 3))
#define SYN_CAP_MULTIFINGER(c) ((c) & (1 << 1)) #define SYN_CAP_MULTIFINGER(c) ((c) & (1 << 1))
#define SYN_CAP_PALMDETECT(c) ((c) & (1 << 0)) #define SYN_CAP_PALMDETECT(c) ((c) & (1 << 0))
#define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47) #define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47)
#define SYN_EXT_CAP_REQUESTS(c) ((((c) & 0x700000) >> 20) == 1) #define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20)
#define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) #define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12)
/* synaptics modes query bits */ /* synaptics modes query bits */
...@@ -86,18 +86,12 @@ struct synaptics_hw_state { ...@@ -86,18 +86,12 @@ struct synaptics_hw_state {
int y; int y;
int z; int z;
int w; int w;
int left; unsigned int left:1;
int right; unsigned int right:1;
int up; unsigned int middle:1;
int down; unsigned int up:1;
int b0; unsigned int down:1;
int b1; unsigned char ext_buttons;
int b2;
int b3;
int b4;
int b5;
int b6;
int b7;
}; };
struct synaptics_data { struct synaptics_data {
...@@ -108,7 +102,6 @@ struct synaptics_data { ...@@ -108,7 +102,6 @@ struct synaptics_data {
unsigned long int identity; /* Identification */ unsigned long int identity; /* Identification */
/* Data for normal processing */ /* Data for normal processing */
unsigned int out_of_sync; /* # of packets out of sync */
int old_w; /* Previous w value */ int old_w; /* Previous w value */
unsigned char pkt_type; /* packet type - old, new, etc */ unsigned char pkt_type; /* packet type - old, new, etc */
}; };
......
...@@ -86,20 +86,9 @@ static int parkbd_write(struct serio *port, unsigned char c) ...@@ -86,20 +86,9 @@ static int parkbd_write(struct serio *port, unsigned char c)
return 0; return 0;
} }
static int parkbd_open(struct serio *port)
{
return 0;
}
static void parkbd_close(struct serio *port)
{
}
static struct serio parkbd_port = static struct serio parkbd_port =
{ {
.write = parkbd_write, .write = parkbd_write,
.open = parkbd_open,
.close = parkbd_close,
.name = parkbd_name, .name = parkbd_name,
.phys = parkbd_phys, .phys = parkbd_phys,
}; };
......
...@@ -47,23 +47,12 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); ...@@ -47,23 +47,12 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Q40 PS/2 keyboard controller driver"); MODULE_DESCRIPTION("Q40 PS/2 keyboard controller driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static int q40kbd_open(struct serio *port)
{
return 0;
}
static void q40kbd_close(struct serio *port)
{
}
static struct serio q40kbd_port = static struct serio q40kbd_port =
{ {
.type = SERIO_8042, .type = SERIO_8042,
.name = "Q40 kbd port", .name = "Q40 kbd port",
.phys = "Q40", .phys = "Q40",
.write = NULL, .write = NULL,
.open = q40kbd_open,
.close = q40kbd_close,
}; };
static irqreturn_t q40kbd_interrupt(int irq, void *dev_id, static irqreturn_t q40kbd_interrupt(int irq, void *dev_id,
......
...@@ -11,18 +11,18 @@ ...@@ -11,18 +11,18 @@
/* /*
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
* Should you need to contact me, the author, you can do so either by * Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
...@@ -108,7 +108,7 @@ void serio_handle_events(void) ...@@ -108,7 +108,7 @@ void serio_handle_events(void)
struct serio_event *event; struct serio_event *event;
list_for_each_safe(node, next, &serio_event_list) { list_for_each_safe(node, next, &serio_event_list) {
event = container_of(node, struct serio_event, node); event = container_of(node, struct serio_event, node);
down(&serio_sem); down(&serio_sem);
if (event->serio == NULL) if (event->serio == NULL)
...@@ -152,7 +152,7 @@ static int serio_thread(void *nothing) ...@@ -152,7 +152,7 @@ static int serio_thread(void *nothing)
do { do {
serio_handle_events(); serio_handle_events();
wait_event_interruptible(serio_wait, !list_empty(&serio_event_list)); wait_event_interruptible(serio_wait, !list_empty(&serio_event_list));
if (current->flags & PF_FREEZE) if (current->flags & PF_FREEZE)
refrigerator(PF_FREEZE); refrigerator(PF_FREEZE);
} while (!signal_pending(current)); } while (!signal_pending(current));
...@@ -293,7 +293,7 @@ void serio_unregister_device(struct serio_dev *dev) ...@@ -293,7 +293,7 @@ void serio_unregister_device(struct serio_dev *dev)
int serio_open(struct serio *serio, struct serio_dev *dev) int serio_open(struct serio *serio, struct serio_dev *dev)
{ {
serio->dev = dev; serio->dev = dev;
if (serio->open(serio)) { if (serio->open && serio->open(serio)) {
serio->dev = NULL; serio->dev = NULL;
return -1; return -1;
} }
...@@ -303,7 +303,8 @@ int serio_open(struct serio *serio, struct serio_dev *dev) ...@@ -303,7 +303,8 @@ int serio_open(struct serio *serio, struct serio_dev *dev)
/* called from serio_dev->connect/disconnect methods under serio_sem */ /* called from serio_dev->connect/disconnect methods under serio_sem */
void serio_close(struct serio *serio) void serio_close(struct serio *serio)
{ {
serio->close(serio); if (serio->close)
serio->close(serio);
serio->dev = NULL; serio->dev = NULL;
} }
......
...@@ -48,11 +48,6 @@ static int serport_serio_write(struct serio *serio, unsigned char data) ...@@ -48,11 +48,6 @@ static int serport_serio_write(struct serio *serio, unsigned char data)
return -(serport->tty->driver->write(serport->tty, 0, &data, 1) != 1); return -(serport->tty->driver->write(serport->tty, 0, &data, 1) != 1);
} }
static int serport_serio_open(struct serio *serio)
{
return 0;
}
static void serport_serio_close(struct serio *serio) static void serport_serio_close(struct serio *serio)
{ {
struct serport *serport = serio->driver; struct serport *serport = serio->driver;
...@@ -87,7 +82,6 @@ static int serport_ldisc_open(struct tty_struct *tty) ...@@ -87,7 +82,6 @@ static int serport_ldisc_open(struct tty_struct *tty)
serport->serio.type = SERIO_RS232; serport->serio.type = SERIO_RS232;
serport->serio.write = serport_serio_write; serport->serio.write = serport_serio_write;
serport->serio.open = serport_serio_open;
serport->serio.close = serport_serio_close; serport->serio.close = serport_serio_close;
serport->serio.driver = serport; serport->serio.driver = serport;
...@@ -135,7 +129,7 @@ static int serport_ldisc_room(struct tty_struct *tty) ...@@ -135,7 +129,7 @@ static int serport_ldisc_room(struct tty_struct *tty)
} }
/* /*
* serport_ldisc_read() just waits indefinitely if everything goes well. * serport_ldisc_read() just waits indefinitely if everything goes well.
* However, when the serio driver closes the serio port, it finishes, * However, when the serio driver closes the serio port, it finishes,
* returning 0 characters. * returning 0 characters.
*/ */
...@@ -165,7 +159,7 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u ...@@ -165,7 +159,7 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg) static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg)
{ {
struct serport *serport = (struct serport*) tty->disc_data; struct serport *serport = (struct serport*) tty->disc_data;
if (cmd == SPIOCSTYPE) if (cmd == SPIOCSTYPE)
return get_user(serport->serio.type, (unsigned long *) arg); return get_user(serport->serio.type, (unsigned long *) arg);
......
...@@ -124,12 +124,10 @@ static void gunze_connect(struct serio *serio, struct serio_dev *dev) ...@@ -124,12 +124,10 @@ static void gunze_connect(struct serio *serio, struct serio_dev *dev)
memset(gunze, 0, sizeof(struct gunze)); memset(gunze, 0, sizeof(struct gunze));
init_input_dev(&gunze->dev); init_input_dev(&gunze->dev);
gunze->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); gunze->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
gunze->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
gunze->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); gunze->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
input_set_abs_params(&gunze->dev, ABS_X, 96, 4000, 0, 0);
gunze->dev.absmin[ABS_X] = 96; gunze->dev.absmin[ABS_Y] = 72; input_set_abs_params(&gunze->dev, ABS_Y, 72, 3000, 0, 0);
gunze->dev.absmax[ABS_X] = 4000; gunze->dev.absmax[ABS_Y] = 3000;
gunze->serio = serio; gunze->serio = serio;
serio->private = gunze; serio->private = gunze;
......
/* /*
* $Id: h3600_ts_input.c,v 1.4 2002/01/23 06:39:37 jsimmons Exp $ * $Id: h3600_ts_input.c,v 1.4 2002/01/23 06:39:37 jsimmons Exp $
* *
* Copyright (c) 2001 "Crazy" James Simmons jsimmons@transvirtual.com * Copyright (c) 2001 "Crazy" James Simmons jsimmons@transvirtual.com
* *
* Sponsored by Transvirtual Technology. * Sponsored by Transvirtual Technology.
* *
* Derived from the code in h3600_ts.[ch] by Charles Flynn * Derived from the code in h3600_ts.[ch] by Charles Flynn
*/ */
/* /*
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
#define MAX_ID 14 #define MAX_ID 14
#define H3600_MAX_LENGTH 16 #define H3600_MAX_LENGTH 16
#define H3600_KEY 0xf #define H3600_KEY 0xf
#define H3600_SCANCODE_RECORD 1 /* 1 -> record button */ #define H3600_SCANCODE_RECORD 1 /* 1 -> record button */
#define H3600_SCANCODE_CALENDAR 2 /* 2 -> calendar */ #define H3600_SCANCODE_CALENDAR 2 /* 2 -> calendar */
...@@ -118,13 +118,13 @@ static void npower_button_handler(int irq, void *dev_id, struct pt_regs *regs) ...@@ -118,13 +118,13 @@ static void npower_button_handler(int irq, void *dev_id, struct pt_regs *regs)
int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1; int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1;
struct input_dev *dev = (struct input_dev *) dev_id; struct input_dev *dev = (struct input_dev *) dev_id;
/* /*
* This interrupt is only called when we release the key. So we have * This interrupt is only called when we release the key. So we have
* to fake a key press. * to fake a key press.
*/ */
input_regs(dev, regs); input_regs(dev, regs);
input_report_key(dev, KEY_SUSPEND, 1); input_report_key(dev, KEY_SUSPEND, 1);
input_report_key(dev, KEY_SUSPEND, down); input_report_key(dev, KEY_SUSPEND, down);
input_sync(dev); input_sync(dev);
} }
...@@ -144,18 +144,18 @@ unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr) ...@@ -144,18 +144,18 @@ unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr)
unsigned char brightness = ((pwr==FLITE_PWR_OFF) ? 0:flite_brightness); unsigned char brightness = ((pwr==FLITE_PWR_OFF) ? 0:flite_brightness);
struct h3600_dev *ts = dev->private; struct h3600_dev *ts = dev->private;
/* Must be in this order */ /* Must be in this order */
ts->serio->write(ts->serio, 1); ts->serio->write(ts->serio, 1);
ts->serio->write(ts->serio, pwr); ts->serio->write(ts->serio, pwr);
ts->serio->write(ts->serio, brightness); ts->serio->write(ts->serio, brightness);
return 0; return 0;
} }
static int suspended = 0; static int suspended = 0;
static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req, static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req,
void *data) void *data)
{ {
struct input_dev *dev = (struct input_dev *) data; struct input_dev *dev = (struct input_dev *) data;
switch (req) { switch (req) {
case PM_SUSPEND: /* enter D1-D3 */ case PM_SUSPEND: /* enter D1-D3 */
...@@ -183,7 +183,7 @@ static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req, ...@@ -183,7 +183,7 @@ static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req,
/* /*
* This function translates the native event packets to linux input event * This function translates the native event packets to linux input event
* packets. Some packets coming from serial are not touchscreen related. In * packets. Some packets coming from serial are not touchscreen related. In
* this case we send them off to be processed elsewhere. * this case we send them off to be processed elsewhere.
*/ */
static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs)
{ {
...@@ -206,7 +206,7 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) ...@@ -206,7 +206,7 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs)
Note: This is true for non interrupt generated key events. Note: This is true for non interrupt generated key events.
*/ */
case KEYBD_ID: case KEYBD_ID:
down = (ts->buf[0] & 0x80) ? 0 : 1; down = (ts->buf[0] & 0x80) ? 0 : 1;
switch (ts->buf[0] & 0x7f) { switch (ts->buf[0] & 0x7f) {
case H3600_SCANCODE_RECORD: case H3600_SCANCODE_RECORD:
...@@ -218,7 +218,7 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) ...@@ -218,7 +218,7 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs)
case H3600_SCANCODE_CONTACTS: case H3600_SCANCODE_CONTACTS:
key = KEY_PROG2; key = KEY_PROG2;
break; break;
case H3600_SCANCODE_Q: case H3600_SCANCODE_Q:
key = KEY_Q; key = KEY_Q;
break; break;
case H3600_SCANCODE_START: case H3600_SCANCODE_START:
...@@ -237,9 +237,9 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) ...@@ -237,9 +237,9 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs)
key = KEY_DOWN; key = KEY_DOWN;
break; break;
default: default:
key = 0; key = 0;
} }
if (key) if (key)
input_report_key(dev, key, down); input_report_key(dev, key, down);
break; break;
/* /*
...@@ -251,13 +251,13 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) ...@@ -251,13 +251,13 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs)
* byte 0 1 2 3 * byte 0 1 2 3
*/ */
case TOUCHS_ID: case TOUCHS_ID:
if (!touched) { if (!touched) {
input_report_key(dev, BTN_TOUCH, 1); input_report_key(dev, BTN_TOUCH, 1);
touched = 1; touched = 1;
} }
if (ts->len) { if (ts->len) {
unsigned short x, y; unsigned short x, y;
x = ts->buf[0]; x <<= 8; x += ts->buf[1]; x = ts->buf[0]; x <<= 8; x += ts->buf[1];
y = ts->buf[2]; y <<= 8; y += ts->buf[3]; y = ts->buf[2]; y <<= 8; y += ts->buf[3];
...@@ -267,7 +267,7 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) ...@@ -267,7 +267,7 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs)
} else { } else {
input_report_key(dev, BTN_TOUCH, 0); input_report_key(dev, BTN_TOUCH, 0);
touched = 0; touched = 0;
} }
break; break;
default: default:
/* Send a non input event elsewhere */ /* Send a non input event elsewhere */
...@@ -280,7 +280,7 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) ...@@ -280,7 +280,7 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs)
/* /*
* h3600ts_event() handles events from the input module. * h3600ts_event() handles events from the input module.
*/ */
static int h3600ts_event(struct input_dev *dev, unsigned int type, static int h3600ts_event(struct input_dev *dev, unsigned int type,
unsigned int code, int value) unsigned int code, int value)
{ {
struct h3600_dev *ts = dev->private; struct h3600_dev *ts = dev->private;
...@@ -290,7 +290,7 @@ static int h3600ts_event(struct input_dev *dev, unsigned int type, ...@@ -290,7 +290,7 @@ static int h3600ts_event(struct input_dev *dev, unsigned int type,
// ts->serio->write(ts->serio, SOME_CMD); // ts->serio->write(ts->serio, SOME_CMD);
return 0; return 0;
} }
} }
return -1; return -1;
} }
...@@ -323,12 +323,12 @@ static void h3600ts_interrupt(struct serio *serio, unsigned char data, ...@@ -323,12 +323,12 @@ static void h3600ts_interrupt(struct serio *serio, unsigned char data,
struct h3600_dev *ts = serio->private; struct h3600_dev *ts = serio->private;
/* /*
* We have a new frame coming in. * We have a new frame coming in.
*/ */
switch (state) { switch (state) {
case STATE_SOF: case STATE_SOF:
if (data == CHAR_SOF) if (data == CHAR_SOF)
state = STATE_ID; state = STATE_ID;
return; return;
case STATE_ID: case STATE_ID:
ts->event = (data & 0xf0) >> 4; ts->event = (data & 0xf0) >> 4;
...@@ -344,7 +344,7 @@ static void h3600ts_interrupt(struct serio *serio, unsigned char data, ...@@ -344,7 +344,7 @@ static void h3600ts_interrupt(struct serio *serio, unsigned char data,
case STATE_DATA: case STATE_DATA:
ts->chksum += data; ts->chksum += data;
ts->buf[ts->idx]= data; ts->buf[ts->idx]= data;
if(++ts->idx == ts->len) if(++ts->idx == ts->len)
state = STATE_EOF; state = STATE_EOF;
break; break;
case STATE_EOF: case STATE_EOF:
...@@ -382,7 +382,7 @@ static void h3600ts_connect(struct serio *serio, struct serio_dev *dev) ...@@ -382,7 +382,7 @@ static void h3600ts_connect(struct serio *serio, struct serio_dev *dev)
set_GPIO_IRQ_edge( GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE ); set_GPIO_IRQ_edge( GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE );
if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler, if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler,
SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM,
"h3600_action", &ts->dev)) { "h3600_action", &ts->dev)) {
printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n"); printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n");
kfree(ts); kfree(ts);
...@@ -390,24 +390,19 @@ static void h3600ts_connect(struct serio *serio, struct serio_dev *dev) ...@@ -390,24 +390,19 @@ static void h3600ts_connect(struct serio *serio, struct serio_dev *dev)
} }
if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler, if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler,
SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM,
"h3600_suspend", &ts->dev)) { "h3600_suspend", &ts->dev)) {
free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev); free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev);
printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n"); printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n");
kfree(ts); kfree(ts);
return; return;
} }
/* Now we have things going we setup our input device */ /* Now we have things going we setup our input device */
ts->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_LED) | BIT(EV_PWR); ts->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_LED) | BIT(EV_PWR);
ts->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); ts->dev.ledbit[0] = BIT(LED_SLEEP);
ts->dev.ledbit[0] = BIT(LED_SLEEP); input_set_abs_params(&ts->dev, ABS_X, 60, 985, 0, 0);
input_set_abs_params(&ts->dev, ABS_Y, 35, 1024, 0, 0);
ts->dev.absmin[ABS_X] = 60; ts->dev.absmin[ABS_Y] = 35;
ts->dev.absmax[ABS_X] = 985; ts->dev.absmax[ABS_Y] = 1024;
ts->dev.absfuzz[ABS_X] = 0; ts->dev.absfuzz[ABS_Y] = 0;
ts->serio = serio;
serio->private = ts;
set_bit(KEY_RECORD, ts->dev.keybit); set_bit(KEY_RECORD, ts->dev.keybit);
set_bit(KEY_Q, ts->dev.keybit); set_bit(KEY_Q, ts->dev.keybit);
...@@ -422,6 +417,9 @@ static void h3600ts_connect(struct serio *serio, struct serio_dev *dev) ...@@ -422,6 +417,9 @@ static void h3600ts_connect(struct serio *serio, struct serio_dev *dev)
ts->dev.keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH); ts->dev.keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
ts->dev.keybit[LONG(KEY_SUSPEND)] |= BIT(KEY_SUSPEND); ts->dev.keybit[LONG(KEY_SUSPEND)] |= BIT(KEY_SUSPEND);
ts->serio = serio;
serio->private = ts;
sprintf(ts->phys, "%s/input0", serio->phys); sprintf(ts->phys, "%s/input0", serio->phys);
ts->dev.event = h3600ts_event; ts->dev.event = h3600ts_event;
...@@ -442,7 +440,7 @@ static void h3600ts_connect(struct serio *serio, struct serio_dev *dev) ...@@ -442,7 +440,7 @@ static void h3600ts_connect(struct serio *serio, struct serio_dev *dev)
//h3600_flite_control(1, 25); /* default brightness */ //h3600_flite_control(1, 25); /* default brightness */
#ifdef CONFIG_PM #ifdef CONFIG_PM
ts->dev.pm_dev = pm_register(PM_ILLUMINATION_DEV, PM_SYS_LIGHT, ts->dev.pm_dev = pm_register(PM_ILLUMINATION_DEV, PM_SYS_LIGHT,
h3600ts_pm_callback); h3600ts_pm_callback);
printk("registered pm callback\n"); printk("registered pm callback\n");
#endif #endif
...@@ -458,7 +456,7 @@ static void h3600ts_connect(struct serio *serio, struct serio_dev *dev) ...@@ -458,7 +456,7 @@ static void h3600ts_connect(struct serio *serio, struct serio_dev *dev)
static void h3600ts_disconnect(struct serio *serio) static void h3600ts_disconnect(struct serio *serio)
{ {
struct h3600_dev *ts = serio->private; struct h3600_dev *ts = serio->private;
free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev); free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev);
free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, &ts->dev); free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, &ts->dev);
input_unregister_device(&ts->dev); input_unregister_device(&ts->dev);
......
...@@ -655,7 +655,7 @@ struct ff_periodic_effect { ...@@ -655,7 +655,7 @@ struct ff_periodic_effect {
struct ff_envelope envelope; struct ff_envelope envelope;
/* Only used if waveform == FF_CUSTOM */ /* Only used if waveform == FF_CUSTOM */
__u32 custom_len; /* Number of samples */ __u32 custom_len; /* Number of samples */
__s16 *custom_data; /* Buffer of samples */ __s16 *custom_data; /* Buffer of samples */
/* Note: the data pointed by custom_data is copied by the driver. You can /* Note: the data pointed by custom_data is copied by the driver. You can
* therefore dispose of the memory after the upload/update */ * therefore dispose of the memory after the upload/update */
...@@ -749,8 +749,6 @@ struct ff_effect { ...@@ -749,8 +749,6 @@ struct ff_effect {
#define INPUT_KEYCODE(dev, scancode) ((dev->keycodesize == 1) ? ((u8*)dev->keycode)[scancode] : \ #define INPUT_KEYCODE(dev, scancode) ((dev->keycodesize == 1) ? ((u8*)dev->keycode)[scancode] : \
((dev->keycodesize == 2) ? ((u16*)dev->keycode)[scancode] : (((u32*)dev->keycode)[scancode]))) ((dev->keycodesize == 2) ? ((u16*)dev->keycode)[scancode] : (((u32*)dev->keycode)[scancode])))
#define init_input_dev(dev) do { INIT_LIST_HEAD(&((dev)->h_list)); INIT_LIST_HEAD(&((dev)->node)); } while (0)
#define SET_INPUT_KEYCODE(dev, scancode, val) \ #define SET_INPUT_KEYCODE(dev, scancode, val) \
({ unsigned __old; \ ({ unsigned __old; \
switch (dev->keycodesize) { \ switch (dev->keycodesize) { \
...@@ -915,6 +913,12 @@ struct input_handle { ...@@ -915,6 +913,12 @@ struct input_handle {
#define to_handle(n) container_of(n,struct input_handle,d_node) #define to_handle(n) container_of(n,struct input_handle,d_node)
#define to_handle_h(n) container_of(n,struct input_handle,h_node) #define to_handle_h(n) container_of(n,struct input_handle,h_node)
static inline void init_input_dev(struct input_dev *dev)
{
INIT_LIST_HEAD(&dev->h_list);
INIT_LIST_HEAD(&dev->node);
}
void input_register_device(struct input_dev *); void input_register_device(struct input_dev *);
void input_unregister_device(struct input_dev *); void input_unregister_device(struct input_dev *);
...@@ -932,14 +936,51 @@ int input_flush_device(struct input_handle* handle, struct file* file); ...@@ -932,14 +936,51 @@ int input_flush_device(struct input_handle* handle, struct file* file);
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value); void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
#define input_report_key(a,b,c) input_event(a, EV_KEY, b, !!(c)) static inline void input_report_key(struct input_dev *dev, unsigned int code, int value)
#define input_report_rel(a,b,c) input_event(a, EV_REL, b, c) {
#define input_report_abs(a,b,c) input_event(a, EV_ABS, b, c) input_event(dev, EV_KEY, code, !!value);
#define input_report_ff(a,b,c) input_event(a, EV_FF, b, c) }
#define input_report_ff_status(a,b,c) input_event(a, EV_FF_STATUS, b, c)
static inline void input_report_rel(struct input_dev *dev, unsigned int code, int value)
#define input_regs(a,b) do { (a)->regs = (b); } while (0) {
#define input_sync(a) do { input_event(a, EV_SYN, SYN_REPORT, 0); (a)->regs = NULL; } while (0) input_event(dev, EV_REL, code, value);
}
static inline void input_report_abs(struct input_dev *dev, unsigned int code, int value)
{
input_event(dev, EV_ABS, code, value);
}
static inline void input_report_ff(struct input_dev *dev, unsigned int code, int value)
{
input_event(dev, EV_FF, code, value);
}
static inline void input_report_ff_status(struct input_dev *dev, unsigned int code, int value)
{
input_event(dev, EV_FF_STATUS, code, value);
}
static inline void input_regs(struct input_dev *dev, struct pt_regs *regs)
{
dev->regs = regs;
}
static inline void input_sync(struct input_dev *dev)
{
input_event(dev, EV_SYN, SYN_REPORT, 0);
dev->regs = NULL;
}
static inline void input_set_abs_params(struct input_dev *dev, int axis, int min, int max, int fuzz, int flat)
{
dev->absmin[axis] = min;
dev->absmax[axis] = max;
dev->absfuzz[axis] = fuzz;
dev->absflat[axis] = flat;
dev->absbit[LONG(axis)] |= BIT(axis);
}
extern struct class_simple *input_class; extern struct class_simple *input_class;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment