Commit e122050f authored by Dmitry Torokhov's avatar Dmitry Torokhov Committed by Vojtech Pavlik

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: default avatarDmitry Torokhov <dtor@mail.ru>
Signed-off-by: default avatarVojtech Pavlik <vojtech@suse.cz>
parent 8f9ba920
......@@ -129,10 +129,9 @@ static irqreturn_t iforce_serio_irq(struct serio *serio,
static void iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
{
struct iforce *iforce;
if (serio->type != (SERIO_RS232 | SERIO_IFORCE))
return;
if (!(iforce = kmalloc(sizeof(struct iforce), GFP_KERNEL))) return;
if (!(iforce = kmalloc(sizeof(struct iforce), GFP_KERNEL)))
return;
memset(iforce, 0, sizeof(struct iforce));
iforce->bus = IFORCE_232;
......@@ -164,11 +163,24 @@ static void iforce_serio_disconnect(struct serio *serio)
kfree(iforce);
}
static struct serio_device_id iforce_serio_ids[] = {
{
.type = SERIO_RS232,
.proto = SERIO_IFORCE,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{ 0 }
};
MODULE_DEVICE_TABLE(serio, iforce_serio_ids);
struct serio_driver iforce_serio_drv = {
.driver = {
.name = "iforce",
},
.description = "RS232 I-Force joysticks and wheels driver",
.id_table = iforce_serio_ids,
.write_wakeup = iforce_serio_write_wakeup,
.interrupt = iforce_serio_irq,
.connect = iforce_serio_connect,
......
......@@ -146,8 +146,8 @@ static void magellan_disconnect(struct serio *serio)
/*
* magellan_connect() is the routine that is called when someone adds a
* new serio device. It looks for the Magellan, and if found, registers
* it as an input device.
* new serio device that supports Magellan protocol and registers it as
* an input device.
*/
static void magellan_connect(struct serio *serio, struct serio_driver *drv)
......@@ -155,9 +155,6 @@ static void magellan_connect(struct serio *serio, struct serio_driver *drv)
struct magellan *magellan;
int i, t;
if (serio->type != (SERIO_RS232 | SERIO_MAGELLAN))
return;
if (!(magellan = kmalloc(sizeof(struct magellan), GFP_KERNEL)))
return;
......@@ -202,14 +199,27 @@ static void magellan_connect(struct serio *serio, struct serio_driver *drv)
}
/*
* The serio device structure.
* The serio driver structure.
*/
static struct serio_device_id magellan_serio_ids[] = {
{
.type = SERIO_RS232,
.proto = SERIO_MAGELLAN,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{ 0 }
};
MODULE_DEVICE_TABLE(serio, magellan_serio_ids);
static struct serio_driver magellan_drv = {
.driver = {
.name = "magellan",
},
.description = DRIVER_DESC,
.id_table = magellan_serio_ids,
.interrupt = magellan_interrupt,
.connect = magellan_connect,
.disconnect = magellan_disconnect,
......
......@@ -201,8 +201,8 @@ static void spaceball_disconnect(struct serio *serio)
/*
* spaceball_connect() is the routine that is called when someone adds a
* new serio device. It looks for the Magellan, and if found, registers
* it as an input device.
* new serio device that supports Spaceball protocol and registers it as
* an input device.
*/
static void spaceball_connect(struct serio *serio, struct serio_driver *drv)
......@@ -210,10 +210,7 @@ static void spaceball_connect(struct serio *serio, struct serio_driver *drv)
struct spaceball *spaceball;
int i, t, id;
if ((serio->type & ~SERIO_ID) != (SERIO_RS232 | SERIO_SPACEBALL))
return;
if ((id = (serio->type & SERIO_ID) >> 8) > SPACEBALL_MAX_ID)
if ((id = serio->id.id) > SPACEBALL_MAX_ID)
return;
if (!(spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL)))
......@@ -272,14 +269,27 @@ static void spaceball_connect(struct serio *serio, struct serio_driver *drv)
}
/*
* The serio device structure.
* The serio driver structure.
*/
static struct serio_device_id spaceball_serio_ids[] = {
{
.type = SERIO_RS232,
.proto = SERIO_SPACEBALL,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{ 0 }
};
MODULE_DEVICE_TABLE(serio, spaceball_serio_ids);
static struct serio_driver spaceball_drv = {
.driver = {
.name = "spaceball",
},
.description = DRIVER_DESC,
.id_table = spaceball_serio_ids,
.interrupt = spaceball_interrupt,
.connect = spaceball_connect,
.disconnect = spaceball_disconnect,
......
......@@ -162,7 +162,7 @@ static void spaceorb_disconnect(struct serio *serio)
/*
* spaceorb_connect() is the routine that is called when someone adds a
* new serio device. It looks for the SpaceOrb/Avenger, and if found, registers
* new serio device that supports SpaceOrb/Avenger protocol and registers
* it as an input device.
*/
......@@ -171,9 +171,6 @@ static void spaceorb_connect(struct serio *serio, struct serio_driver *drv)
struct spaceorb *spaceorb;
int i, t;
if (serio->type != (SERIO_RS232 | SERIO_SPACEORB))
return;
if (!(spaceorb = kmalloc(sizeof(struct spaceorb), GFP_KERNEL)))
return;
memset(spaceorb, 0, sizeof(struct spaceorb));
......@@ -216,14 +213,27 @@ static void spaceorb_connect(struct serio *serio, struct serio_driver *drv)
}
/*
* The serio device structure.
* The serio driver structure.
*/
static struct serio_device_id spaceorb_serio_ids[] = {
{
.type = SERIO_RS232,
.proto = SERIO_SPACEORB,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{ 0 }
};
MODULE_DEVICE_TABLE(serio, spaceorb_serio_ids);
static struct serio_driver spaceorb_drv = {
.driver = {
.name = "spaceorb",
},
.description = DRIVER_DESC,
.id_table = spaceorb_serio_ids,
.interrupt = spaceorb_interrupt,
.connect = spaceorb_connect,
.disconnect = spaceorb_disconnect,
......
......@@ -134,8 +134,8 @@ static void stinger_disconnect(struct serio *serio)
/*
* stinger_connect() is the routine that is called when someone adds a
* new serio device. It looks for the Stinger, and if found, registers
* it as an input device.
* new serio device that supports Stinger protocol and registers it as
* an input device.
*/
static void stinger_connect(struct serio *serio, struct serio_driver *drv)
......@@ -143,9 +143,6 @@ static void stinger_connect(struct serio *serio, struct serio_driver *drv)
struct stinger *stinger;
int i;
if (serio->type != (SERIO_RS232 | SERIO_STINGER))
return;
if (!(stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL)))
return;
......@@ -191,14 +188,27 @@ static void stinger_connect(struct serio *serio, struct serio_driver *drv)
}
/*
* The serio device structure.
* The serio driver structure.
*/
static struct serio_device_id stinger_serio_ids[] = {
{
.type = SERIO_RS232,
.proto = SERIO_STINGER,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{ 0 }
};
MODULE_DEVICE_TABLE(serio, stinger_serio_ids);
static struct serio_driver stinger_drv = {
.driver = {
.name = "stinger",
},
.description = DRIVER_DESC,
.id_table = stinger_serio_ids,
.interrupt = stinger_interrupt,
.connect = stinger_connect,
.disconnect = stinger_disconnect,
......
......@@ -195,9 +195,6 @@ static void twidjoy_connect(struct serio *serio, struct serio_driver *drv)
struct twidjoy *twidjoy;
int i;
if (serio->type != (SERIO_RS232 | SERIO_TWIDJOY))
return;
if (!(twidjoy = kmalloc(sizeof(struct twidjoy), GFP_KERNEL)))
return;
......@@ -248,14 +245,27 @@ static void twidjoy_connect(struct serio *serio, struct serio_driver *drv)
}
/*
* The serio device structure.
* The serio driver structure.
*/
static struct serio_device_id twidjoy_serio_ids[] = {
{
.type = SERIO_RS232,
.proto = SERIO_TWIDJOY,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{ 0 }
};
MODULE_DEVICE_TABLE(serio, twidjoy_serio_ids);
static struct serio_driver twidjoy_drv = {
.driver = {
.name = "twidjoy",
},
.description = DRIVER_DESC,
.id_table = twidjoy_serio_ids,
.interrupt = twidjoy_interrupt,
.connect = twidjoy_connect,
.disconnect = twidjoy_disconnect,
......
......@@ -148,9 +148,6 @@ static void warrior_connect(struct serio *serio, struct serio_driver *drv)
struct warrior *warrior;
int i;
if (serio->type != (SERIO_RS232 | SERIO_WARRIOR))
return;
if (!(warrior = kmalloc(sizeof(struct warrior), GFP_KERNEL)))
return;
......@@ -202,14 +199,27 @@ static void warrior_connect(struct serio *serio, struct serio_driver *drv)
}
/*
* The serio device structure.
* The serio driver structure.
*/
static struct serio_device_id warrior_serio_ids[] = {
{
.type = SERIO_RS232,
.proto = SERIO_WARRIOR,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{ 0 }
};
MODULE_DEVICE_TABLE(serio, warrior_serio_ids);
static struct serio_driver warrior_drv = {
.driver = {
.name = "warrior",
},
.description = DRIVER_DESC,
.id_table = warrior_serio_ids,
.interrupt = warrior_interrupt,
.connect = warrior_connect,
.disconnect = warrior_disconnect,
......
......@@ -785,7 +785,7 @@ static void atkbd_connect(struct serio *serio, struct serio_driver *drv)
ps2_init(&atkbd->ps2dev, serio);
switch (serio->type & SERIO_TYPE) {
switch (serio->id.type) {
case SERIO_8042_XL:
atkbd->translated = 1;
......@@ -793,12 +793,6 @@ static void atkbd_connect(struct serio *serio, struct serio_driver *drv)
if (serio->write)
atkbd->write = 1;
break;
case SERIO_RS232:
if ((serio->type & SERIO_PROTO) == SERIO_PS2SER)
break;
default:
kfree(atkbd);
return;
}
atkbd->softraw = atkbd_softraw;
......@@ -899,11 +893,36 @@ static int atkbd_reconnect(struct serio *serio)
return 0;
}
static struct serio_device_id atkbd_serio_ids[] = {
{
.type = SERIO_8042,
.proto = SERIO_ANY,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{
.type = SERIO_8042_XL,
.proto = SERIO_ANY,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{
.type = SERIO_RS232,
.proto = SERIO_PS2SER,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{ 0 }
};
MODULE_DEVICE_TABLE(serio, atkbd_serio_ids);
static struct serio_driver atkbd_drv = {
.driver = {
.name = "atkbd",
},
.description = DRIVER_DESC,
.id_table = atkbd_serio_ids,
.interrupt = atkbd_interrupt,
.connect = atkbd_connect,
.reconnect = atkbd_reconnect,
......
......@@ -629,11 +629,6 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv)
struct lkkbd *lk;
int i;
if ((serio->type & SERIO_TYPE) != SERIO_RS232)
return;
if ((serio->type & SERIO_PROTO) != SERIO_LKKBD)
return;
if (!(lk = kmalloc (sizeof (struct lkkbd), GFP_KERNEL)))
return;
memset (lk, 0, sizeof (struct lkkbd));
......@@ -708,11 +703,24 @@ lkkbd_disconnect (struct serio *serio)
kfree (lk);
}
static struct serio_device_id lkkbd_serio_ids[] = {
{
.type = SERIO_RS232,
.proto = SERIO_LKKBD,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{ 0 }
};
MODULE_DEVICE_TABLE(serio, lkkbd_serio_ids);
static struct serio_driver lkkbd_drv = {
.driver = {
.name = "lkkbd",
},
.description = DRIVER_DESC,
.id_table = lkkbd_serio_ids,
.connect = lkkbd_connect,
.disconnect = lkkbd_disconnect,
.interrupt = lkkbd_interrupt,
......
......@@ -89,9 +89,6 @@ void nkbd_connect(struct serio *serio, struct serio_driver *drv)
struct nkbd *nkbd;
int i;
if (serio->type != (SERIO_RS232 | SERIO_NEWTON))
return;
if (!(nkbd = kmalloc(sizeof(struct nkbd), GFP_KERNEL)))
return;
......@@ -145,11 +142,24 @@ void nkbd_disconnect(struct serio *serio)
kfree(nkbd);
}
static struct serio_device_id nkbd_serio_ids[] = {
{
.type = SERIO_RS232,
.proto = SERIO_NEWTON,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{ 0 }
};
MODULE_DEVICE_TABLE(serio, nkbd_serio_ids);
struct serio_driver nkbd_drv = {
.driver = {
.name = "newtonkbd",
},
.description = DRIVER_DESC,
.id_table = nkbd_serio_ids,
.interrupt = nkbd_interrupt,
.connect = nkbd_connect,
.disconnect = nkbd_disconnect,
......
......@@ -228,12 +228,6 @@ static void sunkbd_connect(struct serio *serio, struct serio_driver *drv)
struct sunkbd *sunkbd;
int i;
if ((serio->type & SERIO_TYPE) != SERIO_RS232)
return;
if ((serio->type & SERIO_PROTO) && (serio->type & SERIO_PROTO) != SERIO_SUNKBD)
return;
if (!(sunkbd = kmalloc(sizeof(struct sunkbd), GFP_KERNEL)))
return;
......@@ -307,11 +301,30 @@ static void sunkbd_disconnect(struct serio *serio)
kfree(sunkbd);
}
static struct serio_device_id sunkbd_serio_ids[] = {
{
.type = SERIO_RS232,
.proto = SERIO_SUNKBD,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{
.type = SERIO_RS232,
.proto = SERIO_UNKNOWN, /* sunkbd does probe */
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{ 0 }
};
MODULE_DEVICE_TABLE(serio, sunkbd_serio_ids);
static struct serio_driver sunkbd_drv = {
.driver = {
.name = "sunkbd",
},
.description = DRIVER_DESC,
.id_table = sunkbd_serio_ids,
.interrupt = sunkbd_interrupt,
.connect = sunkbd_connect,
.disconnect = sunkbd_disconnect,
......
......@@ -93,9 +93,6 @@ void xtkbd_connect(struct serio *serio, struct serio_driver *drv)
struct xtkbd *xtkbd;
int i;
if ((serio->type & SERIO_TYPE) != SERIO_XT)
return;
if (!(xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL)))
return;
......@@ -149,11 +146,24 @@ void xtkbd_disconnect(struct serio *serio)
kfree(xtkbd);
}
static struct serio_device_id xtkbd_serio_ids[] = {
{
.type = SERIO_XT,
.proto = SERIO_ANY,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{ 0 }
};
MODULE_DEVICE_TABLE(serio, xtkbd_serio_ids);
struct serio_driver xtkbd_drv = {
.driver = {
.name = "xtkbd",
},
.description = DRIVER_DESC,
.id_table = xtkbd_serio_ids,
.interrupt = xtkbd_interrupt,
.connect = xtkbd_connect,
.disconnect = xtkbd_disconnect,
......
......@@ -654,7 +654,7 @@ static void psmouse_disconnect(struct serio *serio)
psmouse = serio_get_drvdata(serio);
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) {
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = serio_get_drvdata(serio->parent);
if (parent->pt_deactivate)
parent->pt_deactivate(parent);
......@@ -679,15 +679,11 @@ static void psmouse_connect(struct serio *serio, struct serio_driver *drv)
{
struct psmouse *psmouse, *parent = NULL;
if ((serio->type & SERIO_TYPE) != SERIO_8042 &&
(serio->type & SERIO_TYPE) != SERIO_PS_PSTHRU)
return;
/*
* If this is a pass-through port deactivate parent so the device
* connected to this port can be successfully identified
*/
if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) {
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = serio_get_drvdata(serio->parent);
psmouse_deactivate(parent);
}
......@@ -787,7 +783,7 @@ static int psmouse_reconnect(struct serio *serio)
return -1;
}
if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) {
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = serio_get_drvdata(serio->parent);
psmouse_deactivate(parent);
}
......@@ -822,12 +818,30 @@ static int psmouse_reconnect(struct serio *serio)
return rc;
}
static struct serio_device_id psmouse_serio_ids[] = {
{
.type = SERIO_8042,
.proto = SERIO_ANY,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{
.type = SERIO_PS_PSTHRU,
.proto = SERIO_ANY,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{ 0 }
};
MODULE_DEVICE_TABLE(serio, psmouse_serio_ids);
static struct serio_driver psmouse_drv = {
.driver = {
.name = "psmouse",
},
.description = DRIVER_DESC,
.id_table = psmouse_serio_ids,
.interrupt = psmouse_interrupt,
.connect = psmouse_connect,
.reconnect = psmouse_reconnect,
......@@ -874,7 +888,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
goto out;
}
if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) {
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = serio_get_drvdata(serio->parent);
psmouse_deactivate(parent);
}
......
......@@ -246,10 +246,7 @@ static void sermouse_connect(struct serio *serio, struct serio_driver *drv)
struct sermouse *sermouse;
unsigned char c;
if ((serio->type & SERIO_TYPE) != SERIO_RS232)
return;
if (!(serio->type & SERIO_PROTO) || ((serio->type & SERIO_PROTO) > SERIO_MZPP))
if (!serio->id.proto || serio->id.proto > SERIO_MZPP)
return;
if (!(sermouse = kmalloc(sizeof(struct sermouse), GFP_KERNEL)))
......@@ -263,8 +260,8 @@ static void sermouse_connect(struct serio *serio, struct serio_driver *drv)
sermouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
sermouse->dev.private = sermouse;
sermouse->type = serio->type & SERIO_PROTO;
c = (serio->type & SERIO_EXTRA) >> 16;
sermouse->type = serio->id.proto;
c = serio->id.extra;
if (c & 0x01) set_bit(BTN_MIDDLE, sermouse->dev.keybit);
if (c & 0x02) set_bit(BTN_SIDE, sermouse->dev.keybit);
......@@ -295,11 +292,60 @@ static void sermouse_connect(struct serio *serio, struct serio_driver *drv)
printk(KERN_INFO "input: %s on %s\n", sermouse_protocols[sermouse->type], serio->phys);
}
static struct serio_device_id sermouse_serio_ids[] = {
{
.type = SERIO_RS232,
.proto = SERIO_MSC,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{
.type = SERIO_RS232,
.proto = SERIO_SUN,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{
.type = SERIO_RS232,
.proto = SERIO_MS,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{
.type = SERIO_RS232,
.proto = SERIO_MP,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{
.type = SERIO_RS232,
.proto = SERIO_MZ,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{
.type = SERIO_RS232,
.proto = SERIO_MZP,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{
.type = SERIO_RS232,
.proto = SERIO_MZPP,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{ 0 }
};
MODULE_DEVICE_TABLE(serio, sermouse_serio_ids);
static struct serio_driver sermouse_drv = {
.driver = {
.name = "sermouse",
},
.description = DRIVER_DESC,
.id_table = sermouse_serio_ids,
.interrupt = sermouse_interrupt,
.connect = sermouse_connect,
.disconnect = sermouse_disconnect,
......
......@@ -288,7 +288,7 @@ static void synaptics_pt_create(struct psmouse *psmouse)
memset(serio, 0, sizeof(struct serio));
serio->type = SERIO_PS_PSTHRU;
serio->id.type = SERIO_PS_PSTHRU;
strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name));
serio->write = synaptics_pt_write;
......
......@@ -494,11 +494,6 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
{
struct vsxxxaa *mouse;
if ((serio->type & SERIO_TYPE) != SERIO_RS232)
return;
if ((serio->type & SERIO_PROTO) != SERIO_VSXXXAA)
return;
if (!(mouse = kmalloc (sizeof (struct vsxxxaa), GFP_KERNEL)))
return;
......@@ -551,11 +546,24 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
printk (KERN_INFO "input: %s on %s\n", mouse->name, mouse->phys);
}
static struct serio_device_id vsxxaa_serio_ids[] = {
{
.type = SERIO_RS232,
.proto = SERIO_VSXXXAA,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{ 0 }
};
MODULE_DEVICE_TABLE(serio, vsxxaa_serio_ids);
static struct serio_driver vsxxxaa_drv = {
.driver = {
.name = "vsxxxaa",
},
.description = DRIVER_DESC,
.id_table = vsxxaa_serio_ids,
.connect = vsxxxaa_connect,
.interrupt = vsxxxaa_interrupt,
.disconnect = vsxxxaa_disconnect,
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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,
......
......@@ -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;
}
......
......@@ -111,17 +111,14 @@ static void gunze_disconnect(struct serio *serio)
/*
* gunze_connect() is the routine that is called when someone adds a
* new serio device. It looks whether it was registered as a Gunze touchscreen
* and if yes, registers it as an input device.
* new serio device that supports Gunze protocol and registers it as
* an input device.
*/
static void gunze_connect(struct serio *serio, struct serio_driver *drv)
{
struct gunze *gunze;
if (serio->type != (SERIO_RS232 | SERIO_GUNZE))
return;
if (!(gunze = kmalloc(sizeof(struct gunze), GFP_KERNEL)))
return;
......@@ -159,14 +156,27 @@ static void gunze_connect(struct serio *serio, struct serio_driver *drv)
}
/*
* The serio device structure.
* The serio driver structure.
*/
static struct serio_device_id gunze_serio_ids[] = {
{
.type = SERIO_RS232,
.proto = SERIO_GUNZE,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{ 0 }
};
MODULE_DEVICE_TABLE(serio, gunze_serio_ids);
static struct serio_driver gunze_drv = {
.driver = {
.name = "gunze",
},
.description = DRIVER_DESC,
.id_table = gunze_serio_ids,
.interrupt = gunze_interrupt,
.connect = gunze_connect,
.disconnect = gunze_disconnect,
......
......@@ -102,6 +102,7 @@ struct h3600_dev {
struct input_dev dev;
struct pm_dev *pm_dev;
struct serio *serio;
struct pm_dev *pm_dev;
unsigned char event; /* event ID from packet */
unsigned char chksum;
unsigned char len;
......@@ -373,16 +374,13 @@ static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data,
/*
* h3600ts_connect() is the routine that is called when someone adds a
* new serio device. It looks whether it was registered as a H3600 touchscreen
* and if yes, registers it as an input device.
* new serio device that supports H3600 protocol and registers it as
* an input device.
*/
static void h3600ts_connect(struct serio *serio, struct serio_driver *drv)
{
struct h3600_dev *ts;
if (serio->type != (SERIO_RS232 | SERIO_H3600))
return;
if (!(ts = kmalloc(sizeof(struct h3600_dev), GFP_KERNEL)))
return;
......@@ -481,14 +479,27 @@ static void h3600ts_disconnect(struct serio *serio)
}
/*
* The serio device structure.
* The serio driver structure.
*/
static struct serio_device_id h3600ts_serio_ids[] = {
{
.type = SERIO_RS232,
.proto = SERIO_H3600,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{ 0 }
};
MODULE_DEVICE_TABLE(serio, h3600ts_serio_ids);
static struct serio_driver h3600ts_drv = {
.driver = {
.name = "h3600ts",
},
.description = DRIVER_DESC,
.id_table = h3600ts_serio_ids,
.interrupt = h3600ts_interrupt,
.connect = h3600ts_connect,
.disconnect = h3600ts_disconnect,
......
......@@ -1314,12 +1314,13 @@ static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up, int channel)
serio->port_data = up;
serio->type = SERIO_RS232;
serio->id.type = SERIO_RS232;
if (up->su_type == SU_PORT_KBD) {
serio->type |= SERIO_SUNKBD;
serio->id.proto = SERIO_SUNKBD;
strlcpy(serio->name, "sukbd", sizeof(serio->name));
} else {
serio->type |= (SERIO_SUN | (1 << 16));
serio->id.proto = SERIO_SUN;
serio->id.extra = 1;
strlcpy(serio->name, "sums", sizeof(serio->name));
}
strlcpy(serio->phys, (channel == 0 ? "su/serio0" : "su/serio1"),
......
......@@ -1562,12 +1562,13 @@ static void __init sunzilog_register_serio(struct uart_sunzilog_port *up, int ch
serio->port_data = up;
serio->type = SERIO_RS232;
serio->id.type = SERIO_RS232;
if (channel == KEYBOARD_LINE) {
serio->type |= SERIO_SUNKBD;
serio->id.proto = SERIO_SUNKBD;
strlcpy(serio->name, "zskbd", sizeof(serio->name));
} else {
serio->type |= (SERIO_SUN | (1 << 16));
serio->id.proto = SERIO_SUN;
serio->id.extra = 1;
strlcpy(serio->name, "zsms", sizeof(serio->name));
}
strlcpy(serio->phys,
......
......@@ -20,6 +20,13 @@
#include <linux/spinlock.h>
#include <linux/device.h>
struct serio_device_id {
unsigned char type;
unsigned char extra;
unsigned char id;
unsigned char proto;
};
struct serio {
void *port_data;
......@@ -28,13 +35,7 @@ struct serio {
unsigned int manual_bind;
unsigned short idbus;
unsigned short idvendor;
unsigned short idproduct;
unsigned short idversion;
unsigned long type;
unsigned long event;
struct serio_device_id id;
spinlock_t lock; /* protects critical sections from port's interrupt handler */
......@@ -59,6 +60,7 @@ struct serio_driver {
void *private;
char *description;
struct serio_device_id *id_table;
unsigned int manual_bind;
void (*write_wakeup)(struct serio *);
......@@ -160,15 +162,22 @@ static __inline__ void serio_unpin_driver(struct serio *serio)
#define SERIO_PARITY 2
#define SERIO_FRAME 4
#define SERIO_TYPE 0xff000000UL
#define SERIO_XT 0x00000000UL
#define SERIO_8042 0x01000000UL
#define SERIO_RS232 0x02000000UL
#define SERIO_HIL_MLC 0x03000000UL
#define SERIO_PS_PSTHRU 0x05000000UL
#define SERIO_8042_XL 0x06000000UL
#define SERIO_ANY 0xff
#define SERIO_PROTO 0xFFUL
/*
* Serio types
*/
#define SERIO_XT 0x00
#define SERIO_8042 0x01
#define SERIO_RS232 0x02
#define SERIO_HIL_MLC 0x03
#define SERIO_PS_PSTHRU 0x05
#define SERIO_8042_XL 0x06
/*
* Serio types
*/
#define SERIO_UNKNOWN 0x00
#define SERIO_MSC 0x01
#define SERIO_SUN 0x02
#define SERIO_MS 0x03
......@@ -196,7 +205,4 @@ static __inline__ void serio_unpin_driver(struct serio *serio)
#define SERIO_SEMTECH 0x27
#define SERIO_LKKBD 0x28
#define SERIO_ID 0xff00UL
#define SERIO_EXTRA 0xff0000UL
#endif
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