driver & select

Hello!

I wrote resoource manager (device) in NTO.
It works but select(…) call to it returns immediatly with set read fds.
Q: How must i do to select(…) call ?


Vasili

vv40in <vv40in@mail.ru> wrote:

Hello!

I wrote resoource manager (device) in NTO.
It works but select(…) call to it returns immediatly with set read fds.
Q: How must i do to select(…) call ?

Look at the iofunc_notify_* helper functions, and you’ll need an io_notify
callback as well.

-David

QNX Training Services
dagibbs@qnx.com

vv40in <vv40in@mail.ru> wrote:

Thank You.

But I dont understand how to use that notification helper function., how to use
io_notify_t structure.

Writing a Resource Manager
(> http://qdn.qnx.com/support/docs/neutrino_qrp/prog/resmgr.html > if i’m not wrong) dont
contain that information. Library Refference too.
Can You show me any device source code examples with notification processing ?

Thanks
Vasili

Vasili,

You are absolutely 100% correct. Due to time constraints we have
not yet had a chance to get ionotify (mechanism used by select) into
the docs as example code. Dave might have an example from the
Device Driver classes.

Thomas

David Gibbs <> dagibbs@qnx.com
vv40in <> vv40in@mail.ru> > wrote:
Hello!

I wrote resoource manager (device) in NTO.
It works but select(…) call to it returns immediatly with set read fds.
Q: How must i do to select(…) call ?

Look at the iofunc_notify_* helper functions, and you’ll need an io_notify
callback as well.

-David

QNX Training Services
dagibbs@qnx.com



Thomas (toe-mah) Fletcher QNX Software Systems
thomasf@qnx.com Neutrino Development Group
(613)-591-0931 http://www.qnx.com/~thomasf

Thank You.

But I dont understand how to use that notification helper function., how to use
io_notify_t structure.

Writing a Resource Manager
(http://qdn.qnx.com/support/docs/neutrino_qrp/prog/resmgr.html if i’m not wrong) dont
contain that information. Library Refference too.
Can You show me any device source code examples with notification processing ?

Thanks
Vasili

David Gibbs <dagibbs@qnx.com>

vv40in <> vv40in@mail.ru> > wrote:
Hello!

I wrote resoource manager (device) in NTO.
It works but select(…) call to it returns immediatly with set read fds.
Q: How must i do to select(…) call ?

Look at the iofunc_notify_* helper functions, and you’ll need an io_notify
callback as well.

-David

QNX Training Services
dagibbs@qnx.com

thomasf@qnx.com wrote:

vv40in <> vv40in@mail.ru> > wrote:
Thank You.



You are absolutely 100% correct. Due to time constraints we have
not yet had a chance to get ionotify (mechanism used by select) into
the docs as example code. Dave might have an example from the
Device Driver classes.

Here is a sample from our course:

-David
QNX Training Services
dagibbs@qnx.com

/*

  • ionotify.c
  • This is a resource manager that demonstrates how to handle
  • ionotify()/select(). It has a io_notify handler function to handle
  • the _IO_NOTIFY message. It also has an io_write handler to handle
  • _IO_WRITEs. When it gets an _IO_WRITE, it responds by notifying
  • the appropriate client(s). The client then does a read()
  • to get the data. There is a _IO_READ handler to handle this.

*/

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

struct device_attr_s;
#define IOFUNC_ATTR_T struct device_attr_s

#include <sys/iofunc.h>
#include <sys/dispatch.h>
#include <sys/neutrino.h>
#include <sys/resmgr.h>

/* the extended attributes structure /
typedef struct device_attr_s {
iofunc_attr_t attr;
iofunc_notify_t notify[3]; // notification list used by iofunc_notify
()
} device_attr_t;

void options (int argc, char **argv);
int io_close_ocb (resmgr_context_t *ctp, void *reserved, RESMGR_OCB_T *ocb);
int io_read (resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb);
int io_write (resmgr_context_t *ctp, io_write_t *msg, RESMGR_OCB_T *ocb);
int io_notify (resmgr_context_t *ctp, io_notify_t *msg, RESMGR_OCB_T *ocb);

// data structure for storing the data until the client reads it
typedef struct item_s {
struct item_s *next;
char *data;
} item_t;
item_t *firstitem = NULL;
int nitems = 0;

resmgr_connect_funcs_t connect_funcs;
resmgr_io_funcs_t io_funcs;
dispatch_t *dpp;
resmgr_attr_t rattr;
dispatch_context_t *ctp;
device_attr_t ioattr;

char *progname = “ionotify”;
int optv; // -v for verbose operation

main (int argc, char **argv)
{
printf ("%s: starting…\n", progname);

options (argc, argv);

dpp = dispatch_create ();
memset (&rattr, 0, sizeof (rattr));

iofunc_func_init (_RESMGR_CONNECT_NFUNCS, &connect_funcs,
_RESMGR_IO_NFUNCS, &io_funcs);
io_funcs.close_ocb = io_close_ocb;
io_funcs.read = io_read;
io_funcs.write = io_write;
io_funcs.notify = io_notify;

iofunc_attr_init (&ioattr.attr, S_IFCHR | 0666, NULL, NULL);
resmgr_attach (dpp, &rattr, “/dev/ionotify”, _FTYPE_ANY, 0,
&connect_funcs, &io_funcs, &ioattr);

ctp = dispatch_context_alloc (dpp);

while (1) {
ctp = dispatch_block (ctp);
dispatch_handler (ctp);
}
}

/*

  • io_notify
  • This is called when the client calls ionotify() to ask to be
  • notified about something.
    */
    int
    io_notify (resmgr_context_t *ctp, io_notify_t *msg, RESMGR_OCB_T *ocb)
    {
    device_attr_t *attr = ocb->attr;
    int trig = 0;
    int rc;

if (optv) {
printf ("%s: in io_notify\n", progname);
}

/*

  • ‘trig’ tells iofunc_notify() which conditions are currently
  • satisfied.
    */

if (nitems > 0)
trig = _NOTIFY_COND_INPUT; /* we have some data available */

rc = iofunc_notify (ctp, msg, attr->notify, trig, NULL, NULL);

return (rc);
}

/*

  • io_write
  • In this example, this is called when you run the echo utility
  • or anything that write()s. Here we add the data written to a
  • queue of data items and notify any clients that there is data
  • available.
    */
    int
    io_write (resmgr_context_t *ctp, io_write_t *msg, RESMGR_OCB_T *ocb)
    {
    device_attr_t *attr = ocb->attr;
    char *buf;
    int i;
    char *p;
    int status;
    item_t *newitem;

if (optv) {
printf ("%s: in io_write\n", progname);
}

if ((status = iofunc_write_verify(ctp, msg, ocb, NULL)) != EOK)
return (_RESMGR_ERRNO(status));

if (msg->i.xtype & _IO_XTYPE_MASK != _IO_XTYPE_NONE)
return(_RESMGR_ERRNO(ENOSYS)); // No special xtypes

if (msg->i.nbytes > 0) {
if ((newitem = malloc (sizeof (item_t))) == NULL)
return (_RESMGR_ERRNO(errno));
if ((newitem->data = malloc (msg->i.nbytes+1)) == NULL) {
free (newitem);
return (_RESMGR_ERRNO(errno));
}
resmgr_msgread (ctp, newitem->data, msg->i.nbytes, sizeof (msg->i));
newitem->data[msg->i.nbytes] = NULL;

if (firstitem)
newitem->next = firstitem;
else
newitem->next = NULL;
firstitem = newitem;
nitems++;

/*

  • notify anyone who may have asked to be notified when there
  • is data.
    */

iofunc_notify_trigger (attr->notify, nitems, IOFUNC_NOTIFY_INPUT);
}

_IO_SET_WRITE_NBYTES (ctp, msg → i.nbytes);

if (msg->i.nbytes > 0)
ocb->attr->attr.flags |= IOFUNC_ATTR_MTIME | IOFUNC_ATTR_CTIME;

return (_RESMGR_NPARTS (0));
}

/*

  • io_read
  • In the io_write handler above, we notified the client that data
  • was available. The client would get that notification (pulse or
  • signal) and then do a read() to get the data. That is when this
  • io_read handler will be called. In it we get the oldest data from
  • our queue and reply with it.
    */
    int
    io_read (resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb)
    {
    int status;

if (optv) {
printf ("%s: in io_read\n", progname);
}

if ((status = iofunc_read_verify(ctp, msg, ocb, NULL)) != EOK)
return (_RESMGR_ERRNO(status));

if (msg->i.xtype & _IO_XTYPE_MASK != _IO_XTYPE_NONE)
return(_RESMGR_ERRNO(ENOSYS)); // No special xtypes

if (firstitem) { // if we have any data stored away
int nbytes;
item_t *item, *prev;

/* get last item */
item = firstitem;
prev = NULL;
while (item->next != NULL) {
prev = item;
item = item->next;
}

/*

  • figure out number of bytes to give, write the data to the
  • client’s reply buffer
    /
    nbytes = min (strlen (item->data), msg->i.nbytes);
    _IO_SET_WRITE_NBYTES (ctp, nbytes); /
    read() will return nbytes */
    resmgr_msgwrite (ctp, item->data, nbytes, 0);

/* remove the data from the queue */
if (prev)
prev->next = item->next;
else
firstitem = NULL;
free (item->data);
free (item);
nitems–;
} else {
_IO_SET_READ_NBYTES (ctp, 0);
}

if (msg->i.nbytes > 0)
ocb->attr->attr.flags |= IOFUNC_ATTR_ATIME;

return (EOK);
}

int
io_close_ocb (resmgr_context_t *ctp, void *reserved, RESMGR_OCB_T *ocb)
{
if (optv) {
printf ("%s: in io_close_ocb\n", progname);
}

// since the client is closing, we won’t be needing to notify
// it of anything anymore so remove the client from our list

iofunc_notify_remove (ctp, ocb->attr->notify);

return (iofunc_close_ocb_default (ctp, reserved, ocb));
}

/*

  • options
  • This routine handles the command line options.
  • We support:
  •  -v      verbose operation
    

*/
void
options (int argc, char **argv)
{
int opt;
int i;

optv = 0;

i = 0;
while (optind < argc) {
while ((opt = getopt (argc, argv, “v”)) != -1) {
switch (opt) {
case ‘v’:
optv = 1;
break;
}
}
}
}