Re: suspend/resume support for inputs

From: Pavel Machek
Date: Sat Nov 22 2003 - 12:17:48 EST


Hi!

> This is patch that actually looks okay to me. _connect is split into
> hw-dependend and independent parts. Could you apply it?

Scratch it, include/ part missing. Here it is, fixed. Please apply,

Pavel

--- tmp/linux/include/linux/serio.h 2003-10-09 00:14:40.000000000 +0200
+++ linux/include/linux/serio.h 2003-11-22 16:54:24.000000000 +0100
@@ -50,6 +50,7 @@
unsigned int, struct pt_regs *);
void (*connect)(struct serio *, struct serio_dev *dev);
void (*disconnect)(struct serio *);
+ void (*resume)(struct serio *);
void (*cleanup)(struct serio *);

struct list_head node;
--- clean/drivers/input/keyboard/atkbd.c 2003-10-26 13:08:37.000000000 +0100
+++ linux/drivers/input/keyboard/atkbd.c 2003-11-22 17:08:30.000000000 +0100
@@ -582,6 +582,37 @@
kfree(atkbd);
}

+int atkbd_hwinit(struct atkbd *atkbd)
+{
+ if (atkbd->write) {
+ if (atkbd_probe(atkbd)) {
+ return -EIO;
+ }
+
+ atkbd->set = atkbd_set_3(atkbd);
+ atkbd_enable(atkbd);
+
+ } else {
+ atkbd->set = 2;
+ atkbd->id = 0xab00;
+ }
+
+ if (atkbd->set == 4) {
+ 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 Extended keyboard");
+ } else
+ sprintf(atkbd->name, "AT %s Set %d keyboard",
+ atkbd->translated ? "Translated" : "Raw", atkbd->set);
+ return 0;
+}
+
+static void atkbd_resume(struct serio *serio)
+{
+ struct atkbd *atkbd = serio->private;
+ if (atkbd_hwinit(atkbd))
+ printk(KERN_ERR "Ouch, keyboard no longer there after resume?\n");
+}
+
/*
* atkbd_connect() is called when the serio module finds and interface
* that isn't handled yet by an appropriate device driver. We check if
@@ -641,29 +672,11 @@
return;
}

- if (atkbd->write) {
-
- if (atkbd_probe(atkbd)) {
- serio_close(serio);
- kfree(atkbd);
- return;
- }
-
- atkbd->set = atkbd_set_3(atkbd);
- atkbd_enable(atkbd);
-
- } else {
- atkbd->set = 2;
- atkbd->id = 0xab00;
+ if (atkbd_hwinit(atkbd)) {
+ serio_close(serio);
+ kfree(atkbd);
+ return;
}
-
- if (atkbd->set == 4) {
- 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 Extended keyboard");
- } else
- sprintf(atkbd->name, "AT %s Set %d keyboard",
- atkbd->translated ? "Translated" : "Raw", atkbd->set);
-
sprintf(atkbd->phys, "%s/input0", serio->phys);

if (atkbd->set == 3)
@@ -688,10 +701,11 @@
}


-static struct serio_dev atkbd_dev = {
+struct serio_dev atkbd_dev = {
.interrupt = atkbd_interrupt,
.connect = atkbd_connect,
.disconnect = atkbd_disconnect,
+ .resume = atkbd_resume,
.cleanup = atkbd_cleanup,
};

--- clean/drivers/input/serio/i8042.c 2003-09-28 22:05:48.000000000 +0200
+++ linux/drivers/input/serio/i8042.c 2003-11-22 16:56:05.000000000 +0100
@@ -18,6 +18,7 @@
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/serio.h>
+#include <linux/sysdev.h>

#include <asm/io.h>

@@ -398,18 +399,15 @@
* desired.
*/

-static int __init i8042_controller_init(void)
+static int i8042_controller_init(void)
{
-
/*
* Test the i8042. We need to know if it thinks it's working correctly
* before doing anything else.
*/

i8042_flush();
-
if (i8042_reset) {
-
unsigned char param;

if (i8042_command(&param, I8042_CMD_CTL_TEST)) {
@@ -783,6 +781,32 @@
values->mux = index;
}

+static int i8042_resume_port(struct serio *port)
+{
+ struct serio_dev *dev = port->dev;
+ if (dev && dev->resume)
+ dev->resume(port);
+}
+
+static int i8042_resume(struct sys_device *dev)
+{
+ if (i8042_controller_init())
+ printk(KERN_ERR "i8042: resume failed\n");
+ i8042_resume_port(&i8042_aux_port);
+ i8042_resume_port(&i8042_kbd_port);
+ return 0;
+}
+
+static struct sysdev_class kbc_sysclass = {
+ set_kset_name("i8042"),
+ .resume = i8042_resume,
+};
+
+static struct sys_device device_i8042 = {
+ .id = 0,
+ .cls = &kbc_sysclass,
+};
+
int __init i8042_init(void)
{
int i;
@@ -819,6 +843,14 @@

register_reboot_notifier(&i8042_notifier);

+ {
+ int error = sysdev_class_register(&kbc_sysclass);
+ if (!error)
+ error = sys_device_register(&device_i8042);
+ if (error)
+ printk(KERN_CRIT "Unable to register i8042 to driver model\n");
+ }
+
return 0;
}

--
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/