summaryrefslogtreecommitdiff
path: root/drivers/input/serio
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@mail.ru>2005-02-04 15:39:25 +0100
committerVojtech Pavlik <vojtech@suse.cz>2005-02-04 15:39:25 +0100
commite122050fef4216632a43bf6ebcaa44c3ad6b07cf (patch)
treee5525272fe8ba4577107d3572f72bbb06799ad33 /drivers/input/serio
parent8f9ba920e5efff59cff044749a6cae9748f8b6f8 (diff)
Input: replace serio's type field with serio_id structure and
add id_table to serio drivers to split initial matching and probing routines for better sysfs integration and to assist hotplug scripts in loading proper drivers. Add serio_hotplug to notify userspace about new ports. Signed-off-by: Dmitry Torokhov <dtor@mail.ru> Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
Diffstat (limited to 'drivers/input/serio')
-rw-r--r--drivers/input/serio/ambakmi.c2
-rw-r--r--drivers/input/serio/ct82c710.c2
-rw-r--r--drivers/input/serio/gscps2.c6
-rw-r--r--drivers/input/serio/i8042.c6
-rw-r--r--drivers/input/serio/maceps2.c2
-rw-r--r--drivers/input/serio/parkbd.c2
-rw-r--r--drivers/input/serio/pcips2.c2
-rw-r--r--drivers/input/serio/q40kbd.c2
-rw-r--r--drivers/input/serio/rpckbd.c2
-rw-r--r--drivers/input/serio/sa1111ps2.c2
-rw-r--r--drivers/input/serio/serio.c73
-rw-r--r--drivers/input/serio/serio_raw.c16
-rw-r--r--drivers/input/serio/serport.c20
13 files changed, 106 insertions, 31 deletions
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c
index 4b3b5135f5c1..d9c144043d72 100644
--- a/drivers/input/serio/ambakmi.c
+++ b/drivers/input/serio/ambakmi.c
@@ -134,7 +134,7 @@ static int amba_kmi_probe(struct amba_device *dev, void *id)
memset(kmi, 0, sizeof(struct amba_kmi_port));
memset(io, 0, sizeof(struct serio));
- io->type = SERIO_8042;
+ io->id.type = SERIO_8042;
io->write = amba_kmi_write;
io->open = amba_kmi_open;
io->close = amba_kmi_close;
diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c
index ee785460b78f..54b5edad0941 100644
--- a/drivers/input/serio/ct82c710.c
+++ b/drivers/input/serio/ct82c710.c
@@ -181,7 +181,7 @@ static struct serio * __init ct82c710_allocate_port(void)
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
memset(serio, 0, sizeof(struct serio));
- serio->type = SERIO_8042;
+ serio->id.type = SERIO_8042;
serio->open = ct82c710_open;
serio->close = ct82c710_close;
serio->write = ct82c710_write;
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
index 401d750116d5..d530e70a3b47 100644
--- a/drivers/input/serio/gscps2.c
+++ b/drivers/input/serio/gscps2.c
@@ -363,11 +363,7 @@ static int __init gscps2_probe(struct parisc_device *dev)
snprintf(serio->name, sizeof(serio->name), "GSC PS/2 %s",
(ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse");
strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
- serio->idbus = BUS_GSC;
- serio->idvendor = PCI_VENDOR_ID_HP;
- serio->idproduct = 0x0001;
- serio->idversion = 0x0010;
- serio->type = SERIO_8042;
+ serio->id.type = SERIO_8042;
serio->write = gscps2_write;
serio->open = gscps2_open;
serio->close = gscps2_close;
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index cc6a82e26bdb..496e42fbe855 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -971,7 +971,7 @@ static void __init i8042_create_kbd_port(void)
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
memset(serio, 0, sizeof(struct serio));
- serio->type = i8042_direct ? SERIO_8042 : SERIO_8042_XL;
+ serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL;
serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write;
serio->open = i8042_open;
serio->close = i8042_close;
@@ -995,7 +995,7 @@ static void __init i8042_create_aux_port(void)
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
memset(serio, 0, sizeof(struct serio));
- serio->type = SERIO_8042;
+ serio->id.type = SERIO_8042;
serio->write = i8042_aux_write;
serio->open = i8042_open;
serio->close = i8042_close;
@@ -1019,7 +1019,7 @@ static void __init i8042_create_mux_port(int index)
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
memset(serio, 0, sizeof(struct serio));
- serio->type = SERIO_8042;
+ serio->id.type = SERIO_8042;
serio->write = i8042_aux_write;
serio->open = i8042_open;
serio->close = i8042_close;
diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c
index 72b15b20d2a5..9880fc145d90 100644
--- a/drivers/input/serio/maceps2.c
+++ b/drivers/input/serio/maceps2.c
@@ -125,7 +125,7 @@ static struct serio * __init maceps2_allocate_port(int idx)
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
memset(serio, 0, sizeof(struct serio));
- serio->type = SERIO_8042;
+ serio->id.type = SERIO_8042;
serio->write = maceps2_write;
serio->open = maceps2_open;
serio->close = maceps2_close;
diff --git a/drivers/input/serio/parkbd.c b/drivers/input/serio/parkbd.c
index d0510ecaf9ac..40b937e77334 100644
--- a/drivers/input/serio/parkbd.c
+++ b/drivers/input/serio/parkbd.c
@@ -158,7 +158,7 @@ static struct serio * __init parkbd_allocate_serio(void)
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
memset(serio, 0, sizeof(struct serio));
- serio->type = parkbd_mode;
+ serio->id.type = parkbd_mode;
serio->write = parkbd_write,
strlcpy(serio->name, "PARKBD AT/XT keyboard adapter", sizeof(serio->name));
snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", parkbd_dev->port->name);
diff --git a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c
index 489749e7c9d0..cb4cbe18c199 100644
--- a/drivers/input/serio/pcips2.c
+++ b/drivers/input/serio/pcips2.c
@@ -150,7 +150,7 @@ static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_i
memset(ps2if, 0, sizeof(struct pcips2_data));
memset(serio, 0, sizeof(struct serio));
- serio->type = SERIO_8042;
+ serio->id.type = SERIO_8042;
serio->write = pcips2_write;
serio->open = pcips2_open;
serio->close = pcips2_close;
diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
index ab4425db304c..46093c507988 100644
--- a/drivers/input/serio/q40kbd.c
+++ b/drivers/input/serio/q40kbd.c
@@ -122,7 +122,7 @@ static struct serio * __init q40kbd_allocate_port(void)
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
memset(serio, 0, sizeof(struct serio));
- serio->type = SERIO_8042;
+ serio->id.type = SERIO_8042;
serio->open = q40kbd_open;
serio->close = q40kbd_close;
serio->dev.parent = &q40kbd_device->dev;
diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
index 49a58410295e..106f5eefd89a 100644
--- a/drivers/input/serio/rpckbd.c
+++ b/drivers/input/serio/rpckbd.c
@@ -115,7 +115,7 @@ static int __devinit rpckbd_probe(struct device *dev)
return -ENOMEM;
memset(serio, 0, sizeof(struct serio));
- serio->type = SERIO_8042;
+ serio->id.type = SERIO_8042;
serio->write = rpckbd_write;
serio->open = rpckbd_open;
serio->close = rpckbd_close;
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
index 62937f5b3e57..d6433958a9d8 100644
--- a/drivers/input/serio/sa1111ps2.c
+++ b/drivers/input/serio/sa1111ps2.c
@@ -245,7 +245,7 @@ static int ps2_probe(struct sa1111_dev *dev)
memset(ps2if, 0, sizeof(struct ps2if));
memset(serio, 0, sizeof(struct serio));
- serio->type = SERIO_8042;
+ serio->id.type = SERIO_8042;
serio->write = ps2_write;
serio->open = ps2_open;
serio->close = ps2_close;
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 8eaa261e6545..2a9031a99744 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -68,17 +68,33 @@ static void serio_connect_port(struct serio *serio, struct serio_driver *drv);
static void serio_reconnect_port(struct serio *serio);
static void serio_disconnect_port(struct serio *serio);
+static int serio_match_port(const struct serio_device_id *ids, struct serio *serio)
+{
+ while (ids->type || ids->proto) {
+ if ((ids->type == SERIO_ANY || ids->type == serio->id.type) &&
+ (ids->proto == SERIO_ANY || ids->proto == serio->id.proto) &&
+ (ids->extra == SERIO_ANY || ids->extra == serio->id.extra) &&
+ (ids->id == SERIO_ANY || ids->id == serio->id.id))
+ return 1;
+ ids++;
+ }
+ return 0;
+}
+
static int serio_bind_driver(struct serio *serio, struct serio_driver *drv)
{
get_driver(&drv->driver);
- drv->connect(serio, drv);
- if (serio->drv) {
- down_write(&serio_bus.subsys.rwsem);
- serio->dev.driver = &drv->driver;
- device_bind_driver(&serio->dev);
- up_write(&serio_bus.subsys.rwsem);
- return 1;
+ if (serio_match_port(drv->id_table, serio)) {
+ drv->connect(serio, drv);
+
+ if (serio->drv) {
+ down_write(&serio_bus.subsys.rwsem);
+ serio->dev.driver = &drv->driver;
+ device_bind_driver(&serio->dev);
+ up_write(&serio_bus.subsys.rwsem);
+ return 1;
+ }
}
put_driver(&drv->driver);
@@ -648,6 +664,48 @@ static void serio_set_drv(struct serio *serio, struct serio_driver *drv)
up(&serio->drv_sem);
}
+#ifdef CONFIG_HOTPLUG
+
+#define PUT_ENVP(fmt, val) \
+do { \
+ envp[i++] = buffer; \
+ length += snprintf(buffer, buffer_size - length, fmt, val); \
+ if (buffer_size - length <= 0 || i >= num_envp) \
+ return -ENOMEM; \
+ length++; \
+ buffer += length; \
+} while (0)
+static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+{
+ struct serio *serio;
+ int i = 0;
+ int length = 0;
+
+ if (!dev)
+ return -ENODEV;
+
+ serio = to_serio_port(dev);
+
+ PUT_ENVP("SERIO_TYPE=%02x", serio->id.type);
+ PUT_ENVP("SERIO_PROTO=%02x", serio->id.proto);
+ PUT_ENVP("SERIO_ID=%02x", serio->id.id);
+ PUT_ENVP("SERIO_EXTRA=%02x", serio->id.extra);
+
+ envp[i] = NULL;
+
+ return 0;
+}
+#undef PUT_ENVP
+
+#else
+
+static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+{
+ return -ENODEV;
+}
+
+#endif /* CONFIG_HOTPLUG */
+
/* called from serio_driver->connect/disconnect methods under serio_sem */
int serio_open(struct serio *serio, struct serio_driver *drv)
{
@@ -698,6 +756,7 @@ static int __init serio_init(void)
serio_bus.dev_attrs = serio_device_attrs;
serio_bus.drv_attrs = serio_driver_attrs;
+ serio_bus.hotplug = serio_hotplug;
bus_register(&serio_bus);
return 0;
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 6e9144799034..6da5cea8129c 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -275,9 +275,6 @@ static void serio_raw_connect(struct serio *serio, struct serio_driver *drv)
struct serio_raw *serio_raw;
int err;
- if ((serio->type & SERIO_TYPE) != SERIO_8042)
- return;
-
if (!(serio_raw = kmalloc(sizeof(struct serio_raw), GFP_KERNEL))) {
printk(KERN_ERR "serio_raw.c: can't allocate memory for a device\n");
return;
@@ -363,11 +360,24 @@ static void serio_raw_disconnect(struct serio *serio)
up(&serio_raw_sem);
}
+static struct serio_device_id serio_raw_serio_ids[] = {
+ {
+ .type = SERIO_8042,
+ .proto = SERIO_ANY,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, serio_raw_serio_ids);
+
static struct serio_driver serio_raw_drv = {
.driver = {
.name = "serio_raw",
},
.description = DRIVER_DESC,
+ .id_table = serio_raw_serio_ids,
.interrupt = serio_raw_interrupt,
.connect = serio_raw_connect,
.reconnect = serio_raw_reconnect,
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
index 538ccf180797..22f73683952b 100644
--- a/drivers/input/serio/serport.c
+++ b/drivers/input/serio/serport.c
@@ -49,7 +49,7 @@ static void serport_serio_close(struct serio *serio)
{
struct serport *serport = serio->port_data;
- serport->serio->type = 0;
+ serport->serio->id.type = 0;
wake_up_interruptible(&serport->wait);
}
@@ -84,7 +84,7 @@ static int serport_ldisc_open(struct tty_struct *tty)
memset(serio, 0, sizeof(struct serio));
strlcpy(serio->name, "Serial port", sizeof(serio->name));
snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", tty_name(tty, name));
- serio->type = SERIO_RS232;
+ serio->id.type = SERIO_RS232;
serio->write = serport_serio_write;
serio->close = serport_serio_close;
serio->port_data = serport;
@@ -148,7 +148,7 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
serio_register_port(serport->serio);
printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name));
- wait_event_interruptible(serport->wait, !serport->serio->type);
+ wait_event_interruptible(serport->wait, !serport->serio->id.type);
serio_unregister_port(serport->serio);
clear_bit(SERPORT_BUSY, &serport->flags);
@@ -163,9 +163,19 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg)
{
struct serport *serport = (struct serport*) tty->disc_data;
+ struct serio *serio = serport->serio;
+ unsigned long type;
- if (cmd == SPIOCSTYPE)
- return get_user(serport->serio->type, (unsigned long __user *) arg);
+ if (cmd == SPIOCSTYPE) {
+ if (get_user(type, (unsigned long __user *) arg))
+ return -EFAULT;
+
+ serio->id.proto = type & 0x000000ff;
+ serio->id.id = (type & 0x0000ff00) >> 8;
+ serio->id.extra = (type & 0x00ff0000) >> 16;
+
+ return 0;
+ }
return -EINVAL;
}