25-akpm/Documentation/kernel-parameters.txt | 4 25-akpm/drivers/input/mouse/psmouse-base.c | 69 ++++++++--- 25-akpm/drivers/input/mouse/psmouse.h | 22 ++- 25-akpm/drivers/input/mouse/synaptics.c | 172 ++++++++++++++++++++++------ 25-akpm/drivers/input/mouse/synaptics.h | 15 +- 25-akpm/drivers/input/serio/serio.c | 25 ++++ 25-akpm/include/linux/serio.h | 3 7 files changed, 247 insertions(+), 63 deletions(-) diff -puN Documentation/kernel-parameters.txt~p00005_synaptics-pass-through Documentation/kernel-parameters.txt --- 25/Documentation/kernel-parameters.txt~p00005_synaptics-pass-through Fri Aug 1 16:47:25 2003 +++ 25-akpm/Documentation/kernel-parameters.txt Fri Aug 1 16:47:25 2003 @@ -784,6 +784,10 @@ running once the system is up. 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: ,,,,, diff -puN drivers/input/mouse/psmouse-base.c~p00005_synaptics-pass-through drivers/input/mouse/psmouse-base.c --- 25/drivers/input/mouse/psmouse-base.c~p00005_synaptics-pass-through Fri Aug 1 16:47:25 2003 +++ 25-akpm/drivers/input/mouse/psmouse-base.c Fri Aug 1 16:47:25 2003 @@ -29,6 +29,8 @@ MODULE_PARM(psmouse_resolution, "i"); MODULE_PARM_DESC(psmouse_resolution, "Resolution, in dpi."); MODULE_PARM(psmouse_smartscroll, "i"); MODULE_PARM_DESC(psmouse_smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); +MODULE_PARM(psmouse_resetafter, "i"); +MODULE_PARM_DESC(psmouse_resetafter, "Reset Synaptics Touchpad after so many bad packets (0 = never)."); MODULE_LICENSE("GPL"); #define PSMOUSE_LOGITECH_SMARTSCROLL 1 @@ -36,11 +38,12 @@ MODULE_LICENSE("GPL"); static int psmouse_noext; int psmouse_resolution; int psmouse_smartscroll = PSMOUSE_LOGITECH_SMARTSCROLL; +unsigned int psmouse_resetafter; static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "Synaptics"}; /* - * psmouse_process_packet() anlyzes the PS/2 mouse packet contents and + * psmouse_process_packet() analyzes the PS/2 mouse packet contents and * reports relevant events to the input module. */ @@ -108,6 +111,9 @@ static irqreturn_t psmouse_interrupt(str { struct psmouse *psmouse = serio->private; + if (psmouse->state == PSMOUSE_IGNORE) + goto out; + if (psmouse->acking) { switch (data) { case PSMOUSE_RET_ACK: @@ -132,31 +138,46 @@ static irqreturn_t psmouse_interrupt(str } 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; - goto out; + if (psmouse->packet[0] == PSMOUSE_RET_BAT) { + if (psmouse->pktcnt == 1) + goto out; + + if (psmouse->pktcnt == 2) { + if (psmouse->packet[1] == PSMOUSE_RET_ID) { + psmouse->state = PSMOUSE_IGNORE; + serio_rescan(serio); + goto out; + } + if (psmouse->type == PSMOUSE_SYNAPTICS) { + /* neither 0xAA nor 0x00 are valid first bytes + * for a packet in absolute mode + */ + psmouse->pktcnt = 0; + 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; 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: @@ -227,7 +248,7 @@ int psmouse_command(struct psmouse *psmo for (i = 0; i < receive; i++) param[i] = psmouse->cmdbuf[(receive - 1) - i]; - if (psmouse->cmdcnt) + if (psmouse->cmdcnt) return (psmouse->cmdcnt = 0) - 1; return 0; @@ -450,14 +471,18 @@ static void psmouse_initialize(struct ps */ 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->state = PSMOUSE_ACTIVATED; } /* @@ -478,8 +503,9 @@ static void psmouse_cleanup(struct serio static void psmouse_disconnect(struct serio *serio) { struct psmouse *psmouse = serio->private; - if (psmouse->type == PSMOUSE_SYNAPTICS) - synaptics_disconnect(psmouse); + + psmouse->state = PSMOUSE_IGNORE; + synaptics_disconnect(psmouse); input_unregister_device(&psmouse->dev); serio_close(serio); kfree(psmouse); @@ -494,7 +520,8 @@ static void psmouse_connect(struct serio { 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))) @@ -507,6 +534,7 @@ static void psmouse_connect(struct serio 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->state = PSMOUSE_NEW_DEVICE; psmouse->serio = serio; psmouse->dev.private = psmouse; @@ -540,6 +568,10 @@ static void psmouse_connect(struct serio 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 = { @@ -568,9 +600,16 @@ static int __init psmouse_smartscroll_se return 1; } +static int __init psmouse_resetafter_setup(char *str) +{ + get_option(&str, &psmouse_resetafter); + return 1; +} + __setup("psmouse_noext", psmouse_noext_setup); __setup("psmouse_resolution=", psmouse_resolution_setup); __setup("psmouse_smartscroll=", psmouse_smartscroll_setup); +__setup("psmouse_resetafter=", psmouse_resetafter_setup); #endif diff -puN drivers/input/mouse/psmouse.h~p00005_synaptics-pass-through drivers/input/mouse/psmouse.h --- 25/drivers/input/mouse/psmouse.h~p00005_synaptics-pass-through Fri Aug 1 16:47:25 2003 +++ 25-akpm/drivers/input/mouse/psmouse.h Fri Aug 1 16:47:25 2003 @@ -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 @@ struct psmouse { unsigned char type; unsigned char model; unsigned long last; + unsigned char state; char acking; volatile char ack; char error; @@ -36,16 +43,17 @@ struct psmouse { 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 7 int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command); extern int psmouse_smartscroll; +extern unsigned int psmouse_resetafter; #endif /* _PSMOUSE_H */ diff -puN drivers/input/mouse/synaptics.c~p00005_synaptics-pass-through drivers/input/mouse/synaptics.c --- 25/drivers/input/mouse/synaptics.c~p00005_synaptics-pass-through Fri Aug 1 16:47:25 2003 +++ 25-akpm/drivers/input/mouse/synaptics.c Fri Aug 1 16:47:25 2003 @@ -1,6 +1,9 @@ /* * Synaptics TouchPad PS/2 mouse driver * + * 2003 Dmitry Torokhov + * Added support for pass-through port + * * 2003 Peter Osterlund * Ported to 2.5 input device infrastructure. * @@ -21,6 +24,7 @@ #include #include +#include #include "psmouse.h" #include "synaptics.h" @@ -71,7 +75,7 @@ static int synaptics_set_mode(struct psm if (synaptics_special_cmd(psmouse, mode)) return -1; - param[0] = 0x14; + param[0] = SYN_PS_SET_MODE2; if (psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE)) return -1; return 0; @@ -83,7 +87,7 @@ static int synaptics_reset(struct psmous if (psmouse_command(psmouse, r, PSMOUSE_CMD_RESET_BAT)) return -1; - if (r[0] == 0xAA && r[1] == 0x00) + if (r[0] == PSMOUSE_RET_BAT && r[1] == PSMOUSE_RET_ID) return 0; return -1; } @@ -143,13 +147,6 @@ static int synaptics_identify(struct psm return -1; } -static int synaptics_enable_device(struct psmouse *psmouse) -{ - if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_ENABLE)) - return -1; - return 0; -} - static void print_ident(struct synaptics_data *priv) { printk(KERN_INFO "Synaptics Touchpad, model: %ld\n", SYN_ID_MODEL(priv->identity)); @@ -176,6 +173,8 @@ static void print_ident(struct synaptics printk(KERN_INFO " -> multifinger detection\n"); if (SYN_CAP_PALMDETECT(priv->capabilities)) printk(KERN_INFO " -> palm detection\n"); + if (SYN_CAP_PASS_THROUGH(priv->capabilities)) + printk(KERN_INFO " -> pass-through port\n"); } } @@ -199,9 +198,96 @@ static int query_hardware(struct psmouse SYN_BIT_W_MODE))) return -1; - synaptics_enable_device(psmouse); + return 0; +} - print_ident(priv); +/***************************************************************************** + * Synaptics pass-through PS/2 port support + ****************************************************************************/ +static int synaptics_pt_open(struct serio *port) +{ + return 0; +} + +static void synaptics_pt_close(struct serio *port) +{ +} + +static int synaptics_pt_write(struct serio *port, unsigned char c) +{ + struct psmouse *parent = port->driver; + char rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */ + + if (synaptics_special_cmd(parent, c)) + return -1; + if (psmouse_command(parent, &rate_param, PSMOUSE_CMD_SETRATE)) + return -1; + return 0; +} + +static inline int synaptics_is_pt_packet(unsigned char *buf) +{ + return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4; +} + +static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet) +{ + struct psmouse *child = ptport->private; + + if (child) { + if (child->state == PSMOUSE_ACTIVATED) { + serio_interrupt(ptport, packet[1], 0, NULL); + serio_interrupt(ptport, packet[4], 0, NULL); + serio_interrupt(ptport, packet[5], 0, NULL); + if (child->type >= PSMOUSE_GENPS) + serio_interrupt(ptport, packet[2], 0, NULL); + } else if (child->state != PSMOUSE_IGNORE) { + serio_interrupt(ptport, packet[1], 0, NULL); + } + } +} + +int synaptics_pt_init(struct psmouse *psmouse) +{ + struct synaptics_data *priv = psmouse->private; + struct serio *port; + struct psmouse *child; + + if (psmouse->type != PSMOUSE_SYNAPTICS) + return -1; + if (!SYN_CAP_EXTENDED(priv->capabilities)) + return -1; + if (!SYN_CAP_PASS_THROUGH(priv->capabilities)) + return -1; + + priv->ptport = port = kmalloc(sizeof(struct serio), GFP_KERNEL); + if (!port) { + printk(KERN_ERR "synaptics: not enough memory to allocate serio port\n"); + return -1; + } + + memset(port, 0, sizeof(struct serio)); + port->type = SERIO_PS_PSTHRU; + port->name = "Synaptics pass-through"; + port->phys = "synaptics-pt/serio0"; + port->write = synaptics_pt_write; + 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); + + /* adjust the touchpad to child's choice of protocol */ + child = port->private; + if (child && child->type >= PSMOUSE_GENPS) { + if (synaptics_set_mode(psmouse, (SYN_BIT_ABSOLUTE_MODE | + SYN_BIT_HIGH_RATE | + SYN_BIT_DISABLE_GESTURE | + SYN_BIT_FOUR_BYTE_CLIENT | + SYN_BIT_W_MODE))) + printk(KERN_INFO "synaptics: failed to enable 4-byte guest protocol\n"); + } return 0; } @@ -232,13 +318,15 @@ int synaptics_init(struct psmouse *psmou return -1; memset(priv, 0, sizeof(struct synaptics_data)); - priv->inSync = 1; + priv->out_of_sync = 0; if (query_hardware(psmouse)) { printk(KERN_ERR "Unable to query/initialize Synaptics hardware.\n"); goto init_fail; } + print_ident(priv); + /* * The x/y limits are taken from the Synaptics TouchPad interfacing Guide, * which says that they should be valid regardless of the actual size of @@ -290,20 +378,22 @@ void synaptics_disconnect(struct psmouse { struct synaptics_data *priv = psmouse->private; - /* Restore touchpad to power on default state */ - synaptics_set_mode(psmouse, 0); - - kfree(priv); + if (psmouse->type == PSMOUSE_SYNAPTICS && priv) { + synaptics_set_mode(psmouse, 0); + if (priv->ptport) { + serio_unregister_slave_port(priv->ptport); + kfree(priv->ptport); + } + kfree(priv); + } } /***************************************************************************** * Functions to interpret the absolute mode packets ****************************************************************************/ -static void synaptics_parse_hw_state(struct synaptics_data *priv, struct synaptics_hw_state *hw) +static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw) { - unsigned char *buf = priv->proto_buf; - hw->x = (((buf[3] & 0x10) << 8) | ((buf[1] & 0x0f) << 8) | buf[4]); @@ -317,7 +407,7 @@ static void synaptics_parse_hw_state(str ((buf[3] & 0x04) >> 2)); hw->left = (buf[0] & 0x01) ? 1 : 0; - hw->right = (buf[0] & 0x2) ? 1 : 0; + hw->right = (buf[0] & 0x02) ? 1 : 0; hw->up = 0; hw->down = 0; hw->b0 = 0; @@ -366,7 +456,7 @@ static void synaptics_process_packet(str struct synaptics_data *priv = psmouse->private; struct synaptics_hw_state hw; - synaptics_parse_hw_state(priv, &hw); + synaptics_parse_hw_state(psmouse->packet, priv, &hw); if (hw.z > 0) { int w_ok = 0; @@ -431,35 +521,45 @@ void synaptics_process_byte(struct psmou { struct input_dev *dev = &psmouse->dev; struct synaptics_data *priv = psmouse->private; - unsigned char *pBuf = priv->proto_buf; - unsigned char u = psmouse->packet[0]; + unsigned char data = psmouse->packet[psmouse->pktcnt - 1]; input_regs(dev, regs); - pBuf[priv->proto_buf_tail++] = u; - /* check first byte */ - if ((priv->proto_buf_tail == 1) && ((u & 0xC8) != 0x80)) { - priv->inSync = 0; - priv->proto_buf_tail = 0; + if (psmouse->pktcnt == 1 && (data & 0xC8) != 0x80) { printk(KERN_WARNING "Synaptics driver lost sync at 1st byte\n"); + priv->out_of_sync++; + psmouse->pktcnt = 0; + if (psmouse_resetafter > 0 && priv->out_of_sync == psmouse_resetafter) { + psmouse->state = PSMOUSE_IGNORE; + serio_rescan(psmouse->serio); + } return; } /* check 4th byte */ - if ((priv->proto_buf_tail == 4) && ((u & 0xc8) != 0xc0)) { - priv->inSync = 0; - priv->proto_buf_tail = 0; + if (psmouse->pktcnt == 4 && (data & 0xC8) != 0xC0) { printk(KERN_WARNING "Synaptics driver lost sync at 4th byte\n"); + priv->out_of_sync++; + psmouse->pktcnt = 0; + if (psmouse_resetafter > 0 && priv->out_of_sync == psmouse_resetafter) { + psmouse->state = PSMOUSE_IGNORE; + serio_rescan(psmouse->serio); + } return; } - if (priv->proto_buf_tail >= 6) { /* Full packet received */ - if (!priv->inSync) { - priv->inSync = 1; + if (psmouse->pktcnt >= 6) { /* Full packet received */ + if (priv->out_of_sync) { + priv->out_of_sync = 0; printk(KERN_NOTICE "Synaptics driver resynced.\n"); } - synaptics_process_packet(psmouse); - priv->proto_buf_tail = 0; + + if (priv->ptport && synaptics_is_pt_packet(psmouse->packet)) + synaptics_pass_pt_packet(priv->ptport, psmouse->packet); + else + synaptics_process_packet(psmouse); + + psmouse->pktcnt = 0; } } diff -puN drivers/input/mouse/synaptics.h~p00005_synaptics-pass-through drivers/input/mouse/synaptics.h --- 25/drivers/input/mouse/synaptics.h~p00005_synaptics-pass-through Fri Aug 1 16:47:25 2003 +++ 25-akpm/drivers/input/mouse/synaptics.h Fri Aug 1 16:47:25 2003 @@ -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 */ @@ -29,6 +30,7 @@ extern void synaptics_disconnect(struct #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 */ @@ -43,6 +45,7 @@ extern void synaptics_disconnect(struct /* 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)) @@ -65,6 +68,10 @@ extern void synaptics_disconnect(struct #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) */ @@ -96,12 +103,10 @@ struct synaptics_data { 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 */ diff -puN drivers/input/serio/serio.c~p00005_synaptics-pass-through drivers/input/serio/serio.c --- 25/drivers/input/serio/serio.c~p00005_synaptics-pass-through Fri Aug 1 16:47:25 2003 +++ 25-akpm/drivers/input/serio/serio.c Fri Aug 1 16:47:25 2003 @@ -49,7 +49,9 @@ MODULE_LICENSE("GPL"); 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); @@ -166,6 +168,17 @@ void serio_register_port(struct serio *s 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); @@ -175,6 +188,18 @@ void serio_unregister_port(struct serio up(&serio_sem); } +/* + * Same as serio_unregister_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; diff -puN include/linux/serio.h~p00005_synaptics-pass-through include/linux/serio.h --- 25/include/linux/serio.h~p00005_synaptics-pass-through Fri Aug 1 16:47:25 2003 +++ 25-akpm/include/linux/serio.h Fri Aug 1 16:47:25 2003 @@ -65,7 +65,9 @@ void serio_rescan(struct serio *serio); 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 @@ static __inline__ void serio_cleanup(str #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 _