Commit 5821dbd4 authored by Dmitry Torokhov's avatar Dmitry Torokhov

Input: serio sysfs integration

Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent d537c384
...@@ -37,9 +37,9 @@ obj-$(CONFIG_PARIDE) += block/paride/ ...@@ -37,9 +37,9 @@ obj-$(CONFIG_PARIDE) += block/paride/
obj-$(CONFIG_TC) += tc/ obj-$(CONFIG_TC) += tc/
obj-$(CONFIG_USB) += usb/ obj-$(CONFIG_USB) += usb/
obj-$(CONFIG_USB_GADGET) += usb/gadget/ obj-$(CONFIG_USB_GADGET) += usb/gadget/
obj-$(CONFIG_SERIO) += input/serio/
obj-$(CONFIG_INPUT) += input/ obj-$(CONFIG_INPUT) += input/
obj-$(CONFIG_GAMEPORT) += input/gameport/ obj-$(CONFIG_GAMEPORT) += input/gameport/
obj-$(CONFIG_SERIO) += input/serio/
obj-$(CONFIG_I2O) += message/ obj-$(CONFIG_I2O) += message/
obj-$(CONFIG_I2C) += i2c/ obj-$(CONFIG_I2C) += i2c/
obj-$(CONFIG_PHONE) += telephony/ obj-$(CONFIG_PHONE) += telephony/
......
...@@ -159,8 +159,12 @@ static void iforce_serio_disconnect(struct serio *serio) ...@@ -159,8 +159,12 @@ static void iforce_serio_disconnect(struct serio *serio)
} }
struct serio_driver iforce_serio_drv = { struct serio_driver iforce_serio_drv = {
.write_wakeup = iforce_serio_write_wakeup, .driver = {
.interrupt = iforce_serio_irq, .name = "iforce",
.connect = iforce_serio_connect, },
.disconnect = iforce_serio_disconnect, .description = "RS232 I-Force joysticks and wheels driver",
.write_wakeup = iforce_serio_write_wakeup,
.interrupt = iforce_serio_irq,
.connect = iforce_serio_connect,
.disconnect = iforce_serio_disconnect,
}; };
...@@ -35,8 +35,10 @@ ...@@ -35,8 +35,10 @@
#include <linux/serio.h> #include <linux/serio.h>
#include <linux/init.h> #include <linux/init.h>
#define DRIVER_DESC "Magellan and SpaceMouse 6dof controller driver"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Magellan and SpaceMouse 6dof controller driver"); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* /*
...@@ -200,9 +202,13 @@ static void magellan_connect(struct serio *serio, struct serio_driver *drv) ...@@ -200,9 +202,13 @@ static void magellan_connect(struct serio *serio, struct serio_driver *drv)
*/ */
static struct serio_driver magellan_drv = { static struct serio_driver magellan_drv = {
.interrupt = magellan_interrupt, .driver = {
.connect = magellan_connect, .name = "magellan",
.disconnect = magellan_disconnect, },
.description = DRIVER_DESC,
.interrupt = magellan_interrupt,
.connect = magellan_connect,
.disconnect = magellan_disconnect,
}; };
/* /*
......
...@@ -39,8 +39,10 @@ ...@@ -39,8 +39,10 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/serio.h> #include <linux/serio.h>
#define DRIVER_DESC "SpaceTec SpaceBall 2003/3003/4000 FLX driver"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("SpaceTec SpaceBall 2003/3003/4000 FLX driver"); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* /*
...@@ -270,9 +272,13 @@ static void spaceball_connect(struct serio *serio, struct serio_driver *drv) ...@@ -270,9 +272,13 @@ static void spaceball_connect(struct serio *serio, struct serio_driver *drv)
*/ */
static struct serio_driver spaceball_drv = { static struct serio_driver spaceball_drv = {
.interrupt = spaceball_interrupt, .driver = {
.connect = spaceball_connect, .name = "spaceball",
.disconnect = spaceball_disconnect, },
.description = DRIVER_DESC,
.interrupt = spaceball_interrupt,
.connect = spaceball_connect,
.disconnect = spaceball_disconnect,
}; };
/* /*
......
...@@ -38,8 +38,10 @@ ...@@ -38,8 +38,10 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/serio.h> #include <linux/serio.h>
#define DRIVER_DESC "SpaceTec SpaceOrb 360 and Avenger 6dof controller driver"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("SpaceTec SpaceOrb 360 and Avenger 6dof controller driver"); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* /*
...@@ -214,9 +216,13 @@ static void spaceorb_connect(struct serio *serio, struct serio_driver *drv) ...@@ -214,9 +216,13 @@ static void spaceorb_connect(struct serio *serio, struct serio_driver *drv)
*/ */
static struct serio_driver spaceorb_drv = { static struct serio_driver spaceorb_drv = {
.interrupt = spaceorb_interrupt, .driver = {
.connect = spaceorb_connect, .name = "spaceorb",
.disconnect = spaceorb_disconnect, },
.description = DRIVER_DESC,
.interrupt = spaceorb_interrupt,
.connect = spaceorb_connect,
.disconnect = spaceorb_disconnect,
}; };
/* /*
......
...@@ -36,8 +36,10 @@ ...@@ -36,8 +36,10 @@
#include <linux/serio.h> #include <linux/serio.h>
#include <linux/init.h> #include <linux/init.h>
#define DRIVER_DESC "Gravis Stinger gamepad driver"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Gravis Stinger gamepad driver"); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* /*
...@@ -188,9 +190,13 @@ static void stinger_connect(struct serio *serio, struct serio_driver *drv) ...@@ -188,9 +190,13 @@ static void stinger_connect(struct serio *serio, struct serio_driver *drv)
*/ */
static struct serio_driver stinger_drv = { static struct serio_driver stinger_drv = {
.interrupt = stinger_interrupt, .driver = {
.connect = stinger_connect, .name = "stinger",
.disconnect = stinger_disconnect, },
.description = DRIVER_DESC,
.interrupt = stinger_interrupt,
.connect = stinger_connect,
.disconnect = stinger_disconnect,
}; };
/* /*
......
...@@ -247,9 +247,13 @@ static void twidjoy_connect(struct serio *serio, struct serio_driver *drv) ...@@ -247,9 +247,13 @@ static void twidjoy_connect(struct serio *serio, struct serio_driver *drv)
*/ */
static struct serio_driver twidjoy_drv = { static struct serio_driver twidjoy_drv = {
.interrupt = twidjoy_interrupt, .driver = {
.connect = twidjoy_connect, .name = "twidjoy",
.disconnect = twidjoy_disconnect, },
.description = DRIVER_DESC,
.interrupt = twidjoy_interrupt,
.connect = twidjoy_connect,
.disconnect = twidjoy_disconnect,
}; };
/* /*
......
...@@ -35,8 +35,10 @@ ...@@ -35,8 +35,10 @@
#include <linux/serio.h> #include <linux/serio.h>
#include <linux/init.h> #include <linux/init.h>
#define DRIVER_DESC "Logitech WingMan Warrior joystick driver"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Logitech WingMan Warrior joystick driver"); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* /*
...@@ -200,9 +202,13 @@ static void warrior_connect(struct serio *serio, struct serio_driver *drv) ...@@ -200,9 +202,13 @@ static void warrior_connect(struct serio *serio, struct serio_driver *drv)
*/ */
static struct serio_driver warrior_drv = { static struct serio_driver warrior_drv = {
.interrupt = warrior_interrupt, .driver = {
.connect = warrior_connect, .name = "warrior",
.disconnect = warrior_disconnect, },
.description = DRIVER_DESC,
.interrupt = warrior_interrupt,
.connect = warrior_connect,
.disconnect = warrior_disconnect,
}; };
/* /*
......
...@@ -27,8 +27,10 @@ ...@@ -27,8 +27,10 @@
#include <linux/serio.h> #include <linux/serio.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#define DRIVER_DESC "AT and PS/2 keyboard driver"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("AT and PS/2 keyboard driver"); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static int atkbd_set = 2; static int atkbd_set = 2;
...@@ -891,11 +893,15 @@ static int atkbd_reconnect(struct serio *serio) ...@@ -891,11 +893,15 @@ static int atkbd_reconnect(struct serio *serio)
} }
static struct serio_driver atkbd_drv = { static struct serio_driver atkbd_drv = {
.interrupt = atkbd_interrupt, .driver = {
.connect = atkbd_connect, .name = "atkbd",
.reconnect = atkbd_reconnect, },
.disconnect = atkbd_disconnect, .description = DRIVER_DESC,
.cleanup = atkbd_cleanup, .interrupt = atkbd_interrupt,
.connect = atkbd_connect,
.reconnect = atkbd_reconnect,
.disconnect = atkbd_disconnect,
.cleanup = atkbd_cleanup,
}; };
int __init atkbd_init(void) int __init atkbd_init(void)
......
...@@ -76,8 +76,10 @@ ...@@ -76,8 +76,10 @@
#include <linux/serio.h> #include <linux/serio.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#define DRIVER_DESC "LK keyboard driver"
MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>"); MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
MODULE_DESCRIPTION ("LK keyboard driver"); MODULE_DESCRIPTION (DRIVER_DESC);
MODULE_LICENSE ("GPL"); MODULE_LICENSE ("GPL");
/* /*
...@@ -704,9 +706,13 @@ lkkbd_disconnect (struct serio *serio) ...@@ -704,9 +706,13 @@ lkkbd_disconnect (struct serio *serio)
} }
static struct serio_driver lkkbd_drv = { static struct serio_driver lkkbd_drv = {
.connect = lkkbd_connect, .driver = {
.disconnect = lkkbd_disconnect, .name = "lkkbd",
.interrupt = lkkbd_interrupt, },
.description = DRIVER_DESC,
.connect = lkkbd_connect,
.disconnect = lkkbd_disconnect,
.interrupt = lkkbd_interrupt,
}; };
/* /*
......
...@@ -32,8 +32,10 @@ ...@@ -32,8 +32,10 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/serio.h> #include <linux/serio.h>
#define DRIVER_DESC "Newton keyboard driver"
MODULE_AUTHOR("Justin Cormack <j.cormack@doc.ic.ac.uk>"); MODULE_AUTHOR("Justin Cormack <j.cormack@doc.ic.ac.uk>");
MODULE_DESCRIPTION("Newton keyboard driver"); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#define NKBD_KEY 0x7f #define NKBD_KEY 0x7f
...@@ -139,9 +141,13 @@ void nkbd_disconnect(struct serio *serio) ...@@ -139,9 +141,13 @@ void nkbd_disconnect(struct serio *serio)
} }
struct serio_driver nkbd_drv = { struct serio_driver nkbd_drv = {
.interrupt = nkbd_interrupt, .driver = {
.connect = nkbd_connect, .name = "newtonkbd",
.disconnect = nkbd_disconnect },
.description = DRIVER_DESC,
.interrupt = nkbd_interrupt,
.connect = nkbd_connect,
.disconnect = nkbd_disconnect,
}; };
int __init nkbd_init(void) int __init nkbd_init(void)
......
...@@ -37,8 +37,10 @@ ...@@ -37,8 +37,10 @@
#include <linux/serio.h> #include <linux/serio.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#define DRIVER_DESC "Sun keyboard driver"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Sun keyboard driver"); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static unsigned char sunkbd_keycode[128] = { static unsigned char sunkbd_keycode[128] = {
...@@ -302,9 +304,13 @@ static void sunkbd_disconnect(struct serio *serio) ...@@ -302,9 +304,13 @@ static void sunkbd_disconnect(struct serio *serio)
} }
static struct serio_driver sunkbd_drv = { static struct serio_driver sunkbd_drv = {
.interrupt = sunkbd_interrupt, .driver = {
.connect = sunkbd_connect, .name = "sunkbd",
.disconnect = sunkbd_disconnect },
.description = DRIVER_DESC,
.interrupt = sunkbd_interrupt,
.connect = sunkbd_connect,
.disconnect = sunkbd_disconnect,
}; };
/* /*
......
...@@ -34,8 +34,10 @@ ...@@ -34,8 +34,10 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/serio.h> #include <linux/serio.h>
#define DRIVER_DESC "XT keyboard driver"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("XT keyboard driver"); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#define XTKBD_EMUL0 0xe0 #define XTKBD_EMUL0 0xe0
...@@ -144,9 +146,13 @@ void xtkbd_disconnect(struct serio *serio) ...@@ -144,9 +146,13 @@ void xtkbd_disconnect(struct serio *serio)
} }
struct serio_driver xtkbd_drv = { struct serio_driver xtkbd_drv = {
.interrupt = xtkbd_interrupt, .driver = {
.connect = xtkbd_connect, .name = "xtkbd",
.disconnect = xtkbd_disconnect },
.description = DRIVER_DESC,
.interrupt = xtkbd_interrupt,
.connect = xtkbd_connect,
.disconnect = xtkbd_disconnect,
}; };
int __init xtkbd_init(void) int __init xtkbd_init(void)
......
...@@ -22,8 +22,10 @@ ...@@ -22,8 +22,10 @@
#include "synaptics.h" #include "synaptics.h"
#include "logips2pp.h" #include "logips2pp.h"
#define DRIVER_DESC "PS/2 mouse driver"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("PS/2 mouse driver"); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static char *psmouse_proto; static char *psmouse_proto;
...@@ -815,11 +817,15 @@ static int psmouse_reconnect(struct serio *serio) ...@@ -815,11 +817,15 @@ static int psmouse_reconnect(struct serio *serio)
static struct serio_driver psmouse_drv = { static struct serio_driver psmouse_drv = {
.interrupt = psmouse_interrupt, .driver = {
.connect = psmouse_connect, .name = "psmouse",
.reconnect = psmouse_reconnect, },
.disconnect = psmouse_disconnect, .description = DRIVER_DESC,
.cleanup = psmouse_cleanup, .interrupt = psmouse_interrupt,
.connect = psmouse_connect,
.reconnect = psmouse_reconnect,
.disconnect = psmouse_disconnect,
.cleanup = psmouse_cleanup,
}; };
static inline void psmouse_parse_proto(void) static inline void psmouse_parse_proto(void)
......
...@@ -37,8 +37,10 @@ ...@@ -37,8 +37,10 @@
#include <linux/serio.h> #include <linux/serio.h>
#include <linux/init.h> #include <linux/init.h>
#define DRIVER_DESC "Serial mouse driver"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Serial mouse driver"); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static char *sermouse_protocols[] = { "None", "Mouse Systems Mouse", "Sun Mouse", "Microsoft Mouse", static char *sermouse_protocols[] = { "None", "Mouse Systems Mouse", "Sun Mouse", "Microsoft Mouse",
...@@ -290,9 +292,13 @@ static void sermouse_connect(struct serio *serio, struct serio_driver *drv) ...@@ -290,9 +292,13 @@ static void sermouse_connect(struct serio *serio, struct serio_driver *drv)
} }
static struct serio_driver sermouse_drv = { static struct serio_driver sermouse_drv = {
.interrupt = sermouse_interrupt, .driver = {
.connect = sermouse_connect, .name = "sermouse",
.disconnect = sermouse_disconnect },
.description = DRIVER_DESC,
.interrupt = sermouse_interrupt,
.connect = sermouse_connect,
.disconnect = sermouse_disconnect,
}; };
int __init sermouse_init(void) int __init sermouse_init(void)
......
...@@ -82,8 +82,10 @@ ...@@ -82,8 +82,10 @@
#include <linux/serio.h> #include <linux/serio.h>
#include <linux/init.h> #include <linux/init.h>
#define DRIVER_DESC "Serial DEC VSXXX-AA/GA mouse / DEC tablet driver"
MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>"); MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
MODULE_DESCRIPTION ("Serial DEC VSXXX-AA/GA mouse / DEC tablet driver"); MODULE_DESCRIPTION (DRIVER_DESC);
MODULE_LICENSE ("GPL"); MODULE_LICENSE ("GPL");
#undef VSXXXAA_DEBUG #undef VSXXXAA_DEBUG
...@@ -541,9 +543,13 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv) ...@@ -541,9 +543,13 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
} }
static struct serio_driver vsxxxaa_drv = { static struct serio_driver vsxxxaa_drv = {
.connect = vsxxxaa_connect, .driver = {
.interrupt = vsxxxaa_interrupt, .name = "vsxxxaa",
.disconnect = vsxxxaa_disconnect, },
.description = DRIVER_DESC,
.connect = vsxxxaa_connect,
.interrupt = vsxxxaa_interrupt,
.disconnect = vsxxxaa_disconnect,
}; };
int __init int __init
......
...@@ -56,6 +56,11 @@ EXPORT_SYMBOL(serio_reconnect); ...@@ -56,6 +56,11 @@ EXPORT_SYMBOL(serio_reconnect);
static DECLARE_MUTEX(serio_sem); /* protects serio_list and serio_diriver_list */ static DECLARE_MUTEX(serio_sem); /* protects serio_list and serio_diriver_list */
static LIST_HEAD(serio_list); static LIST_HEAD(serio_list);
static LIST_HEAD(serio_driver_list); static LIST_HEAD(serio_driver_list);
static unsigned int serio_no;
struct bus_type serio_bus = {
.name = "serio",
};
static void serio_find_driver(struct serio *serio); static void serio_find_driver(struct serio *serio);
static void serio_create_port(struct serio *serio); static void serio_create_port(struct serio *serio);
...@@ -66,9 +71,19 @@ static void serio_disconnect_port(struct serio *serio); ...@@ -66,9 +71,19 @@ static void serio_disconnect_port(struct serio *serio);
static int serio_bind_driver(struct serio *serio, struct serio_driver *drv) static int serio_bind_driver(struct serio *serio, struct serio_driver *drv)
{ {
get_driver(&drv->driver);
drv->connect(serio, drv); 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;
}
return serio->drv != NULL; put_driver(&drv->driver);
return 0;
} }
/* serio_find_driver() must be called with serio_sem down. */ /* serio_find_driver() must be called with serio_sem down. */
...@@ -224,10 +239,41 @@ static int serio_thread(void *nothing) ...@@ -224,10 +239,41 @@ static int serio_thread(void *nothing)
* Serio port operations * Serio port operations
*/ */
static ssize_t serio_show_description(struct device *dev, char *buf)
{
struct serio *serio = to_serio_port(dev);
return sprintf(buf, "%s\n", serio->name);
}
static DEVICE_ATTR(description, S_IRUGO, serio_show_description, NULL);
static ssize_t serio_show_driver(struct device *dev, char *buf)
{
return sprintf(buf, "%s\n", dev->driver ? dev->driver->name : "(none)");
}
static DEVICE_ATTR(driver, S_IRUGO, serio_show_driver, NULL);
static void serio_release_port(struct device *dev)
{
struct serio *serio = to_serio_port(dev);
kfree(serio);
module_put(THIS_MODULE);
}
static void serio_create_port(struct serio *serio) static void serio_create_port(struct serio *serio)
{ {
try_module_get(THIS_MODULE);
spin_lock_init(&serio->lock); spin_lock_init(&serio->lock);
list_add_tail(&serio->node, &serio_list); list_add_tail(&serio->node, &serio_list);
snprintf(serio->dev.bus_id, sizeof(serio->dev.bus_id), "serio%d", serio_no++);
serio->dev.bus = &serio_bus;
serio->dev.release = serio_release_port;
if (serio->parent)
serio->dev.parent = &serio->parent->dev;
device_register(&serio->dev);
device_create_file(&serio->dev, &dev_attr_description);
device_create_file(&serio->dev, &dev_attr_driver);
} }
/* /*
...@@ -242,8 +288,13 @@ static void serio_destroy_port(struct serio *serio) ...@@ -242,8 +288,13 @@ static void serio_destroy_port(struct serio *serio)
serio_remove_pending_events(serio); serio_remove_pending_events(serio);
list_del_init(&serio->node); list_del_init(&serio->node);
if (drv) if (drv) {
drv->disconnect(serio); drv->disconnect(serio);
down_write(&serio_bus.subsys.rwsem);
device_release_driver(&serio->dev);
up_write(&serio_bus.subsys.rwsem);
put_driver(&drv->driver);
}
if (serio->parent) { if (serio->parent) {
spin_lock_irqsave(&serio->parent->lock, flags); spin_lock_irqsave(&serio->parent->lock, flags);
...@@ -251,7 +302,7 @@ static void serio_destroy_port(struct serio *serio) ...@@ -251,7 +302,7 @@ static void serio_destroy_port(struct serio *serio)
spin_unlock_irqrestore(&serio->parent->lock, flags); spin_unlock_irqrestore(&serio->parent->lock, flags);
} }
kfree(serio); device_unregister(&serio->dev);
} }
/* /*
...@@ -332,8 +383,13 @@ static void serio_disconnect_port(struct serio *serio) ...@@ -332,8 +383,13 @@ static void serio_disconnect_port(struct serio *serio)
/* /*
* Ok, no children left, now disconnect this port * Ok, no children left, now disconnect this port
*/ */
if (drv) if (drv) {
drv->disconnect(serio); drv->disconnect(serio);
down_write(&serio_bus.subsys.rwsem);
device_release_driver(&serio->dev);
up_write(&serio_bus.subsys.rwsem);
put_driver(&drv->driver);
}
} }
void serio_rescan(struct serio *serio) void serio_rescan(struct serio *serio)
...@@ -387,6 +443,12 @@ void serio_unregister_port_delayed(struct serio *serio) ...@@ -387,6 +443,12 @@ void serio_unregister_port_delayed(struct serio *serio)
* Serio driver operations * Serio driver operations
*/ */
static ssize_t serio_driver_show_description(struct device_driver *drv, char *buf)
{
struct serio_driver *driver = to_serio_driver(drv);
return sprintf(buf, "%s\n", driver->description ? driver->description : "(none)");
}
static DRIVER_ATTR(description, S_IRUGO, serio_driver_show_description, NULL);
void serio_register_driver(struct serio_driver *drv) void serio_register_driver(struct serio_driver *drv)
{ {
...@@ -396,6 +458,10 @@ void serio_register_driver(struct serio_driver *drv) ...@@ -396,6 +458,10 @@ void serio_register_driver(struct serio_driver *drv)
list_add_tail(&drv->node, &serio_driver_list); list_add_tail(&drv->node, &serio_driver_list);
drv->driver.bus = &serio_bus;
driver_register(&drv->driver);
driver_create_file(&drv->driver, &driver_attr_description);
start_over: start_over:
list_for_each_entry(serio, &serio_list, node) { list_for_each_entry(serio, &serio_list, node) {
if (!serio->drv) { if (!serio->drv) {
...@@ -430,6 +496,8 @@ void serio_unregister_driver(struct serio_driver *drv) ...@@ -430,6 +496,8 @@ void serio_unregister_driver(struct serio_driver *drv)
} }
} }
driver_unregister(&drv->driver);
up(&serio_sem); up(&serio_sem);
} }
...@@ -489,22 +557,19 @@ irqreturn_t serio_interrupt(struct serio *serio, ...@@ -489,22 +557,19 @@ irqreturn_t serio_interrupt(struct serio *serio,
static int __init serio_init(void) static int __init serio_init(void)
{ {
int pid; if (!(serio_pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL))) {
pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL);
if (!pid) {
printk(KERN_WARNING "serio: Failed to start kseriod\n"); printk(KERN_WARNING "serio: Failed to start kseriod\n");
return -1; return -1;
} }
serio_pid = pid; bus_register(&serio_bus);
return 0; return 0;
} }
static void __exit serio_exit(void) static void __exit serio_exit(void)
{ {
bus_unregister(&serio_bus);
kill_proc(serio_pid, SIGTERM, 1); kill_proc(serio_pid, SIGTERM, 1);
wait_for_completion(&serio_exited); wait_for_completion(&serio_exited);
} }
......
...@@ -36,8 +36,10 @@ ...@@ -36,8 +36,10 @@
#include <linux/serio.h> #include <linux/serio.h>
#include <linux/init.h> #include <linux/init.h>
#define DRIVER_DESC "Gunze AHL-51S touchscreen driver"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Gunze AHL-51S touchscreen driver"); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* /*
...@@ -157,9 +159,13 @@ static void gunze_connect(struct serio *serio, struct serio_driver *drv) ...@@ -157,9 +159,13 @@ static void gunze_connect(struct serio *serio, struct serio_driver *drv)
*/ */
static struct serio_driver gunze_drv = { static struct serio_driver gunze_drv = {
.interrupt = gunze_interrupt, .driver = {
.connect = gunze_connect, .name = "gunze",
.disconnect = gunze_disconnect, },
.description = DRIVER_DESC,
.interrupt = gunze_interrupt,
.connect = gunze_connect,
.disconnect = gunze_disconnect,
}; };
/* /*
......
...@@ -45,8 +45,10 @@ ...@@ -45,8 +45,10 @@
#include <asm/arch/hardware.h> #include <asm/arch/hardware.h>
#include <asm/arch/irqs.h> #include <asm/arch/irqs.h>
#define DRIVER_DESC "H3600 touchscreen driver"
MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>"); MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>");
MODULE_DESCRIPTION("H3600 touchscreen driver"); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* /*
...@@ -479,9 +481,13 @@ static void h3600ts_disconnect(struct serio *serio) ...@@ -479,9 +481,13 @@ static void h3600ts_disconnect(struct serio *serio)
*/ */
static struct serio_driver h3600ts_drv = { static struct serio_driver h3600ts_drv = {
.interrupt = h3600ts_interrupt, .driver = {
.connect = h3600ts_connect, .name = "h3600ts",
.disconnect = h3600ts_disconnect, },
.description = DRIVER_DESC,
.interrupt = h3600ts_interrupt,
.connect = h3600ts_connect,
.disconnect = h3600ts_disconnect,
}; };
/* /*
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/device.h>
struct serio { struct serio {
void *private; void *private;
...@@ -44,12 +45,15 @@ struct serio { ...@@ -44,12 +45,15 @@ struct serio {
struct serio_driver *drv; /* Accessed from interrupt, writes must be protected by serio_lock */ struct serio_driver *drv; /* Accessed from interrupt, writes must be protected by serio_lock */
struct device dev;
struct list_head node; struct list_head node;
}; };
#define to_serio_port(d) container_of(d, struct serio, dev)
struct serio_driver { struct serio_driver {
void *private; void *private;
char *name; char *description;
void (*write_wakeup)(struct serio *); void (*write_wakeup)(struct serio *);
irqreturn_t (*interrupt)(struct serio *, unsigned char, irqreturn_t (*interrupt)(struct serio *, unsigned char,
...@@ -59,8 +63,11 @@ struct serio_driver { ...@@ -59,8 +63,11 @@ struct serio_driver {
void (*disconnect)(struct serio *); void (*disconnect)(struct serio *);
void (*cleanup)(struct serio *); void (*cleanup)(struct serio *);
struct device_driver driver;
struct list_head node; struct list_head node;
}; };
#define to_serio_driver(d) container_of(d, struct serio_driver, driver)
int serio_open(struct serio *serio, struct serio_driver *drv); int serio_open(struct serio *serio, struct serio_driver *drv);
void serio_close(struct serio *serio); void serio_close(struct serio *serio);
......
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