Skip navigation.
Home
The QNX Community Portal

View topic - Questions about writing a serial device using io-char

Questions about writing a serial device using io-char

Read-only archive of qnx.ddk (Writing device drivers for scanners, video card, optical mouse, etc) at inn.qnx.com

Questions about writing a serial device using io-char

Postby ED209 » Fri Sep 15, 2006 3:15 pm

Hello!
I'm currently trying to write a serial device driver using the io-char library. So far I'm able to read and write data but there are still some things unclear to me. Maybe someone that has already done this can help me...


1) tte()-function:
Can this function directly be used by the driver or is it just a io-char internal event handler (the documentation is a bit unclear at this but i assume the latter)?


2) Sending events:
This question is related to question 1) and assumes that tte() is a io-char internal handler. So how does the driver sends events to io-char?
I can see that the structure TTYCTRL has an "event"-member and also TTYDEV's "flags"-member is used for events (at least in the 8250 example). But just setting the flags in TTYDEV will, of course, not do anything. As I see it only makes sense doing this inside the tto()-function, as the function that is calling it ( kick() in io_write.c ) will queue the event in "ttyctrl" and send a message. How can it be done on other places?

Btw: Whats the difference, regarding EVENT_*, between the TTYCTRL "event" and the TTYDEV "flags" member ?


3) Event queue:
TTYCTRL also contains an event queue ("num_events"+"event_queue"). It is written in the documentation that this is used by io-char AND the driver to queue events. How is this related to sending events as desribed in 2) ? It seems conflicting to me.
I see that it is used in the interrupt-handler of the 8250-example.


4) Blocking read:
When read() is called on the character-device then it blocks when there is no data in the "ibuf" of the device. How can the driver indicate when data has been written to the "ibuf", so io-char will process it and deliver it to the caller ?


5) Drain:
What is the meaning of EVENT_DRAIN and the "waiting_drain"-queue in TTYDEF ? What is the driver supposed to do with that information ?


6) Instances:
This is a more general question regarding resource managers. How do I distinguish between different instances of the serial device (two processes call open() on the same device). I assume it will create two instances in this case, will it ?!


Quick help on these issues would be appreciated :)
ED209
New Member
 
Posts: 3
Joined: Fri Sep 15, 2006 3:00 pm

Re: Questions about writing a serial device using io-char

Postby David Gibbs » Tue Oct 03, 2006 9:26 pm

ED209 <ans666@gmx-dot-de.no-spam.invalid> wrote:
Hello!
I'm currently trying to write a serial device driver using the io-char
library. So far I'm able to read and write data but there are still
some things unclear to me. Maybe someone that has already done this
can help me...


1) tte()-function:
Can this function directly be used by the driver or is it just a
io-char internal event handler (the documentation is a bit unclear at
this but i assume the latter)?

I don't think you ever use this function.

2) Sending events:
This question is related to question 1) and assumes that tte() is a
io-char internal handler. So how does the driver sends events to
io-char?
I can see that the structure TTYCTRL has an "event"-member
and also TTYDEV's "flags"-member is used for events (at
least in the 8250 example). But just setting the flags in TTYDEV
will, of course, not do anything. As I see it only makes sense doing
this inside the tto()-function, as the function that is calling it (
kick() in io_write.c ) will queue the event in "ttyctrl"
and send a message. How can it be done on other places?

Either you return an event from the interrupt handler -- this is what
devc-ser8250 does, or you call iochar_send_event( &ttydev ).

3) Event queue:
TTYCTRL also contains an event queue
("num_events"+"event_queue"). It is written in
the documentation that this is used by io-char AND the driver to
queue events. How is this related to sending events as desribed in 2)
? It seems conflicting to me.
I see that it is used in the interrupt-handler of the 8250-example.

See above -- either steal the devc-ser8250 interrupt code, or call
iochar_send_event() which properly manipulates the event queue for you.

4) Blocking read:
When read() is called on the character-device then it blocks when
there is no data in the "ibuf" of the device. How can the
driver indicate when data has been written to the "ibuf",
so io-char will process it and deliver it to the caller ?

By setting a "data available" flag then queueing an event to wake
up the io-char processing.

5) Drain:
What is the meaning of EVENT_DRAIN and the
"waiting_drain"-queue in TTYDEF ? What is the driver
supposed to do with that information ?

EVENT_DRAIN should, I think, be set when all the data in the
outgoing buffer has drained.

6) Instances:
This is a more general question regarding resource managers. How do I
distinguish between different instances of the serial device (two
processes call open() on the same device). I assume it will create
two instances in this case, will it ?!

I'm not sure what you mean by instances.

From a general resmgr point of view, there is a client-tracking structure
called an OCB (open control block) which is allocated on each successful
open(), and used to track the client's requests, state, etc. It is cleaned
up at final close. The ocb points to the device structure, which corresponds
to the registered name (/dev/ser1, /dev/ser2).

So..

fd = open("/dev/ser1") -> ocb -> dev_attr <--> /dev/ser1.

The device attr is a "TTYDEV" in the devc-ser8250, in general it is an
iofunc_attr_t, or an extension of this type.

But, in the serial port case, all this per-client tracking is completely
hidden from you in the io-char library.

Quick help on these issues would be appreciated :)

Sorry, not quick, got here when I could.

I'll also email you a "sample" serial port driver -- it does not do
real hardware, but tx/rxs fake data driven by the timer interrupt. This
may more clearly illustrate the architecture. (Well, if your email
address is valid, I will.)

-David
--
David Gibbs
QNX Training Services
dagibbs@qnx.com
David Gibbs
 

re:Questions about writing a serial device using io-char

Postby ED209 » Fri Feb 02, 2007 7:01 pm

Hello,

thanks for the reply and for the sample code also. My driver is working now.But i still have one question:

Is there a better description how to handle the different actions in tto() besides TTO_DATA ? I only found this in the ser8250-docs:
TTO_STTY -- an stty command was received. It's called by io-char when the stty command is performed on the device. This action calls ser_stty(); the argument is ignored.

TTO_CTRL -- set the characteristics of the port i.e. control RS-232 modem lines.
arg1 _SERCTL_BRK_CHG -- called by io-char when the application requests a break such as tcsendbreak() to be sent
arg1 _SERCTL_DTR_CHG -- changes the DTR line
arg1 _SERCTL_RTS_CHG -- used to change the RTS line; io-char calls this to assert hardware flow control when the input buffer is filling up (based on the highwater level)
TTO_LINESTATUS -- a request for line status. Returns the status of the Modem Status and Modem Control registers when the user performs a devctl() with DCMD_CHR_LINESTATUS; the argument is ignored.
TTO_DATA -- output transmit data.
TTO_EVENT -- ignored.
ED209
New Member
 
Posts: 3
Joined: Fri Sep 15, 2006 3:00 pm

re:Questions about writing a serial device using io-char

Postby ED209 » Fri Feb 02, 2007 7:13 pm

accidentally hit submit... (isn't there an edit here?)

What i want to know especially is:
- what exactly is tto() supposed to return for TTO_LINESTATUS ?
- where are the parameters for TTO_STTY coming from ?
- whats the meaning of the arg1-parameters for TTO_CTRL (see code of 8250) ?

> if(arg1 & _SERCTL_BRK_CHG)
> set_port(port[REG_LC], LCR_BREAK, arg1 &_SERCTL_BRK ? LCR_BREAK : 0);
>
>if(arg1 & _SERCTL_DTR_CHG)
> set_port(port[REG_MC], MCR_DTR, arg1 & _SERCTL_DTR ? MCR_DTR : 0);
>
>if(arg1 & _SERCTL_RTS_CHG)
> set_port(port[REG_MC], MCR_RTS, arg1 & _SERCTL_RTS ? MCR_RTS : 0);

Thanks
ED209
New Member
 
Posts: 3
Joined: Fri Sep 15, 2006 3:00 pm

Re: re:Questions about writing a serial device using io-char

Postby David Gibbs » Fri Feb 02, 2007 8:34 pm

ED209 <ans666@gmx-dot-de.no-spam.invalid> wrote:
accidentally hit submit... (isn't there an edit here?)

What i want to know especially is:
- what exactly is tto() supposed to return for TTO_LINESTATUS ?

A set of line status bits. The exact bits will depend on the
device you are handling. The client issued a DCMD_CHR_LINESTATUS,
and you're responding. Take a look at <sys/dcmd_chr.h> for examples.
You'll see that parallel ports have different answers from serial ports,
and from others. You need to determine what makes sense for your device,
and provide (usually) a set of masks to that.

- where are the parameters for TTO_STTY coming from ?

tcsetattr() or devctl() calls -- often from a command line stty command,
but could be programmatically, too.

The io-char library will update your TTYDEV structure to reflect the
needed changes, you just have to implement those changes. devc-ser8250
just completely resets the hardware to reflect the new configuration.

Since these are, generally, only used at start/end of sessions, rather
than on the fly, the reset is a reasonable approach.

- whats the meaning of the arg1-parameters for TTO_CTRL (see code of
8250) ?

I think these are the result of a DCMD_CHR_LINECTRL devctl(), used to
manually toggle the line states. I haven't looked deeply enough at
the io-char library to see what they are from, exactly. But, you should
have a copy of the io-char library as part of the character driver DDK,
and could take a look.

Also... devc-ser8250 overloads tto() as both "io-char calls this to
tell me to do stuff" and "I call this at interrupt time to move data
out to the hardware". I prefer (architecturally, in my drivers) to
split those two ideas out.

(Actually, the char DDK/io-char library overloads way too many things,
especially the ttc() function, that sings, dances, and goes for soda.)

-David
--
David Gibbs
QNX Training Services
dagibbs@qnx.com
David Gibbs
 


Return to qnx.ddk

Who is online

Users browsing this forum: No registered users and 2 guests