Synaptics: support for pass-through port (stick)
Subsystems (2)
PATCH 1/1 Synaptics: support for pass-through port (stick)
Hi,
Here is my attempt to add support for pass-through port to the Synaptics touchpad driver so the track stick would work when the touchpad is in absolute mode.
After synaptics driver and the rest of psmouse is fully initialized and is about to enable reporting of motion data the new code creates and registers a new serio structure that does encapsulation of PS/2 commands so touchpad would pass them to the stick. Synaptics' interrupt routine recognizes stick's packets and passes them to that new serio. The rest of the processing is done again by psmouse driver that binds on that new pass-through serio and doesn't even notice anything unusual.
In order to register that pass-though serio I had to add 2 new functions to the serio interface - serio_register/unregister_slave_port. These functions do not try to acquire serio semaphore as it has already been downed. If this isn't appropriate I'm open to any suggestions.
The driver's output is like this:
Synaptics Touchpad, model: 1
Firmware: 5.7
180 degree mounted touchpad
Sensor: 1
new absolute packet format
Touchpad has extended capability bits
-> multifinger detection
-> palm detection
-> pass-through port
input: Synaptics Synaptics TouchPad on isa0060/serio1
serio: Synaptics pass-through port at isa0060/serio1/input0
input: PS/2 Generic Mouse on synaptics-pt/serio0
What you think?
Dmitry
drivers/input/mouse/psmouse-base.c +25 -13
@@ -132,31 +132,33 @@ }if (psmouse->pktcnt &&time_after (jiffies, psmouse->last +HZ /2 )) { -printk (KERN_WARNING "psmouse.c: Lost synchronization, throwing %d bytes away.\n" , psmouse->pktcnt); +printk (KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n" , + psmouse->name, psmouse->phys, psmouse->pktcnt); psmouse->pktcnt =0 ; } psmouse->last = jiffies; psmouse->packet[psmouse->pktcnt++] = data; - -if (psmouse->pktcnt ==3 + (psmouse->type >=PSMOUSE_GENPS )) { -psmouse_process_packet (psmouse, regs); - psmouse->pktcnt =0 ; + +if (psmouse->pktcnt ==1 && psmouse->packet[0 ] ==PSMOUSE_RET_BAT ) { +serio_rescan (serio); goto out; } -if (psmouse->pktcnt ==1 && psmouse->type ==PSMOUSE_SYNAPTICS ) { +if (psmouse->type ==PSMOUSE_SYNAPTICS ) {/* * The synaptics driver has its own resync logic, * so it needs to receive all bytes one at a time. */ -synaptics_process_byte (psmouse, regs); - psmouse->pktcnt =0 ; +if (synaptics_process_byte (psmouse, regs)) + psmouse->pktcnt =0 ; + goto out; } -if (psmouse->pktcnt ==1 && psmouse->packet[0 ] ==PSMOUSE_RET_BAT ) { -serio_rescan (serio); +if (psmouse->pktcnt ==3 + (psmouse->type >=PSMOUSE_GENPS )) { +psmouse_process_packet (psmouse, regs); + psmouse->pktcnt =0 ; goto out; } out:
@@ -450,14 +452,18 @@*/ psmouse_command (psmouse, param,PSMOUSE_CMD_SETSTREAM ); +}/* -* Last, we enable the mouse so that we get reports from it. +* psmouse_activate() enables the mouse so that we get motion reports from it. */ +static void psmouse_activate (struct psmouse *psmouse) +{if (psmouse_command (psmouse,NULL ,PSMOUSE_CMD_ENABLE ))printk (KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n" , psmouse->serio->phys); + psmouse->init_done =1 ; }/*
@@ -478,9 +484,10 @@static void psmouse_disconnect (struct serio *serio) {struct psmouse *psmouse = serio->private; +input_unregister_device (&psmouse->dev); -serio_close (serio);synaptics_disconnect (psmouse); +serio_close (serio);kfree (psmouse); }
@@ -493,7 +500,8 @@ {struct psmouse *psmouse; -if ((serio->type &SERIO_TYPE ) !=SERIO_8042 ) +if ((serio->type &SERIO_TYPE ) !=SERIO_8042 && + (serio->type &SERIO_TYPE ) !=SERIO_PS_PSTHRU )return ;if (!(psmouse =kmalloc (sizeof (struct psmouse ),GFP_KERNEL )))
@@ -539,6 +547,10 @@printk (KERN_INFO "input: %s on %s\n" , psmouse->devname, serio->phys);psmouse_initialize (psmouse); + +synaptics_pt_init (psmouse); + +psmouse_activate (psmouse); }static struct serio_dev psmouse_dev = {
drivers/input/mouse/psmouse.h +8 -7
@@ -31,18 +31,19 @@unsigned long last;char acking;volatile char ack; +char init_done;char error;char devname[64 ];char phys[32 ]; }; -#define PSMOUSE_PS2 1 -#define PSMOUSE_PS2PP 2 -#define PSMOUSE_PS2TPP 3 -#define PSMOUSE_GENPS 4 -#define PSMOUSE_IMPS 5 -#define PSMOUSE_IMEX 6 -#define PSMOUSE_SYNAPTICS 7 +#define PSMOUSE_PS2 1 +#define PSMOUSE_PS2PP 2 +#define PSMOUSE_PS2TPP 3 +#define PSMOUSE_GENPS 4 +#define PSMOUSE_IMPS 5 +#define PSMOUSE_IMEX 6 +#define PSMOUSE_SYNAPTICS 7int psmouse_command (struct psmouse *psmouse,unsigned char *param,int command);
drivers/input/mouse/synaptics.c +116 -30
240 lines not on this page · raw message
drivers/input/mouse/synaptics.h +8 -5
@@ -10,8 +10,9 @@#define _SYNAPTICS_H -extern void synaptics_process_byte (struct psmouse *psmouse,struct pt_regs *regs); +extern int synaptics_process_byte (struct psmouse *psmouse,struct pt_regs *regs);extern int synaptics_init (struct psmouse *psmouse); +extern int synaptics_pt_init (struct psmouse *psmouse);extern void synaptics_disconnect (struct psmouse *psmouse);/* synaptics queries */
@@ -42,6 +43,7 @@/* synaptics capability bits */ #define SYN_CAP_EXTENDED (c) ((c) & (1 << 23)) +#define SYN_CAP_PASS_THROUGH (c) ((c) & (1 << 7))#define SYN_CAP_SLEEP (c) ((c) & (1 << 4))#define SYN_CAP_FOUR_BUTTON (c) ((c) & (1 << 3))#define SYN_CAP_MULTIFINGER (c) ((c) & (1 << 1))
@@ -62,6 +64,9 @@#define SYN_ID_MINOR (i) (((i) >> 16) & 0xff)#define SYN_ID_IS_SYNAPTICS (i) ((((i) >> 8) & 0xff) == 0x47) +#define SYN_REL_DECEL_FACTOR 8 +#define SYN_REL_PRESSURE_THRESHOLD 30 +/* * A structure to describe the state of the touchpad hardware (buttons and pad) */
@@ -84,12 +89,10 @@unsigned long int identity;/* Identification */ /* Data for normal processing */ -unsigned char proto_buf[6 ];/* Buffer for Packet */ -unsigned char last_byte;/* last received byte */ int inSync;/* Packets in sync */ -int proto_buf_tail; -int old_w;/* Previous w value */ + + struct serio *ptport; /* pass-through port */ };#endif /* _SYNAPTICS_H */
drivers/input/serio/serio.c +23 -0
@@ -45,7 +45,9 @@EXPORT_SYMBOL (serio_interrupt);EXPORT_SYMBOL (serio_register_port); +EXPORT_SYMBOL (serio_register_slave_port);EXPORT_SYMBOL (serio_unregister_port); +EXPORT_SYMBOL (serio_unregister_slave_port);EXPORT_SYMBOL (serio_register_device);EXPORT_SYMBOL (serio_unregister_device);EXPORT_SYMBOL (serio_open);
@@ -162,6 +164,16 @@up (&serio_sem); } +/* Same as serio_register_port but does not try to acquire serio_sem. +* Should be used when registering a serio from other input device's +* connect() function. +*/ +void serio_register_slave_port (struct serio *serio) +{ +list_add_tail (&serio->node, &serio_list); +serio_find_dev (serio); +} +void serio_unregister_port (struct serio *serio) {down (&serio_sem);
@@ -171,6 +183,17 @@up (&serio_sem); } +/* Same as serio_register_port but does not try to acquire serio_sem. +* Should be used when unregistering a serio from other input device's +* disconnect() function. +*/ +void serio_unregister_slave_port (struct serio *serio) +{ +list_del_init (&serio->node); +if (serio->dev && serio->dev->disconnect) + serio->dev->disconnect (serio); +} +void serio_register_device (struct serio_dev *dev) {struct serio *serio;
include/linux/serio.h +3 -0
@@ -65,7 +65,9 @@irqreturn_t serio_interrupt (struct serio *serio,unsigned char data,unsigned int flags,struct pt_regs *regs);void serio_register_port (struct serio *serio); +void serio_register_slave_port (struct serio *serio);void serio_unregister_port (struct serio *serio); +void serio_unregister_slave_port (struct serio *serio);void serio_register_device (struct serio_dev *dev);void serio_unregister_device (struct serio_dev *dev);
@@ -104,6 +106,7 @@#define SERIO_RS232 0x02000000UL#define SERIO_HIL_MLC 0x03000000UL#define SERIO_PC9800 0x04000000UL +#define SERIO_PS_PSTHRU 0x05000000UL#define SERIO_PROTO 0xFFUL#define SERIO_MSC 0x01
drivers/input/mouse/psmouse-base.c line 148
Quoted 10 lines · Dmitry Torokhov
drivers/input/mouse/psmouse-base.c +4
-3-psmouse_process_packet (psmouse, regs); - psmouse->pktcnt =0 ; + +if (psmouse->pktcnt ==1 && psmouse->packet[0 ] ==PSMOUSE_RET_BAT ) { +serio_rescan (serio); goto out; } -if (psmouse->pktcnt ==1 && psmouse->type ==PSMOUSE_SYNAPTICS ) { +if (psmouse->type ==PSMOUSE_SYNAPTICS ) {
Why did you move the rescan up above the synaptics test? if the synaptics is out of sync, any byte can be recieved.
drivers/input/mouse/synaptics.c line 208
Quoted 4 lines
drivers/input/mouse/synaptics.c +4
-0+static int synaptics_pt_write (struct serio *port,unsigned char c) +{ +struct psmouse *parent = port->driver; +char client_cmd =0x28 ;// indicates that we want pass-through port
Could client_cmd be renamed to f.ex. rate_param?
drivers/input/mouse/synaptics.c line 232
Quoted 6 lines
drivers/input/mouse/synaptics.c +6
-0+if (child->init_done) { +serio_interrupt (ptport, packet[1 ],0 ,NULL ); +if (child->type >=PSMOUSE_GENPS ) +serio_interrupt (ptport, packet[2 ],0 ,NULL ); +serio_interrupt (ptport, packet[4 ],0 ,NULL ); +serio_interrupt (ptport, packet[5 ],0 ,NULL );
The 4th protocol byte from a guest is the 3rd byte in the encapsulated packet from the pad. So I would move "if (..." last.
There might be a (de)multiplexing problem here. The button information (pressed/released) in byte 0 and 3 is lost, and are not repeated in the guest protocol.
Quoted 4 lines
drivers/input/mouse/synaptics.c +4
-0+ port->type =SERIO_PS_PSTHRU ; + port->name ="Synaptics pass-through" ; + port->phys ="synaptics-pt/serio0" ; + port->write = synaptics_pt_write;
drivers/input/mouse/synaptics.c line 271
Quoted 10 lines
drivers/input/mouse/synaptics.c +10
-0+ port->open = synaptics_pt_open; + port->close = synaptics_pt_close; + port->driver = psmouse; + +printk (KERN_INFO "serio: %s port at %s\n" , port->name, psmouse->phys); +serio_register_slave_port (port); + +return 0 ; +} +
Bit 2 in the pads second mode byte must be set if the guest uses a 4 bytes protocol. So you need to check which protocol is negotiated on the slave port.
Peter
Quoted 7 lines · Peter Berg Larsen
Review
Quoted 2 lines · Dmitry Torokhov
(quoted diff) +1
-1- if (psmouse->pktcnt == 1 && psmouse->type == PSMOUSE_SYNAPTICS) { + if (psmouse->type == PSMOUSE_SYNAPTICS) {Why did you move the rescan up above the synaptics test? if the synaptics is out of sync, any byte can be recieved.
Yes, any byte can be received but it is unlikely that we will receive 0xAA. On the other hand by moving rescan there it will actually work if somehow the device gets reset. (What happens on resume for example? I am not sure as I didn't get to play with suspending/resuming my laptop yet.)
Quoted 6 lines
Review
Quoted 4 lines
(quoted diff) +4
-0+static int synaptics_pt_write(struct serio *port, unsigned char c) +{ + struct psmouse *parent = port->driver; + char client_cmd = 0x28; // indicates that we want pass-through portCould
client_cmdbe renamed to f.ex.rate_param?
Ok... although it has nothing to do with setting rate...
What you think about the patch below? I fixed the client's protocol order, button reporting (only left and right as I am not sure to which buttons up/down should be mapped), and switching to 4-byte protocol for master. Unfortunately my stick reports as generic PS/2 mouse so I can't test the 4 byte protocol.
Dmitry
drivers/input/mouse/psmouse-base.c +25 -13
@@ -132,31 +132,33 @@ }if (psmouse->pktcnt &&time_after (jiffies, psmouse->last +HZ /2 )) { -printk (KERN_WARNING "psmouse.c: Lost synchronization, throwing %d bytes away.\n" , psmouse->pktcnt); +printk (KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n" , + psmouse->name, psmouse->phys, psmouse->pktcnt); psmouse->pktcnt =0 ; } psmouse->last = jiffies; psmouse->packet[psmouse->pktcnt++] = data; - -if (psmouse->pktcnt ==3 + (psmouse->type >=PSMOUSE_GENPS )) { -psmouse_process_packet (psmouse, regs); - psmouse->pktcnt =0 ; + +if (psmouse->pktcnt ==1 && psmouse->packet[0 ] ==PSMOUSE_RET_BAT ) { +serio_rescan (serio); goto out; } -if (psmouse->pktcnt ==1 && psmouse->type ==PSMOUSE_SYNAPTICS ) { +if (psmouse->type ==PSMOUSE_SYNAPTICS ) {/* * The synaptics driver has its own resync logic, * so it needs to receive all bytes one at a time. */ -synaptics_process_byte (psmouse, regs); - psmouse->pktcnt =0 ; +if (synaptics_process_byte (psmouse, regs)) + psmouse->pktcnt =0 ; + goto out; } -if (psmouse->pktcnt ==1 && psmouse->packet[0 ] ==PSMOUSE_RET_BAT ) { -serio_rescan (serio); +if (psmouse->pktcnt ==3 + (psmouse->type >=PSMOUSE_GENPS )) { +psmouse_process_packet (psmouse, regs); + psmouse->pktcnt =0 ; goto out; } out:
@@ -450,14 +452,18 @@*/ psmouse_command (psmouse, param,PSMOUSE_CMD_SETSTREAM ); +}/* -* Last, we enable the mouse so that we get reports from it. +* psmouse_activate() enables the mouse so that we get motion reports from it. */ +static void psmouse_activate (struct psmouse *psmouse) +{if (psmouse_command (psmouse,NULL ,PSMOUSE_CMD_ENABLE ))printk (KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n" , psmouse->serio->phys); + psmouse->init_done =1 ; }/*
@@ -478,9 +484,10 @@static void psmouse_disconnect (struct serio *serio) {struct psmouse *psmouse = serio->private; +input_unregister_device (&psmouse->dev); -serio_close (serio);synaptics_disconnect (psmouse); +serio_close (serio);kfree (psmouse); }
@@ -493,7 +500,8 @@ {struct psmouse *psmouse; -if ((serio->type &SERIO_TYPE ) !=SERIO_8042 ) +if ((serio->type &SERIO_TYPE ) !=SERIO_8042 && + (serio->type &SERIO_TYPE ) !=SERIO_PS_PSTHRU )return ;if (!(psmouse =kmalloc (sizeof (struct psmouse ),GFP_KERNEL )))
@@ -539,6 +547,10 @@printk (KERN_INFO "input: %s on %s\n" , psmouse->devname, serio->phys);psmouse_initialize (psmouse); + +synaptics_pt_init (psmouse); + +psmouse_activate (psmouse); }static struct serio_dev psmouse_dev = {
drivers/input/mouse/psmouse.h +8 -7
@@ -31,18 +31,19 @@unsigned long last;char acking;volatile char ack; +char init_done;char error;char devname[64 ];char phys[32 ]; }; -#define PSMOUSE_PS2 1 -#define PSMOUSE_PS2PP 2 -#define PSMOUSE_PS2TPP 3 -#define PSMOUSE_GENPS 4 -#define PSMOUSE_IMPS 5 -#define PSMOUSE_IMEX 6 -#define PSMOUSE_SYNAPTICS 7 +#define PSMOUSE_PS2 1 +#define PSMOUSE_PS2PP 2 +#define PSMOUSE_PS2TPP 3 +#define PSMOUSE_GENPS 4 +#define PSMOUSE_IMPS 5 +#define PSMOUSE_IMEX 6 +#define PSMOUSE_SYNAPTICS 7int psmouse_command (struct psmouse *psmouse,unsigned char *param,int command);
drivers/input/mouse/synaptics.c +134 -31
265 lines not on this page · raw message
drivers/input/mouse/synaptics.h +10 -5
@@ -10,8 +10,9 @@#define _SYNAPTICS_H -extern void synaptics_process_byte (struct psmouse *psmouse,struct pt_regs *regs); +extern int synaptics_process_byte (struct psmouse *psmouse,struct pt_regs *regs);extern int synaptics_init (struct psmouse *psmouse); +extern int synaptics_pt_init (struct psmouse *psmouse);extern void synaptics_disconnect (struct psmouse *psmouse);/* synaptics queries */
@@ -28,6 +29,7 @@#define SYN_BIT_HIGH_RATE (1 << 6)#define SYN_BIT_SLEEP_MODE (1 << 3)#define SYN_BIT_DISABLE_GESTURE (1 << 2) +#define SYN_BIT_FOUR_BYTE_CLIENT (1 << 1)#define SYN_BIT_W_MODE (1 << 0)/* synaptics model ID bits */
@@ -42,6 +44,7 @@/* synaptics capability bits */ #define SYN_CAP_EXTENDED (c) ((c) & (1 << 23)) +#define SYN_CAP_PASS_THROUGH (c) ((c) & (1 << 7))#define SYN_CAP_SLEEP (c) ((c) & (1 << 4))#define SYN_CAP_FOUR_BUTTON (c) ((c) & (1 << 3))#define SYN_CAP_MULTIFINGER (c) ((c) & (1 << 1))
@@ -62,6 +65,10 @@#define SYN_ID_MINOR (i) (((i) >> 16) & 0xff)#define SYN_ID_IS_SYNAPTICS (i) ((((i) >> 8) & 0xff) == 0x47) +/* synaptics special commands */ +#define SYN_PS_SET_MODE2 0x14 +#define SYN_PS_CLIENT_CMD 0x28 +/* * A structure to describe the state of the touchpad hardware (buttons and pad) */
@@ -84,12 +91,10 @@unsigned long int identity;/* Identification */ /* Data for normal processing */ -unsigned char proto_buf[6 ];/* Buffer for Packet */ -unsigned char last_byte;/* last received byte */ int inSync;/* Packets in sync */ -int proto_buf_tail; -int old_w;/* Previous w value */ + + struct serio *ptport; /* pass-through port */ };#endif /* _SYNAPTICS_H */
drivers/input/serio/serio.c +23 -0
@@ -45,7 +45,9 @@EXPORT_SYMBOL (serio_interrupt);EXPORT_SYMBOL (serio_register_port); +EXPORT_SYMBOL (serio_register_slave_port);EXPORT_SYMBOL (serio_unregister_port); +EXPORT_SYMBOL (serio_unregister_slave_port);EXPORT_SYMBOL (serio_register_device);EXPORT_SYMBOL (serio_unregister_device);EXPORT_SYMBOL (serio_open);
@@ -162,6 +164,16 @@up (&serio_sem); } +/* Same as serio_register_port but does not try to acquire serio_sem. +* Should be used when registering a serio from other input device's +* connect() function. +*/ +void serio_register_slave_port (struct serio *serio) +{ +list_add_tail (&serio->node, &serio_list); +serio_find_dev (serio); +} +void serio_unregister_port (struct serio *serio) {down (&serio_sem);
@@ -171,6 +183,17 @@up (&serio_sem); } +/* Same as serio_register_port but does not try to acquire serio_sem. +* Should be used when unregistering a serio from other input device's +* disconnect() function. +*/ +void serio_unregister_slave_port (struct serio *serio) +{ +list_del_init (&serio->node); +if (serio->dev && serio->dev->disconnect) + serio->dev->disconnect (serio); +} +void serio_register_device (struct serio_dev *dev) {struct serio *serio;
include/linux/serio.h +3 -0
@@ -65,7 +65,9 @@irqreturn_t serio_interrupt (struct serio *serio,unsigned char data,unsigned int flags,struct pt_regs *regs);void serio_register_port (struct serio *serio); +void serio_register_slave_port (struct serio *serio);void serio_unregister_port (struct serio *serio); +void serio_unregister_slave_port (struct serio *serio);void serio_register_device (struct serio_dev *dev);void serio_unregister_device (struct serio_dev *dev);
@@ -104,6 +106,7 @@#define SERIO_RS232 0x02000000UL#define SERIO_HIL_MLC 0x03000000UL#define SERIO_PC9800 0x04000000UL +#define SERIO_PS_PSTHRU 0x05000000UL#define SERIO_PROTO 0xFFUL#define SERIO_MSC 0x01
Quoted 6 lines · Dmitry Torokhov
Quoted 2 lines · Peter Berg Larsen
Why did you move the rescan up above the synaptics test? if the synaptics is out of sync, any byte can be recieved.
Yes, any byte can be received but it is unlikely that we will receive
0xAA.
Are you sure that it is unlikely for all type >= PSMOUSE_GENPS? How about looking for the 0x00 also.
Quoted 1 line
drivers/input/mouse/psmouse-base.c +1
-0+if (psmouse->pktcnt ==1 && psmouse->packet[0 ] ==PSMOUSE_RET_BAT ) {
...
Quoted 1 line
drivers/input/mouse/psmouse-base.c +1
-0+if (psmouse->type ==PSMOUSE_SYNAPTICS ) {
...
Quoted 5 lines
drivers/input/mouse/psmouse-base.c +1
-0+if (psmouse->pktcnt ==3 + (psmouse->type >=PSMOUSE_GENPS )) {the device gets reset. (What happens on resume for example? I am not sure as I didn't get to play with suspending/resuming my laptop yet.)
The mode byte is cleared to default.
Quoted 2 lines
What you think about the patch below? I fixed the client's protocol order, ... and switching to 4-byte protocol for master.
ok.
Quoted 2 lines
button reporting (only left and right as I am not sure to which buttons up/down should be mapped),
hmm. You dont know what the guest protocol, so you can't just | the button information. However, reallity is that this will work for nearly anybody now.
drivers/input/mouse/synaptics.c line 277
Quoted 3 lines
drivers/input/mouse/synaptics.c +3
-0+/* adjust the touchpad to child's choice of protocol */ + child = port->private; +if (child && child->type >=PSMOUSE_GENPS ) {
Not type > PSMOUSE_GENPS ?
Peter
On Mon, 7 Jul 2003, Peter Berg Larsen wrote:
Replying to myself.
Quoted 6 lines
Quoted 2 lines
button reporting (only left and right as I am not sure to which buttons up/down should be mapped),
hmm. You dont know what the guest protocol, so you can't just | the button information. However, reallity is that this will work for nearly anybody now.
This is not the greatest idea as the guest sometimes does not recieve the button release. This is bad only if the userdriver multiplex the micebuttons from different mice, because it would then seem as the user holds the button down.
Peter
Quoted 7 lines · Peter Berg Larsen
On Mon, 7 Jul 2003, Peter Berg Larsen wrote:
Replying to myself.
Quoted 3 lines
Quoted 2 lines
button reporting (only left and right as I am not sure to which buttons up/down should be mapped),
Quoted 9 lines
Quoted 3 lines
hmm. You dont know what the guest protocol, so you can't just | the button information. However, reallity is that this will work for nearly anybody now.
This is not the greatest idea as the guest sometimes does not recieve the button release. This is bad only if the userdriver multiplex the micebuttons from different mice, because it would then seem as the user holds the button down.
So should we just get rid of all button multiplexing in kernel module and leave it to the userland (gpm/XFree)? Not trying to bail out, just want to find the best solution...
Dmitry
Quoted 7 lines · Peter Berg Larsen
On Mon, 7 Jul 2003, Peter Berg Larsen wrote:
Replying to myself.
Quoted 3 lines
Quoted 2 lines
button reporting (only left and right as I am not sure to which buttons up/down should be mapped),
Quoted 9 lines
Quoted 3 lines
hmm. You dont know what the guest protocol, so you can't just | the button information. However, reallity is that this will work for nearly anybody now.
This is not the greatest idea as the guest sometimes does not recieve the button release. This is bad only if the userdriver multiplex the micebuttons from different mice, because it would then seem as the user holds the button down.
Ok, here is hopefully the final version:
- no button multiplexing is done in kernel, this task is left for the userland (gpm/XFree);
- the driver looks for both 0xAA and 0x00 before attempting rescan;
- there is a new module parameter - psmouse_resetafter - which specifies how many bad packets synaptics will receive before attempting to rescan (plugging my laptop into a docking station causes synaptics to be silently reset back into relative mode, having this parameter set to let's say 10 allows quickly restore it). 0 - never.
Dmitry
Documentation/kernel-parameters.txt +4 -0
@@ -780,6 +780,10 @@ psmouse_noext [HW,MOUSE] Disable probing for PS2 mouse protocol extensions + psmouse_resetafter= + [HW,MOUSE] Try to reset Synaptics Touchpad after so many + bad packets (0 = never). + pss= [HW,OSS] Personal Sound System (ECHO ESC614) Format: <io>,<mss_io>,<mss_irq>,<mss_dma>,<mpu_io>,<mpu_irq>
drivers/input/mouse/psmouse-base.c +55 -16
161 lines not on this page · raw message
drivers/input/mouse/psmouse.h +15 -7
@@ -13,9 +13,15 @@#define PSMOUSE_CMD_RESET_BAT 0x02ff#define PSMOUSE_RET_BAT 0xaa +#define PSMOUSE_RET_ID 0x00#define PSMOUSE_RET_ACK 0xfa#define PSMOUSE_RET_NAK 0xfe +/* psmouse states */ +#define PSMOUSE_NEW_DEVICE 0 +#define PSMOUSE_ACTIVATED 1 +#define PSMOUSE_IGNORE 2 +struct psmouse {void *private;struct input_dev dev;
@@ -29,6 +35,7 @@unsigned char type;unsigned char model;unsigned long last; +unsigned char state;char acking;volatile char ack;char error;
@@ -36,16 +43,17 @@ char phys[32]; }; -#define PSMOUSE_PS2 1 -#define PSMOUSE_PS2PP 2 -#define PSMOUSE_PS2TPP 3 -#define PSMOUSE_GENPS 4 -#define PSMOUSE_IMPS 5 -#define PSMOUSE_IMEX 6 -#define PSMOUSE_SYNAPTICS 7 +#define PSMOUSE_PS2 1 +#define PSMOUSE_PS2PP 2 +#define PSMOUSE_PS2TPP 3 +#define PSMOUSE_GENPS 4 +#define PSMOUSE_IMPS 5 +#define PSMOUSE_IMEX 6 +#define PSMOUSE_SYNAPTICS 7int psmouse_command (struct psmouse *psmouse,unsigned char *param,int command);extern int psmouse_smartscroll; +extern unsigned int psmouse_resetafter;#endif /* _PSMOUSE_H */
drivers/input/mouse/synaptics.c +141 -34
282 lines not on this page · raw message
drivers/input/mouse/synaptics.h +10 -5
@@ -12,6 +12,7 @@extern void synaptics_process_byte (struct psmouse *psmouse,struct pt_regs *regs);extern int synaptics_init (struct psmouse *psmouse); +extern int synaptics_pt_init (struct psmouse *psmouse);extern void synaptics_disconnect (struct psmouse *psmouse);/* synaptics queries */
@@ -28,6 +29,7 @@#define SYN_BIT_HIGH_RATE (1 << 6)#define SYN_BIT_SLEEP_MODE (1 << 3)#define SYN_BIT_DISABLE_GESTURE (1 << 2) +#define SYN_BIT_FOUR_BYTE_CLIENT (1 << 1)#define SYN_BIT_W_MODE (1 << 0)/* synaptics model ID bits */
@@ -42,6 +44,7 @@/* synaptics capability bits */ #define SYN_CAP_EXTENDED (c) ((c) & (1 << 23)) +#define SYN_CAP_PASS_THROUGH (c) ((c) & (1 << 7))#define SYN_CAP_SLEEP (c) ((c) & (1 << 4))#define SYN_CAP_FOUR_BUTTON (c) ((c) & (1 << 3))#define SYN_CAP_MULTIFINGER (c) ((c) & (1 << 1))
@@ -62,6 +65,10 @@#define SYN_ID_MINOR (i) (((i) >> 16) & 0xff)#define SYN_ID_IS_SYNAPTICS (i) ((((i) >> 8) & 0xff) == 0x47) +/* synaptics special commands */ +#define SYN_PS_SET_MODE2 0x14 +#define SYN_PS_CLIENT_CMD 0x28 +/* * A structure to describe the state of the touchpad hardware (buttons and pad) */
@@ -84,12 +91,10 @@unsigned long int identity;/* Identification */ /* Data for normal processing */ -unsigned char proto_buf[6 ];/* Buffer for Packet */ -unsigned char last_byte;/* last received byte */ -int inSync;/* Packets in sync */ -int proto_buf_tail; - +unsigned int out_of_sync;/* # of packets out of sync */ int old_w;/* Previous w value */ + + struct serio *ptport; /* pass-through port */ };#endif /* _SYNAPTICS_H */
drivers/input/serio/serio.c +23 -0
@@ -45,7 +45,9 @@EXPORT_SYMBOL (serio_interrupt);EXPORT_SYMBOL (serio_register_port); +EXPORT_SYMBOL (serio_register_slave_port);EXPORT_SYMBOL (serio_unregister_port); +EXPORT_SYMBOL (serio_unregister_slave_port);EXPORT_SYMBOL (serio_register_device);EXPORT_SYMBOL (serio_unregister_device);EXPORT_SYMBOL (serio_open);
@@ -162,6 +164,16 @@up (&serio_sem); } +/* Same as serio_register_port but does not try to acquire serio_sem. +* Should be used when registering a serio from other input device's +* connect() function. +*/ +void serio_register_slave_port (struct serio *serio) +{ +list_add_tail (&serio->node, &serio_list); +serio_find_dev (serio); +} +void serio_unregister_port (struct serio *serio) {down (&serio_sem);
@@ -171,6 +183,17 @@up (&serio_sem); } +/* Same as serio_register_port but does not try to acquire serio_sem. +* Should be used when unregistering a serio from other input device's +* disconnect() function. +*/ +void serio_unregister_slave_port (struct serio *serio) +{ +list_del_init (&serio->node); +if (serio->dev && serio->dev->disconnect) + serio->dev->disconnect (serio); +} +void serio_register_device (struct serio_dev *dev) {struct serio *serio;
include/linux/serio.h +3 -0
@@ -65,7 +65,9 @@irqreturn_t serio_interrupt (struct serio *serio,unsigned char data,unsigned int flags,struct pt_regs *regs);void serio_register_port (struct serio *serio); +void serio_register_slave_port (struct serio *serio);void serio_unregister_port (struct serio *serio); +void serio_unregister_slave_port (struct serio *serio);void serio_register_device (struct serio_dev *dev);void serio_unregister_device (struct serio_dev *dev);
@@ -104,6 +106,7 @@#define SERIO_RS232 0x02000000UL#define SERIO_HIL_MLC 0x03000000UL#define SERIO_PC9800 0x04000000UL +#define SERIO_PS_PSTHRU 0x05000000UL#define SERIO_PROTO 0xFFUL#define SERIO_MSC 0x01
Quoted 7 lines · Peter Berg Larsen
drivers/input/mouse/synaptics.c line 277
Quoted 3 lines · Dmitry Torokhov
drivers/input/mouse/synaptics.c +3
-0+/* adjust the touchpad to child's choice of protocol */ + child = port->private; +if (child && child->type >=PSMOUSE_GENPS ) {Not type >
PSMOUSE_GENPS?
We have this code in psmouse-base.c ...
if (psmouse->pktcnt == 3 + (psmouse->type >= PSMOUSE_GENPS)) {
psmouse_process_packet(psmouse, regs);
psmouse->pktcnt = 0;
goto out;
}..or am I misreading it?
I will check what can be done with 0xAA 0x00 before we decide to rescan later this evening.
Dmitry
Quoted 4 lines · Dmitry Torokhov
Quoted 2 lines
drivers/input/mouse/synaptics.c line 277
Quoted 1 line
drivers/input/mouse/synaptics.c +1
-0+if (child && child->type >=PSMOUSE_GENPS ) {Not type >
PSMOUSE_GENPS?We have this code in
psmouse-base.c...
...
Quoted 1 line
..or am I misreading it?
No, you are right. I misread it as generic ps2 protocol.
A complete different problem that might be a problem is that even though the master(pad) says it has passthough capabilities, there might not be any guest attached. The bit only tells that it is capable of handling one. I asked synaptics about this some time ago and they replyed that the only way to find out is to send a byte and look for a returnbyte or a timeout.
Quoted 6 lines · Peter Berg Larsen
A complete different problem that might be a problem is that even though the master(pad) says it has passthough capabilities, there might not be any guest attached. The bit only tells that it is capable of handling one. I asked synaptics about this some time ago and they replyed that the only way to find out is to send a byte and look for a returnbyte or a timeout.
I think this won't be a problem - if there is no guest attached then, when we register pass-through serio port, psmouse_probe will run. The very first thing it to tries identify attached device and bails out if something goes wrong. In our case it should time out. This will leave us with a serio without input device attached - a perfectly valid scenario I think.
Dmitry