Commit e7de3690 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/dtor/input

parents 87530db5 eab9edd2
...@@ -348,6 +348,40 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable) ...@@ -348,6 +348,40 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable)
return 0; return 0;
} }
/*
* alps_poll() - poll the touchpad for current motion packet.
* Used in resync.
*/
static int alps_poll(struct psmouse *psmouse)
{
struct alps_data *priv = psmouse->private;
unsigned char buf[6];
int poll_failed;
if (priv->i->flags & ALPS_PASS)
alps_passthrough_mode(psmouse, 1);
poll_failed = ps2_command(&psmouse->ps2dev, buf,
PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0;
if (priv->i->flags & ALPS_PASS)
alps_passthrough_mode(psmouse, 0);
if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0)
return -1;
if ((psmouse->badbyte & 0xc8) == 0x08) {
/*
* Poll the track stick ...
*/
if (ps2_command(&psmouse->ps2dev, buf, PSMOUSE_CMD_POLL | (3 << 8)))
return -1;
}
memcpy(psmouse->packet, buf, sizeof(buf));
return 0;
}
static int alps_reconnect(struct psmouse *psmouse) static int alps_reconnect(struct psmouse *psmouse)
{ {
struct alps_data *priv = psmouse->private; struct alps_data *priv = psmouse->private;
...@@ -451,10 +485,14 @@ int alps_init(struct psmouse *psmouse) ...@@ -451,10 +485,14 @@ int alps_init(struct psmouse *psmouse)
input_register_device(priv->dev2); input_register_device(priv->dev2);
psmouse->protocol_handler = alps_process_byte; psmouse->protocol_handler = alps_process_byte;
psmouse->poll = alps_poll;
psmouse->disconnect = alps_disconnect; psmouse->disconnect = alps_disconnect;
psmouse->reconnect = alps_reconnect; psmouse->reconnect = alps_reconnect;
psmouse->pktsize = 6; psmouse->pktsize = 6;
/* We are having trouble resyncing ALPS touchpads so disable it for now */
psmouse->resync_time = 0;
return 0; return 0;
init_fail: init_fail:
......
...@@ -117,7 +117,7 @@ static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned cha ...@@ -117,7 +117,7 @@ static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned cha
if (psmouse_sliced_command(psmouse, command)) if (psmouse_sliced_command(psmouse, command))
return -1; return -1;
if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL)) if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL | 0x0300))
return -1; return -1;
return 0; return 0;
......
...@@ -54,10 +54,14 @@ static unsigned int psmouse_smartscroll = 1; ...@@ -54,10 +54,14 @@ static unsigned int psmouse_smartscroll = 1;
module_param_named(smartscroll, psmouse_smartscroll, bool, 0644); module_param_named(smartscroll, psmouse_smartscroll, bool, 0644);
MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");
static unsigned int psmouse_resetafter; static unsigned int psmouse_resetafter = 5;
module_param_named(resetafter, psmouse_resetafter, uint, 0644); module_param_named(resetafter, psmouse_resetafter, uint, 0644);
MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
static unsigned int psmouse_resync_time = 5;
module_param_named(resync_time, psmouse_resync_time, uint, 0644);
MODULE_PARM_DESC(resync_time, "How long can mouse stay idle before forcing resync (in seconds, 0 = never).");
PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO, PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO,
NULL, NULL,
psmouse_attr_show_protocol, psmouse_attr_set_protocol); psmouse_attr_show_protocol, psmouse_attr_set_protocol);
...@@ -70,12 +74,16 @@ PSMOUSE_DEFINE_ATTR(resolution, S_IWUSR | S_IRUGO, ...@@ -70,12 +74,16 @@ PSMOUSE_DEFINE_ATTR(resolution, S_IWUSR | S_IRUGO,
PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO, PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO,
(void *) offsetof(struct psmouse, resetafter), (void *) offsetof(struct psmouse, resetafter),
psmouse_show_int_attr, psmouse_set_int_attr); psmouse_show_int_attr, psmouse_set_int_attr);
PSMOUSE_DEFINE_ATTR(resync_time, S_IWUSR | S_IRUGO,
(void *) offsetof(struct psmouse, resync_time),
psmouse_show_int_attr, psmouse_set_int_attr);
static struct attribute *psmouse_attributes[] = { static struct attribute *psmouse_attributes[] = {
&psmouse_attr_protocol.dattr.attr, &psmouse_attr_protocol.dattr.attr,
&psmouse_attr_rate.dattr.attr, &psmouse_attr_rate.dattr.attr,
&psmouse_attr_resolution.dattr.attr, &psmouse_attr_resolution.dattr.attr,
&psmouse_attr_resetafter.dattr.attr, &psmouse_attr_resetafter.dattr.attr,
&psmouse_attr_resync_time.dattr.attr,
NULL NULL
}; };
...@@ -98,6 +106,8 @@ __obsolete_setup("psmouse_rate="); ...@@ -98,6 +106,8 @@ __obsolete_setup("psmouse_rate=");
*/ */
static DECLARE_MUTEX(psmouse_sem); static DECLARE_MUTEX(psmouse_sem);
static struct workqueue_struct *kpsmoused_wq;
struct psmouse_protocol { struct psmouse_protocol {
enum psmouse_type type; enum psmouse_type type;
char *name; char *name;
...@@ -178,15 +188,79 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse, struct pt_reg ...@@ -178,15 +188,79 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse, struct pt_reg
} }
/* /*
* psmouse_interrupt() handles incoming characters, either gathering them into * __psmouse_set_state() sets new psmouse state and resets all flags.
* packets or passing them to the command routine as command output. */
static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
{
psmouse->state = new_state;
psmouse->pktcnt = psmouse->out_of_sync = 0;
psmouse->ps2dev.flags = 0;
psmouse->last = jiffies;
}
/*
* psmouse_set_state() sets new psmouse state and resets all flags and
* counters while holding serio lock so fighting with interrupt handler
* is not a concern.
*/
static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
{
serio_pause_rx(psmouse->ps2dev.serio);
__psmouse_set_state(psmouse, new_state);
serio_continue_rx(psmouse->ps2dev.serio);
}
/*
* psmouse_handle_byte() processes one byte of the input data stream
* by calling corresponding protocol handler.
*/
static int psmouse_handle_byte(struct psmouse *psmouse, struct pt_regs *regs)
{
psmouse_ret_t rc = psmouse->protocol_handler(psmouse, regs);
switch (rc) {
case PSMOUSE_BAD_DATA:
if (psmouse->state == PSMOUSE_ACTIVATED) {
printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n",
psmouse->name, psmouse->phys, psmouse->pktcnt);
if (++psmouse->out_of_sync == psmouse->resetafter) {
__psmouse_set_state(psmouse, PSMOUSE_IGNORE);
printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n");
serio_reconnect(psmouse->ps2dev.serio);
return -1;
}
}
psmouse->pktcnt = 0;
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;
}
return 0;
}
/*
* psmouse_interrupt() handles incoming characters, either passing them
* for normal processing or gathering them as command response.
*/ */
static irqreturn_t psmouse_interrupt(struct serio *serio, 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_get_drvdata(serio); struct psmouse *psmouse = serio_get_drvdata(serio);
psmouse_ret_t rc;
if (psmouse->state == PSMOUSE_IGNORE) if (psmouse->state == PSMOUSE_IGNORE)
goto out; goto out;
...@@ -208,67 +282,58 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, ...@@ -208,67 +282,58 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
if (ps2_handle_response(&psmouse->ps2dev, data)) if (ps2_handle_response(&psmouse->ps2dev, data))
goto out; goto out;
if (psmouse->state == PSMOUSE_INITIALIZING) if (psmouse->state <= PSMOUSE_RESYNCING)
goto out; goto out;
if (psmouse->state == PSMOUSE_ACTIVATED && if (psmouse->state == PSMOUSE_ACTIVATED &&
psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) { psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {
printk(KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n", printk(KERN_INFO "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n",
psmouse->name, psmouse->phys, psmouse->pktcnt); psmouse->name, psmouse->phys, psmouse->pktcnt);
psmouse->pktcnt = 0; psmouse->badbyte = psmouse->packet[0];
__psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
queue_work(kpsmoused_wq, &psmouse->resync_work);
goto out;
} }
psmouse->last = jiffies;
psmouse->packet[psmouse->pktcnt++] = data; psmouse->packet[psmouse->pktcnt++] = data;
/*
if (psmouse->packet[0] == PSMOUSE_RET_BAT) { * Check if this is a new device announcement (0xAA 0x00)
*/
if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) {
if (psmouse->pktcnt == 1) if (psmouse->pktcnt == 1)
goto out; goto out;
if (psmouse->pktcnt == 2) {
if (psmouse->packet[1] == PSMOUSE_RET_ID) { if (psmouse->packet[1] == PSMOUSE_RET_ID) {
psmouse->state = PSMOUSE_IGNORE; __psmouse_set_state(psmouse, PSMOUSE_IGNORE);
serio_reconnect(serio); serio_reconnect(serio);
goto out; goto out;
} }
if (psmouse->type == PSMOUSE_SYNAPTICS) { /*
/* neither 0xAA nor 0x00 are valid first bytes * Not a new device, try processing first byte normally
* for a packet in absolute mode
*/ */
psmouse->pktcnt = 0; psmouse->pktcnt = 1;
if (psmouse_handle_byte(psmouse, regs))
goto out; goto out;
}
}
}
rc = psmouse->protocol_handler(psmouse, regs); psmouse->packet[psmouse->pktcnt++] = data;
switch (rc) {
case PSMOUSE_BAD_DATA:
printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n",
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->ps2dev.serio);
} }
break;
case PSMOUSE_FULL_PACKET: /*
psmouse->pktcnt = 0; * See if we need to force resync because mouse was idle for too long
if (psmouse->out_of_sync) { */
psmouse->out_of_sync = 0; if (psmouse->state == PSMOUSE_ACTIVATED &&
printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", psmouse->pktcnt == 1 && psmouse->resync_time &&
psmouse->name, psmouse->phys); time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) {
psmouse->badbyte = psmouse->packet[0];
__psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
queue_work(kpsmoused_wq, &psmouse->resync_work);
goto out;
} }
break;
case PSMOUSE_GOOD_DATA: psmouse->last = jiffies;
break; psmouse_handle_byte(psmouse, regs);
}
out: out:
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -751,21 +816,6 @@ static void psmouse_initialize(struct psmouse *psmouse) ...@@ -751,21 +816,6 @@ static void psmouse_initialize(struct psmouse *psmouse)
} }
} }
/*
* psmouse_set_state() sets new psmouse state and resets all flags and
* counters while holding serio lock so fighting with interrupt handler
* is not a concern.
*/
static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
{
serio_pause_rx(psmouse->ps2dev.serio);
psmouse->state = new_state;
psmouse->pktcnt = psmouse->out_of_sync = 0;
psmouse->ps2dev.flags = 0;
serio_continue_rx(psmouse->ps2dev.serio);
}
/* /*
* psmouse_activate() enables the mouse so that we get motion reports from it. * psmouse_activate() enables the mouse so that we get motion reports from it.
*/ */
...@@ -794,6 +844,111 @@ static void psmouse_deactivate(struct psmouse *psmouse) ...@@ -794,6 +844,111 @@ static void psmouse_deactivate(struct psmouse *psmouse)
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
} }
/*
* psmouse_poll() - default poll hanlder. Everyone except for ALPS uses it.
*/
static int psmouse_poll(struct psmouse *psmouse)
{
return ps2_command(&psmouse->ps2dev, psmouse->packet,
PSMOUSE_CMD_POLL | (psmouse->pktsize << 8));
}
/*
* psmouse_resync() attempts to re-validate current protocol.
*/
static void psmouse_resync(void *p)
{
struct psmouse *psmouse = p, *parent = NULL;
struct serio *serio = psmouse->ps2dev.serio;
psmouse_ret_t rc = PSMOUSE_GOOD_DATA;
int failed = 0, enabled = 0;
int i;
down(&psmouse_sem);
if (psmouse->state != PSMOUSE_RESYNCING)
goto out;
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = serio_get_drvdata(serio->parent);
psmouse_deactivate(parent);
}
/*
* Some mice don't ACK commands sent while they are in the middle of
* transmitting motion packet. To avoid delay we use ps2_sendbyte()
* instead of ps2_command() which would wait for 200ms for an ACK
* that may never come.
* As an additional quirk ALPS touchpads may not only forget to ACK
* disable command but will stop reporting taps, so if we see that
* mouse at least once ACKs disable we will do full reconnect if ACK
* is missing.
*/
psmouse->num_resyncs++;
if (ps2_sendbyte(&psmouse->ps2dev, PSMOUSE_CMD_DISABLE, 20)) {
if (psmouse->num_resyncs < 3 || psmouse->acks_disable_command)
failed = 1;
} else
psmouse->acks_disable_command = 1;
/*
* Poll the mouse. If it was reset the packet will be shorter than
* psmouse->pktsize and ps2_command will fail. We do not expect and
* do not handle scenario when mouse "upgrades" its protocol while
* disconnected since it would require additional delay. If we ever
* see a mouse that does it we'll adjust the code.
*/
if (!failed) {
if (psmouse->poll(psmouse))
failed = 1;
else {
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
for (i = 0; i < psmouse->pktsize; i++) {
psmouse->pktcnt++;
rc = psmouse->protocol_handler(psmouse, NULL);
if (rc != PSMOUSE_GOOD_DATA)
break;
}
if (rc != PSMOUSE_FULL_PACKET)
failed = 1;
psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
}
}
/*
* Now try to enable mouse. We try to do that even if poll failed and also
* repeat our attempts 5 times, otherwise we may be left out with disabled
* mouse.
*/
for (i = 0; i < 5; i++) {
if (!ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) {
enabled = 1;
break;
}
msleep(200);
}
if (!enabled) {
printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n",
psmouse->ps2dev.serio->phys);
failed = 1;
}
if (failed) {
psmouse_set_state(psmouse, PSMOUSE_IGNORE);
printk(KERN_INFO "psmouse.c: resync failed, issuing reconnect request\n");
serio_reconnect(serio);
} else
psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
if (parent)
psmouse_activate(parent);
out:
up(&psmouse_sem);
}
/* /*
* psmouse_cleanup() resets the mouse into power-on state. * psmouse_cleanup() resets the mouse into power-on state.
...@@ -822,6 +977,11 @@ static void psmouse_disconnect(struct serio *serio) ...@@ -822,6 +977,11 @@ static void psmouse_disconnect(struct serio *serio)
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
/* make sure we don't have a resync in progress */
up(&psmouse_sem);
flush_workqueue(kpsmoused_wq);
down(&psmouse_sem);
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = serio_get_drvdata(serio->parent); parent = serio_get_drvdata(serio->parent);
psmouse_deactivate(parent); psmouse_deactivate(parent);
...@@ -859,6 +1019,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto ...@@ -859,6 +1019,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto
psmouse->set_rate = psmouse_set_rate; psmouse->set_rate = psmouse_set_rate;
psmouse->set_resolution = psmouse_set_resolution; psmouse->set_resolution = psmouse_set_resolution;
psmouse->poll = psmouse_poll;
psmouse->protocol_handler = psmouse_process_byte; psmouse->protocol_handler = psmouse_process_byte;
psmouse->pktsize = 3; psmouse->pktsize = 3;
...@@ -874,6 +1035,23 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto ...@@ -874,6 +1035,23 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto
else else
psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1);
/*
* If mouse's packet size is 3 there is no point in polling the
* device in hopes to detect protocol reset - we won't get less
* than 3 bytes response anyhow.
*/
if (psmouse->pktsize == 3)
psmouse->resync_time = 0;
/*
* Some smart KVMs fake response to POLL command returning just
* 3 bytes and messing up our resync logic, so if initial poll
* fails we won't try polling the device anymore. Hopefully
* such KVM will maintain initially selected protocol.
*/
if (psmouse->resync_time && psmouse->poll(psmouse))
psmouse->resync_time = 0;
sprintf(psmouse->devname, "%s %s %s", sprintf(psmouse->devname, "%s %s %s",
psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name);
...@@ -914,6 +1092,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) ...@@ -914,6 +1092,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
goto out; goto out;
ps2_init(&psmouse->ps2dev, serio); ps2_init(&psmouse->ps2dev, serio);
INIT_WORK(&psmouse->resync_work, psmouse_resync, psmouse);
psmouse->dev = input_dev; psmouse->dev = input_dev;
sprintf(psmouse->phys, "%s/input0", serio->phys); sprintf(psmouse->phys, "%s/input0", serio->phys);
...@@ -934,6 +1113,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) ...@@ -934,6 +1113,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
psmouse->rate = psmouse_rate; psmouse->rate = psmouse_rate;
psmouse->resolution = psmouse_resolution; psmouse->resolution = psmouse_resolution;
psmouse->resetafter = psmouse_resetafter; psmouse->resetafter = psmouse_resetafter;
psmouse->resync_time = parent ? 0 : psmouse_resync_time;
psmouse->smartscroll = psmouse_smartscroll; psmouse->smartscroll = psmouse_smartscroll;
psmouse_switch_protocol(psmouse, NULL); psmouse_switch_protocol(psmouse, NULL);
...@@ -1278,13 +1458,21 @@ static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) ...@@ -1278,13 +1458,21 @@ static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp)
static int __init psmouse_init(void) static int __init psmouse_init(void)
{ {
kpsmoused_wq = create_singlethread_workqueue("kpsmoused");
if (!kpsmoused_wq) {
printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n");
return -ENOMEM;
}
serio_register_driver(&psmouse_drv); serio_register_driver(&psmouse_drv);
return 0; return 0;
} }
static void __exit psmouse_exit(void) static void __exit psmouse_exit(void)
{ {
serio_unregister_driver(&psmouse_drv); serio_unregister_driver(&psmouse_drv);
destroy_workqueue(kpsmoused_wq);
} }
module_init(psmouse_init); module_init(psmouse_init);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#define PSMOUSE_CMD_GETINFO 0x03e9 #define PSMOUSE_CMD_GETINFO 0x03e9
#define PSMOUSE_CMD_SETSTREAM 0x00ea #define PSMOUSE_CMD_SETSTREAM 0x00ea
#define PSMOUSE_CMD_SETPOLL 0x00f0 #define PSMOUSE_CMD_SETPOLL 0x00f0
#define PSMOUSE_CMD_POLL 0x03eb #define PSMOUSE_CMD_POLL 0x00eb /* caller sets number of bytes to receive */
#define PSMOUSE_CMD_GETID 0x02f2 #define PSMOUSE_CMD_GETID 0x02f2
#define PSMOUSE_CMD_SETRATE 0x10f3 #define PSMOUSE_CMD_SETRATE 0x10f3
#define PSMOUSE_CMD_ENABLE 0x00f4 #define PSMOUSE_CMD_ENABLE 0x00f4
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
enum psmouse_state { enum psmouse_state {
PSMOUSE_IGNORE, PSMOUSE_IGNORE,
PSMOUSE_INITIALIZING, PSMOUSE_INITIALIZING,
PSMOUSE_RESYNCING,
PSMOUSE_CMD_MODE, PSMOUSE_CMD_MODE,
PSMOUSE_ACTIVATED, PSMOUSE_ACTIVATED,
}; };
...@@ -38,15 +39,19 @@ struct psmouse { ...@@ -38,15 +39,19 @@ struct psmouse {
void *private; void *private;
struct input_dev *dev; struct input_dev *dev;
struct ps2dev ps2dev; struct ps2dev ps2dev;
struct work_struct resync_work;
char *vendor; char *vendor;
char *name; char *name;
unsigned char packet[8]; unsigned char packet[8];
unsigned char badbyte;
unsigned char pktcnt; unsigned char pktcnt;
unsigned char pktsize; unsigned char pktsize;
unsigned char type; unsigned char type;
unsigned char acks_disable_command;
unsigned int model; unsigned int model;
unsigned long last; unsigned long last;
unsigned long out_of_sync; unsigned long out_of_sync;
unsigned long num_resyncs;
enum psmouse_state state; enum psmouse_state state;
char devname[64]; char devname[64];
char phys[32]; char phys[32];
...@@ -54,6 +59,7 @@ struct psmouse { ...@@ -54,6 +59,7 @@ struct psmouse {
unsigned int rate; unsigned int rate;
unsigned int resolution; unsigned int resolution;
unsigned int resetafter; unsigned int resetafter;
unsigned int resync_time;
unsigned int smartscroll; /* Logitech only */ unsigned int smartscroll; /* Logitech only */
psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs); psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs);
...@@ -62,6 +68,7 @@ struct psmouse { ...@@ -62,6 +68,7 @@ struct psmouse {
int (*reconnect)(struct psmouse *psmouse); int (*reconnect)(struct psmouse *psmouse);
void (*disconnect)(struct psmouse *psmouse); void (*disconnect)(struct psmouse *psmouse);
int (*poll)(struct psmouse *psmouse);
void (*pt_activate)(struct psmouse *psmouse); void (*pt_activate)(struct psmouse *psmouse);
void (*pt_deactivate)(struct psmouse *psmouse); void (*pt_deactivate)(struct psmouse *psmouse);
......
...@@ -652,6 +652,8 @@ int synaptics_init(struct psmouse *psmouse) ...@@ -652,6 +652,8 @@ int synaptics_init(struct psmouse *psmouse)
psmouse->disconnect = synaptics_disconnect; psmouse->disconnect = synaptics_disconnect;
psmouse->reconnect = synaptics_reconnect; psmouse->reconnect = synaptics_reconnect;
psmouse->pktsize = 6; psmouse->pktsize = 6;
/* Synaptics can usually stay in sync without extra help */
psmouse->resync_time = 0;
if (SYN_CAP_PASS_THROUGH(priv->capabilities)) if (SYN_CAP_PASS_THROUGH(priv->capabilities))
synaptics_pt_create(psmouse); synaptics_pt_create(psmouse);
......
...@@ -173,6 +173,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { ...@@ -173,6 +173,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"), DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"),
}, },
}, },
{
.ident = "Sony Vaio FS-115b",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"),
},
},
{ } { }
}; };
......
...@@ -37,6 +37,16 @@ config USB_HIDINPUT ...@@ -37,6 +37,16 @@ config USB_HIDINPUT
If unsure, say Y. If unsure, say Y.
config USB_HIDINPUT_POWERBOOK
bool "Enable support for iBook/PowerBook special keys"
default n
depends on USB_HIDINPUT
help
Say Y here if you want support for the special keys (Fn, Numlock) on
Apple iBooks and PowerBooks.
If unsure, say N.
config HID_FF config HID_FF
bool "Force feedback support (EXPERIMENTAL)" bool "Force feedback support (EXPERIMENTAL)"
depends on USB_HIDINPUT && EXPERIMENTAL depends on USB_HIDINPUT && EXPERIMENTAL
......
...@@ -1450,6 +1450,9 @@ void hid_init_reports(struct hid_device *hid) ...@@ -1450,6 +1450,9 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_APPLE 0x05ac #define USB_VENDOR_ID_APPLE 0x05ac
#define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304 #define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304
#define USB_VENDOR_ID_CHERRY 0x046a
#define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023
/* /*
* Alphabetically sorted blacklist by quirk type. * Alphabetically sorted blacklist by quirk type.
*/ */
...@@ -1580,6 +1583,16 @@ static const struct hid_blacklist { ...@@ -1580,6 +1583,16 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
{ USB_VENDOR_ID_APPLE, 0x020E, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x020F, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN },
{ 0, 0 } { 0, 0 }
}; };
...@@ -1626,6 +1639,20 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) ...@@ -1626,6 +1639,20 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma); usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma);
} }
/*
* Cherry Cymotion keyboard have an invalid HID report descriptor,
* that needs fixing before we can parse it.
*/
static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize)
{
if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
info("Fixing up Cherry Cymotion report descriptor");
rdesc[11] = rdesc[16] = 0xff;
rdesc[12] = rdesc[17] = 0x03;
}
}
static struct hid_device *usb_hid_configure(struct usb_interface *intf) static struct hid_device *usb_hid_configure(struct usb_interface *intf)
{ {
struct usb_host_interface *interface = intf->cur_altsetting; struct usb_host_interface *interface = intf->cur_altsetting;
...@@ -1673,6 +1700,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) ...@@ -1673,6 +1700,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
return NULL; return NULL;
} }
if ((quirks & HID_QUIRK_CYMOTION))
hid_fixup_cymotion_descriptor(rdesc, rsize);
#ifdef DEBUG_DATA #ifdef DEBUG_DATA
printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
for (n = 0; n < rsize; n++) for (n = 0; n < rsize; n++)
......
...@@ -73,6 +73,160 @@ static const struct { ...@@ -73,6 +73,160 @@ static const struct {
#define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0)
#define map_ff_effect(c) do { set_bit(c, input->ffbit); } while (0) #define map_ff_effect(c) do { set_bit(c, input->ffbit); } while (0)
#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
struct hidinput_key_translation {
u16 from;
u16 to;
u8 flags;
};
#define POWERBOOK_FLAG_FKEY 0x01
static struct hidinput_key_translation powerbook_fn_keys[] = {
{ KEY_BACKSPACE, KEY_DELETE },
{ KEY_F1, KEY_BRIGHTNESSDOWN, POWERBOOK_FLAG_FKEY },
{ KEY_F2, KEY_BRIGHTNESSUP, POWERBOOK_FLAG_FKEY },
{ KEY_F3, KEY_MUTE, POWERBOOK_FLAG_FKEY },
{ KEY_F4, KEY_VOLUMEDOWN, POWERBOOK_FLAG_FKEY },
{ KEY_F5, KEY_VOLUMEUP, POWERBOOK_FLAG_FKEY },
{ KEY_F6, KEY_NUMLOCK, POWERBOOK_FLAG_FKEY },
{ KEY_F7, KEY_SWITCHVIDEOMODE, POWERBOOK_FLAG_FKEY },
{ KEY_F8, KEY_KBDILLUMTOGGLE, POWERBOOK_FLAG_FKEY },
{ KEY_F9, KEY_KBDILLUMDOWN, POWERBOOK_FLAG_FKEY },
{ KEY_F10, KEY_KBDILLUMUP, POWERBOOK_FLAG_FKEY },
{ KEY_UP, KEY_PAGEUP },
{ KEY_DOWN, KEY_PAGEDOWN },
{ KEY_LEFT, KEY_HOME },
{ KEY_RIGHT, KEY_END },
{ }
};
static struct hidinput_key_translation powerbook_numlock_keys[] = {
{ KEY_J, KEY_KP1 },
{ KEY_K, KEY_KP2 },
{ KEY_L, KEY_KP3 },
{ KEY_U, KEY_KP4 },
{ KEY_I, KEY_KP5 },
{ KEY_O, KEY_KP6 },
{ KEY_7, KEY_KP7 },
{ KEY_8, KEY_KP8 },
{ KEY_9, KEY_KP9 },
{ KEY_M, KEY_KP0 },
{ KEY_DOT, KEY_KPDOT },
{ KEY_SLASH, KEY_KPPLUS },
{ KEY_SEMICOLON, KEY_KPMINUS },
{ KEY_P, KEY_KPASTERISK },
{ KEY_MINUS, KEY_KPEQUAL },
{ KEY_0, KEY_KPSLASH },
{ KEY_F6, KEY_NUMLOCK },
{ KEY_KPENTER, KEY_KPENTER },
{ KEY_BACKSPACE, KEY_BACKSPACE },
{ }
};
static int usbhid_pb_fnmode = 1;
module_param_named(pb_fnmode, usbhid_pb_fnmode, int, 0644);
MODULE_PARM_DESC(pb_fnmode,
"Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");
static struct hidinput_key_translation *find_translation(struct hidinput_key_translation *table, u16 from)
{
struct hidinput_key_translation *trans;
/* Look for the translation */
for (trans = table; trans->from; trans++)
if (trans->from == from)
return trans;
return NULL;
}
static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
struct hid_usage *usage, __s32 value)
{
struct hidinput_key_translation *trans;
if (usage->code == KEY_FN) {
if (value) hid->quirks |= HID_QUIRK_POWERBOOK_FN_ON;
else hid->quirks &= ~HID_QUIRK_POWERBOOK_FN_ON;
input_event(input, usage->type, usage->code, value);
return 1;
}
if (usbhid_pb_fnmode) {
int do_translate;
trans = find_translation(powerbook_fn_keys, usage->code);
if (trans) {
if (test_bit(usage->code, hid->pb_pressed_fn))
do_translate = 1;
else if (trans->flags & POWERBOOK_FLAG_FKEY)
do_translate =
(usbhid_pb_fnmode == 2 && (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) ||
(usbhid_pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON));
else
do_translate = (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON);
if (do_translate) {
if (value)
set_bit(usage->code, hid->pb_pressed_fn);
else
clear_bit(usage->code, hid->pb_pressed_fn);
input_event(input, usage->type, trans->to, value);
return 1;
}
}
if (test_bit(usage->code, hid->pb_pressed_numlock) ||
test_bit(LED_NUML, input->led)) {
trans = find_translation(powerbook_numlock_keys, usage->code);
if (trans) {
if (value)
set_bit(usage->code, hid->pb_pressed_numlock);
else
clear_bit(usage->code, hid->pb_pressed_numlock);
input_event(input, usage->type, trans->to, value);
}
return 1;
}
}
return 0;
}
static void hidinput_pb_setup(struct input_dev *input)
{
struct hidinput_key_translation *trans;
set_bit(KEY_NUMLOCK, input->keybit);
/* Enable all needed keys */
for (trans = powerbook_fn_keys; trans->from; trans++)
set_bit(trans->to, input->keybit);
for (trans = powerbook_numlock_keys; trans->from; trans++)
set_bit(trans->to, input->keybit);
}
#else
static inline int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
struct hid_usage *usage, __s32 value)
{
return 0;
}
static inline void hidinput_pb_setup(struct input_dev *input)
{
}
#endif
static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
struct hid_usage *usage) struct hid_usage *usage)
{ {
...@@ -137,6 +291,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel ...@@ -137,6 +291,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
switch (usage->hid & 0xffff) { switch (usage->hid & 0xffff) {
case 0xba: map_abs(ABS_RUDDER); break; case 0xba: map_abs(ABS_RUDDER); break;
case 0xbb: map_abs(ABS_THROTTLE); break; case 0xbb: map_abs(ABS_THROTTLE); break;
case 0xc4: map_abs(ABS_GAS); break;
case 0xc5: map_abs(ABS_BRAKE); break;
case 0xc8: map_abs(ABS_WHEEL); break;
default: goto ignore; default: goto ignore;
} }
break; break;
...@@ -289,11 +446,19 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel ...@@ -289,11 +446,19 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x226: map_key_clear(KEY_STOP); break; case 0x226: map_key_clear(KEY_STOP); break;
case 0x227: map_key_clear(KEY_REFRESH); break; case 0x227: map_key_clear(KEY_REFRESH); break;
case 0x22a: map_key_clear(KEY_BOOKMARKS); break; case 0x22a: map_key_clear(KEY_BOOKMARKS); break;
case 0x233: map_key_clear(KEY_SCROLLUP); break;
case 0x234: map_key_clear(KEY_SCROLLDOWN); break;
case 0x238: map_rel(REL_HWHEEL); break; case 0x238: map_rel(REL_HWHEEL); break;
case 0x279: map_key_clear(KEY_REDO); break; case 0x279: map_key_clear(KEY_REDO); break;
case 0x289: map_key_clear(KEY_REPLY); break; case 0x289: map_key_clear(KEY_REPLY); break;
case 0x28b: map_key_clear(KEY_FORWARDMAIL); break; case 0x28b: map_key_clear(KEY_FORWARDMAIL); break;
case 0x28c: map_key_clear(KEY_SEND); break; case 0x28c: map_key_clear(KEY_SEND); break;
/* Reported on a Cherry Cymotion keyboard */
case 0x301: map_key_clear(KEY_PROG1); break;
case 0x302: map_key_clear(KEY_PROG2); break;
case 0x303: map_key_clear(KEY_PROG3); break;
default: goto ignore; default: goto ignore;
} }
break; break;
...@@ -325,7 +490,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel ...@@ -325,7 +490,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
set_bit(EV_REP, input->evbit); set_bit(EV_REP, input->evbit);
switch(usage->hid & HID_USAGE) { switch(usage->hid & HID_USAGE) {
case 0x003: map_key_clear(KEY_FN); break; case 0x003:
/* The fn key on Apple PowerBooks */
map_key_clear(KEY_FN);
hidinput_pb_setup(input);
break;
default: goto ignore; default: goto ignore;
} }
break; break;
...@@ -482,6 +652,9 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct ...@@ -482,6 +652,9 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
return; return;
} }
if ((hid->quirks & HID_QUIRK_POWERBOOK_HAS_FN) && hidinput_pb_event(hid, input, usage, value))
return;
if (usage->hat_min < usage->hat_max || usage->hat_dir) { if (usage->hat_min < usage->hat_max || usage->hat_dir) {
int hat_dir = usage->hat_dir; int hat_dir = usage->hat_dir;
if (!hat_dir) if (!hat_dir)
...@@ -524,7 +697,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct ...@@ -524,7 +697,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
return; return;
} }
if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */ if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
return; return;
input_event(input, usage->type, usage->code, value); input_event(input, usage->type, usage->code, value);
......
...@@ -235,17 +235,20 @@ struct hid_item { ...@@ -235,17 +235,20 @@ struct hid_item {
* HID device quirks. * HID device quirks.
*/ */
#define HID_QUIRK_INVERT 0x001 #define HID_QUIRK_INVERT 0x00000001
#define HID_QUIRK_NOTOUCH 0x002 #define HID_QUIRK_NOTOUCH 0x00000002
#define HID_QUIRK_IGNORE 0x004 #define HID_QUIRK_IGNORE 0x00000004
#define HID_QUIRK_NOGET 0x008 #define HID_QUIRK_NOGET 0x00000008
#define HID_QUIRK_HIDDEV 0x010 #define HID_QUIRK_HIDDEV 0x00000010
#define HID_QUIRK_BADPAD 0x020 #define HID_QUIRK_BADPAD 0x00000020
#define HID_QUIRK_MULTI_INPUT 0x040 #define HID_QUIRK_MULTI_INPUT 0x00000040
#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x080 #define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080
#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x100 #define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100
#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x200 #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200
#define HID_QUIRK_2WHEEL_POWERMOUSE 0x400 #define HID_QUIRK_2WHEEL_POWERMOUSE 0x00000400
#define HID_QUIRK_CYMOTION 0x00000800
#define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000
#define HID_QUIRK_POWERBOOK_FN_ON 0x00002000
/* /*
* This is the global environment of the parser. This information is * This is the global environment of the parser. This information is
...@@ -431,6 +434,11 @@ struct hid_device { /* device report descriptor */ ...@@ -431,6 +434,11 @@ struct hid_device { /* device report descriptor */
void (*ff_exit)(struct hid_device*); /* Called by hid_exit_ff(hid) */ void (*ff_exit)(struct hid_device*); /* Called by hid_exit_ff(hid) */
int (*ff_event)(struct hid_device *hid, struct input_dev *input, int (*ff_event)(struct hid_device *hid, struct input_dev *input,
unsigned int type, unsigned int code, int value); unsigned int type, unsigned int code, int value);
#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
unsigned long pb_pressed_fn[NBITS(KEY_MAX)];
unsigned long pb_pressed_numlock[NBITS(KEY_MAX)];
#endif
}; };
#define HID_GLOBAL_STACK_SIZE 4 #define HID_GLOBAL_STACK_SIZE 4
......
...@@ -259,7 +259,7 @@ static int hid_pid_upload_effect(struct input_dev *dev, ...@@ -259,7 +259,7 @@ static int hid_pid_upload_effect(struct input_dev *dev,
int hid_pid_init(struct hid_device *hid) int hid_pid_init(struct hid_device *hid)
{ {
struct hid_ff_pid *private; struct hid_ff_pid *private;
struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list); struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
struct input_dev *input_dev = hidinput->input; struct input_dev *input_dev = hidinput->input;
private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL); private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL);
......
...@@ -95,7 +95,7 @@ MODULE_LICENSE(DRIVER_LICENSE); ...@@ -95,7 +95,7 @@ MODULE_LICENSE(DRIVER_LICENSE);
enum { enum {
PENPARTNER = 0, PENPARTNER = 0,
GRAPHIRE, GRAPHIRE,
G4, WACOM_G4,
PL, PL,
INTUOS, INTUOS,
INTUOS3, INTUOS3,
...@@ -373,7 +373,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) ...@@ -373,7 +373,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
case 2: /* Mouse with wheel */ case 2: /* Mouse with wheel */
input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); input_report_key(dev, BTN_MIDDLE, data[1] & 0x04);
if (wacom->features->type == G4) { if (wacom->features->type == WACOM_G4) {
rw = data[7] & 0x04 ? -(data[7] & 0x03) : (data[7] & 0x03); rw = data[7] & 0x04 ? -(data[7] & 0x03) : (data[7] & 0x03);
input_report_rel(dev, REL_WHEEL, rw); input_report_rel(dev, REL_WHEEL, rw);
} else } else
...@@ -385,7 +385,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) ...@@ -385,7 +385,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
id = CURSOR_DEVICE_ID; id = CURSOR_DEVICE_ID;
input_report_key(dev, BTN_LEFT, data[1] & 0x01); input_report_key(dev, BTN_LEFT, data[1] & 0x01);
input_report_key(dev, BTN_RIGHT, data[1] & 0x02); input_report_key(dev, BTN_RIGHT, data[1] & 0x02);
if (wacom->features->type == G4) if (wacom->features->type == WACOM_G4)
input_report_abs(dev, ABS_DISTANCE, data[6]); input_report_abs(dev, ABS_DISTANCE, data[6]);
else else
input_report_abs(dev, ABS_DISTANCE, data[7]); input_report_abs(dev, ABS_DISTANCE, data[7]);
...@@ -410,7 +410,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) ...@@ -410,7 +410,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
input_sync(dev); input_sync(dev);
/* send pad data */ /* send pad data */
if (wacom->features->type == G4) { if (wacom->features->type == WACOM_G4) {
/* fist time sending pad data */ /* fist time sending pad data */
if (wacom->tool[1] != BTN_TOOL_FINGER) { if (wacom->tool[1] != BTN_TOOL_FINGER) {
wacom->id[1] = 0; wacom->id[1] = 0;
...@@ -713,8 +713,8 @@ static struct wacom_features wacom_features[] = { ...@@ -713,8 +713,8 @@ static struct wacom_features wacom_features[] = {
{ "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq }, { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq },
{ "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq }, { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq },
{ "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq }, { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq },
{ "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, G4, wacom_graphire_irq }, { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, WACOM_G4, wacom_graphire_irq },
{ "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, G4, wacom_graphire_irq }, { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, WACOM_G4, wacom_graphire_irq },
{ "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq },
{ "Wacom PenStation2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq }, { "Wacom PenStation2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq },
{ "Wacom Volito2 4x5", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq },
...@@ -859,7 +859,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i ...@@ -859,7 +859,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0); input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0);
switch (wacom->features->type) { switch (wacom->features->type) {
case G4: case WACOM_G4:
input_dev->evbit[0] |= BIT(EV_MSC); input_dev->evbit[0] |= BIT(EV_MSC);
input_dev->mscbit[0] |= BIT(MSC_SERIAL); input_dev->mscbit[0] |= BIT(MSC_SERIAL);
input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
......
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