linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Writing a driver for a legacy serial device
@ 2007-06-19 17:05 Jean Delvare
  2007-06-19 18:59 ` Dmitry Torokhov
  0 siblings, 1 reply; 10+ messages in thread
From: Jean Delvare @ 2007-06-19 17:05 UTC (permalink / raw)
  To: LKML; +Cc: Vojtech Pavlik

Hi all,

I want to write a Linux kernel driver for a device which connects to
the legacy serial port. I started writing a driver, however I am
already stuck at the very beginning. The .connect function of my serial
driver is never called, and I just don't get why. I couldn't find any
documentation about writing such a legacy driver in Documentation nor
in LDD3. Is there anyone out there which could lend a helping hand?

I know that the device and my serial port both work. I can talk to the
device using minicom just fine. I have the following drivers loaded: 

$ lsmod | grep 8250
8250_pnp               11648  0
8250                   23464  1 8250_pnp
serial_core            19392  1 8250

Serial: 8250/16550 driver $Revision: 1.90 $ 2 ports, IRQ sharing disabled
00:08: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A

But I need to implement my driver in kernel space. My code looks like
this:

static struct serio_device_id taos_serio_ids[] = {
	{
		.type	= SERIO_RS232,
		.proto	= SERIO_ANY,
		.id	= SERIO_ANY,
		.extra	= SERIO_ANY,
	},
	{ 0 }
};
MODULE_DEVICE_TABLE(serio, taos_serio_ids);

static struct serio_driver taos_drv = {
	.driver		= {
		.name	= "taos-evm",
	},
	.description	= "TAOS evaluation module driver",
	.id_table	= taos_serio_ids,
	.connect	= taos_connect,
	.disconnect	= taos_disconnect,
	.interrupt	= taos_interrupt,
};

static int __init taos_init(void)
{
	return serio_register_driver(&taos_drv);
}

static void __exit taos_exit(void)
{
	serio_unregister_driver(&taos_drv);
}

The problem is that taos_connect is never called. I suppose that I need
different values for .type, .proto or .id, except that I just don't
know what to put there. I tried a few random values without success.
What's the trick?

Thanks,
-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Writing a driver for a legacy serial device
  2007-06-19 17:05 Writing a driver for a legacy serial device Jean Delvare
@ 2007-06-19 18:59 ` Dmitry Torokhov
  2007-06-20  8:56   ` Jean Delvare
  0 siblings, 1 reply; 10+ messages in thread
From: Dmitry Torokhov @ 2007-06-19 18:59 UTC (permalink / raw)
  To: Jean Delvare; +Cc: LKML, Vojtech Pavlik

Hi Jean,

On 6/19/07, Jean Delvare <khali@linux-fr.org> wrote:
> Hi all,
>
> I want to write a Linux kernel driver for a device which connects to
> the legacy serial port. I started writing a driver, however I am
> already stuck at the very beginning. The .connect function of my serial
> driver is never called, and I just don't get why. I couldn't find any
> documentation about writing such a legacy driver in Documentation nor
> in LDD3. Is there anyone out there which could lend a helping hand?
>
> I know that the device and my serial port both work. I can talk to the
> device using minicom just fine. I have the following drivers loaded:
>
> $ lsmod | grep 8250
> 8250_pnp               11648  0
> 8250                   23464  1 8250_pnp
> serial_core            19392  1 8250
>
> Serial: 8250/16550 driver $Revision: 1.90 $ 2 ports, IRQ sharing disabled
> 00:08: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
>
> But I need to implement my driver in kernel space. My code looks like
> this:
>
> static struct serio_device_id taos_serio_ids[] = {
>        {
>                .type   = SERIO_RS232,
>                .proto  = SERIO_ANY,
>                .id     = SERIO_ANY,
>                .extra  = SERIO_ANY,
>        },
>        { 0 }
> };
> MODULE_DEVICE_TABLE(serio, taos_serio_ids);
>
> static struct serio_driver taos_drv = {
>        .driver         = {
>                .name   = "taos-evm",
>        },
>        .description    = "TAOS evaluation module driver",
>        .id_table       = taos_serio_ids,
>        .connect        = taos_connect,
>        .disconnect     = taos_disconnect,
>        .interrupt      = taos_interrupt,
> };
>
> static int __init taos_init(void)
> {
>        return serio_register_driver(&taos_drv);
> }
>
> static void __exit taos_exit(void)
> {
>        serio_unregister_driver(&taos_drv);
> }
>
> The problem is that taos_connect is never called. I suppose that I need
> different values for .type, .proto or .id, except that I just don't
> know what to put there. I tried a few random values without success.
> What's the trick?
>

You need to load serport modue and play with inputattach utility.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Writing a driver for a legacy serial device
  2007-06-19 18:59 ` Dmitry Torokhov
@ 2007-06-20  8:56   ` Jean Delvare
  2007-06-21  3:11     ` Dmitry Torokhov
  0 siblings, 1 reply; 10+ messages in thread
From: Jean Delvare @ 2007-06-20  8:56 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: LKML, Vojtech Pavlik

Hi Dmitry,

Thanks for your answer, very much appreciated.

On Tue, 19 Jun 2007 14:59:34 -0400, Dmitry Torokhov wrote:
> Hi Jean,
> 
> On 6/19/07, Jean Delvare <khali@linux-fr.org> wrote:
> > Hi all,
> >
> > I want to write a Linux kernel driver for a device which connects to
> > the legacy serial port. I started writing a driver, however I am
> > already stuck at the very beginning. The .connect function of my serial
> > driver is never called, and I just don't get why. I couldn't find any
> > documentation about writing such a legacy driver in Documentation nor
> > in LDD3. Is there anyone out there which could lend a helping hand?
> >
> > I know that the device and my serial port both work. I can talk to the
> > device using minicom just fine. I have the following drivers loaded:
> >
> > $ lsmod | grep 8250
> > 8250_pnp               11648  0
> > 8250                   23464  1 8250_pnp
> > serial_core            19392  1 8250
> >
> > Serial: 8250/16550 driver $Revision: 1.90 $ 2 ports, IRQ sharing disabled
> > 00:08: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
> >
> > But I need to implement my driver in kernel space. My code looks like
> > this:
> >
> > static struct serio_device_id taos_serio_ids[] = {
> >        {
> >                .type   = SERIO_RS232,
> >                .proto  = SERIO_ANY,
> >                .id     = SERIO_ANY,
> >                .extra  = SERIO_ANY,
> >        },
> >        { 0 }
> > };
> > MODULE_DEVICE_TABLE(serio, taos_serio_ids);
> >
> > static struct serio_driver taos_drv = {
> >        .driver         = {
> >                .name   = "taos-evm",
> >        },
> >        .description    = "TAOS evaluation module driver",
> >        .id_table       = taos_serio_ids,
> >        .connect        = taos_connect,
> >        .disconnect     = taos_disconnect,
> >        .interrupt      = taos_interrupt,
> > };
> >
> > static int __init taos_init(void)
> > {
> >        return serio_register_driver(&taos_drv);
> > }
> >
> > static void __exit taos_exit(void)
> > {
> >        serio_unregister_driver(&taos_drv);
> > }
> >
> > The problem is that taos_connect is never called. I suppose that I need
> > different values for .type, .proto or .id, except that I just don't
> > know what to put there. I tried a few random values without success.
> > What's the trick?
> 
> You need to load serport modue and play with inputattach utility.

Ah, I see. There's no way to detect what device is connected to the
serial port, so we need a user-space tool to bind the port to the right
driver? Makes some sense, even though it's a but strange that I need
something called inputattach for a device which isn't an input device.

So I've set CONFIG_SERIO_SERPORT=m, compiled and loaded serport. Then I
added a new protocol number in <linux/serio.h>:

#define SERIO_TAOSEVM	0x40

Then I added the following entry to inputattach and recompiled it:

{ "--taos-evm",		"-taos",	B1200, CS8,			SERIO_TAOSEVM,	0,	0,	0,	NULL },

Then I changed my driver code to:

static struct serio_device_id taos_serio_ids[] = {
	{
		.type	= SERIO_RS232,
		.proto	= SERIO_TAOSEVM,
		.id	= SERIO_ANY,
		.extra	= SERIO_ANY,
	},
	{ 0 }
};

And lastly I ran, as root:

./inputattach -taos /dev/ttyS0

I see the following line in the logs as a result:

serio: Serial port ttyS0

But unfortunately, my driver's .connect function is still not called.
I guess that I missed one step? Any idea what it would be?

Thanks,
-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Writing a driver for a legacy serial device
  2007-06-20  8:56   ` Jean Delvare
@ 2007-06-21  3:11     ` Dmitry Torokhov
  2007-06-21  9:33       ` Jean Delvare
  0 siblings, 1 reply; 10+ messages in thread
From: Dmitry Torokhov @ 2007-06-21  3:11 UTC (permalink / raw)
  To: Jean Delvare; +Cc: LKML, Vojtech Pavlik

On Wednesday 20 June 2007 04:56, Jean Delvare wrote:
> Hi Dmitry,
> 
> Thanks for your answer, very much appreciated.
> 
> On Tue, 19 Jun 2007 14:59:34 -0400, Dmitry Torokhov wrote:
> > 
> > You need to load serport modue and play with inputattach utility.
> 
> Ah, I see. There's no way to detect what device is connected to the
> serial port, so we need a user-space tool to bind the port to the right
> driver? Makes some sense, even though it's a but strange that I need
> something called inputattach for a device which isn't an input device.

Because serio interface is mostly used with input devices. For all other
devices I think universal answer is "userspace" but with input devices
we want to do processing in kernel so we can route events into console
and other standard interfaces (although one coudl use uinput to achieve
similar result).

> 
> So I've set CONFIG_SERIO_SERPORT=m, compiled and loaded serport. Then I
> added a new protocol number in <linux/serio.h>:
> 
> #define SERIO_TAOSEVM	0x40
> 
> Then I added the following entry to inputattach and recompiled it:
> 
> { "--taos-evm",		"-taos",	B1200, CS8,			SERIO_TAOSEVM,	0,	0,	0,	NULL },
> 
> Then I changed my driver code to:
> 
> static struct serio_device_id taos_serio_ids[] = {
> 	{
> 		.type	= SERIO_RS232,
> 		.proto	= SERIO_TAOSEVM,
> 		.id	= SERIO_ANY,
> 		.extra	= SERIO_ANY,
> 	},
> 	{ 0 }
> };
> 
> And lastly I ran, as root:
> 
> ./inputattach -taos /dev/ttyS0
> 
> I see the following line in the logs as a result:
> 
> serio: Serial port ttyS0
> 
> But unfortunately, my driver's .connect function is still not called.
> I guess that I missed one step? Any idea what it would be?
> 

Not sure. Could you check /sys/bus/serio/devices/serioX/id/* and verify
that inputattach sets up serio port properly?

-- 
Dmitry

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Writing a driver for a legacy serial device
  2007-06-21  3:11     ` Dmitry Torokhov
@ 2007-06-21  9:33       ` Jean Delvare
  2007-06-21 14:47         ` David Woodhouse
  2007-06-22 19:47         ` Dmitry Torokhov
  0 siblings, 2 replies; 10+ messages in thread
From: Jean Delvare @ 2007-06-21  9:33 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: LKML, Vojtech Pavlik

Hi Dmitry,

On Wed, 20 Jun 2007 23:11:32 -0400, Dmitry Torokhov wrote:
> On Wednesday 20 June 2007 04:56, Jean Delvare wrote:
> > Ah, I see. There's no way to detect what device is connected to the
> > serial port, so we need a user-space tool to bind the port to the right
> > driver? Makes some sense, even though it's a but strange that I need
> > something called inputattach for a device which isn't an input device.
> 
> Because serio interface is mostly used with input devices. For all other
> devices I think universal answer is "userspace" but with input devices
> we want to do processing in kernel so we can route events into console
> and other standard interfaces (although one coudl use uinput to achieve
> similar result).

OK. This leads me to a question: is it OK for me to add support for my
non-input device to inputattach, or is a separate, dedicated helper
tool preferred? Both ways are fine with me, I don't know what the input
subsystem maintainers expect.

> > But unfortunately, my driver's .connect function is still not called.
> > I guess that I missed one step? Any idea what it would be?
> 
> Not sure. Could you check /sys/bus/serio/devices/serioX/id/* and verify
> that inputattach sets up serio port properly?

Thanks for the hint, I checked that and the proto value was 42 instead
of the expected 40. Reading the source code of my local copy of
inputattach.c, I found that SERIO_RS232 was OR'd to the value. This
seems to be a rather old bug which is already fixed upstream:

http://linuxconsole.cvs.sourceforge.net/linuxconsole/ruby/utils/inputattach.c?r1=1.23&r2=1.24

But for some reason the openSuse package is lagging behind. I'll go
update it.

After fixing this, I finally see my .connect function being called! Now
I can start doing the real driver development work. Thanks a lot for
your highly valuable help, Dmitry :)

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Writing a driver for a legacy serial device
  2007-06-21  9:33       ` Jean Delvare
@ 2007-06-21 14:47         ` David Woodhouse
  2007-06-21 18:38           ` Jean Delvare
  2007-06-22 19:47         ` Dmitry Torokhov
  1 sibling, 1 reply; 10+ messages in thread
From: David Woodhouse @ 2007-06-21 14:47 UTC (permalink / raw)
  To: Jean Delvare; +Cc: Dmitry Torokhov, LKML, Vojtech Pavlik

On Thu, 2007-06-21 at 11:33 +0200, Jean Delvare wrote:
> OK. This leads me to a question: is it OK for me to add support for my
> non-input device to inputattach, or is a separate, dedicated helper
> tool preferred? Both ways are fine with me, I don't know what the
> input subsystem maintainers expect.

You might do better to implement it as a line discipline instead. 
Or just do it in userspace. What exactly are you trying to do?

-- 
dwmw2


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Writing a driver for a legacy serial device
  2007-06-21 14:47         ` David Woodhouse
@ 2007-06-21 18:38           ` Jean Delvare
  2007-06-21 23:31             ` Arnd Bergmann
  0 siblings, 1 reply; 10+ messages in thread
From: Jean Delvare @ 2007-06-21 18:38 UTC (permalink / raw)
  To: David Woodhouse; +Cc: Dmitry Torokhov, LKML, Vojtech Pavlik

Hi David,

On Thu, 21 Jun 2007 22:47:12 +0800, David Woodhouse wrote:
> On Thu, 2007-06-21 at 11:33 +0200, Jean Delvare wrote:
> > OK. This leads me to a question: is it OK for me to add support for my
> > non-input device to inputattach, or is a separate, dedicated helper
> > tool preferred? Both ways are fine with me, I don't know what the
> > input subsystem maintainers expect.
> 
> You might do better to implement it as a line discipline instead. 
> Or just do it in userspace. What exactly are you trying to do?

I am writing a driver for a TAOS evaluation module. This device is a
limited SMBus master, connecting to the serial port. The evaluation
chip is connected to the SMBus. In my case this is a TSL2550 light
sensor, but virtually all compatible TAOS evaluation modules could be
supported.

I2C bus drivers have to be implemented in the kernel, so user-space
isn't an option for me.

I just posted a first (working) version of my driver, if you want to
take a look:
http://lists.lm-sensors.org/pipermail/i2c/2007-June/001508.html

Thanks,
-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Writing a driver for a legacy serial device
  2007-06-21 18:38           ` Jean Delvare
@ 2007-06-21 23:31             ` Arnd Bergmann
  0 siblings, 0 replies; 10+ messages in thread
From: Arnd Bergmann @ 2007-06-21 23:31 UTC (permalink / raw)
  To: Jean Delvare; +Cc: David Woodhouse, Dmitry Torokhov, LKML, Vojtech Pavlik

On Thursday 21 June 2007, Jean Delvare wrote:
> I2C bus drivers have to be implemented in the kernel, so user-space
> isn't an option for me.

Well, you could have an i2c_algorithm that exports a character device
node to user space, and then have a trivial user application that
simply relays between that and the serial port.

It's probably not much different to what you have in the end though.

	Arnd <><

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Writing a driver for a legacy serial device
  2007-06-21  9:33       ` Jean Delvare
  2007-06-21 14:47         ` David Woodhouse
@ 2007-06-22 19:47         ` Dmitry Torokhov
  2007-06-23  8:34           ` Jean Delvare
  1 sibling, 1 reply; 10+ messages in thread
From: Dmitry Torokhov @ 2007-06-22 19:47 UTC (permalink / raw)
  To: Jean Delvare; +Cc: LKML, Vojtech Pavlik

On 6/21/07, Jean Delvare <khali@linux-fr.org> wrote:
>
> OK. This leads me to a question: is it OK for me to add support for my
> non-input device to inputattach, or is a separate, dedicated helper
> tool preferred? Both ways are fine with me, I don't know what the input
> subsystem maintainers expect.
>

Your device does not need any initialization done by userspace, does
it? How widespread is this device? inputattach has "--dump" option
which sets up a SERIO_RS232/0/0/0 serio port. You could mark your
serio driver as manual bind driver and bind it trhough sysfs (echo -n
"taos-evm" /sys/device/serio/devices/serioX/drvctl to bind it).

-- 
Dmitry

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Writing a driver for a legacy serial device
  2007-06-22 19:47         ` Dmitry Torokhov
@ 2007-06-23  8:34           ` Jean Delvare
  0 siblings, 0 replies; 10+ messages in thread
From: Jean Delvare @ 2007-06-23  8:34 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: LKML, Vojtech Pavlik

Hi Dmitry,

On Fri, 22 Jun 2007 15:47:43 -0400, Dmitry Torokhov wrote:
> On 6/21/07, Jean Delvare <khali@linux-fr.org> wrote:
> >
> > OK. This leads me to a question: is it OK for me to add support for my
> > non-input device to inputattach, or is a separate, dedicated helper
> > tool preferred? Both ways are fine with me, I don't know what the input
> > subsystem maintainers expect.
> 
> Your device does not need any initialization done by userspace, does
> it?

No, it doesn't. But it wants a specific serial line speed and mode.

> How widespread is this device?

Not widespread. It's a family of evaluation modules for I2C/SMBus
chips. They will mainly be used to develop and test chip drivers, I
suppose. But OTOH, I'm not sure how it matters. We're in year 2007, I
pretty much doubt that any of the devices supported by inputattach is
still in widespread use. As a matter of fact, inputattach has been
broken in Suse for half of the supported devices for almost two years
now, and I couldn't find any bug report about it.

> inputattach has "--dump" option
> which sets up a SERIO_RS232/0/0/0 serio port. You could mark your
> serio driver as manual bind driver and bind it trhough sysfs (echo -n
> "taos-evm" /sys/device/serio/devices/serioX/drvctl to bind it).

One problem I foresee is that the dump mode sets the port to 2400 bps,
while my evaluation module wants 1200 bps.

Another problem is that the dump mode of inputattach doesn't appear to
create a serio device. Probably not very surprising, as dump_init()
never returns. So I don't think I can use that.

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2007-06-23  8:33 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-06-19 17:05 Writing a driver for a legacy serial device Jean Delvare
2007-06-19 18:59 ` Dmitry Torokhov
2007-06-20  8:56   ` Jean Delvare
2007-06-21  3:11     ` Dmitry Torokhov
2007-06-21  9:33       ` Jean Delvare
2007-06-21 14:47         ` David Woodhouse
2007-06-21 18:38           ` Jean Delvare
2007-06-21 23:31             ` Arnd Bergmann
2007-06-22 19:47         ` Dmitry Torokhov
2007-06-23  8:34           ` Jean Delvare

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).