Handling out-of-band (_IO_MSG) messages
An _IO_MSG message lets a client send an
out-of-band
or control message to a resource manager, by way of a file descriptor.
This interface is more general than an ioctl() or
devctl(), but less portable.
The format of the message is specific to the resource manager, aside from the header, which we'll look at shortly. The client program sets up the message and uses MsgSend() to send it to the resource manager. The resource manager must set up an io_msg handler in order to receive the message; there isn't a default handler.
struct _io_msg {
uint16_t type;
uint16_t combine_len;
uint16_t mgrid;
uint16_t subtype;
};
The fields include:
- type
- _IO_MSG
- combine_len
- Set this to
sizeof (struct _io_msg)
. - mgrid
- A unique ID for your resource manager. The <sys/iomgr.h> header file defines some IDs that are reserved for various QNX OS resource managers. You can use an ID in the range from _IOMGR_PRIVATE_BASE through _IOMGR_PRIVATE_MAX for your resource manager.
- subtype
- Use this field to distinguish different types of _IO_MSG messages that you want your resource manager to handle.
typedef struct {
struct _io_msg hdr;
/* Add any required data fields here. */
} my_msg_t;
#define MY_MGR_ID (_IOMGR_PRIVATE_BASE + 22)
my_msg_t msg, my_reply;
int fd;
long status;
fd = open ("/dev/sample", O_RDWR);
msg.hdr.type = _IO_MSG;
msg.hdr.combine_len = sizeof( msg.hdr );
msg.hdr.mgrid = MY_MGR_ID;
msg.hdr.subtype = 0;
/* Fill in the additional fields as required. */
status = MsgSend( fd, &msg, sizeof( msg ), &my_reply, sizeof (my_reply));
/* Initialize the functions for handling messages */
iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &connect_funcs,
_RESMGR_IO_NFUNCS, &io_funcs);
io_funcs.msg = my_io_msg;
int my_io_msg (resmgr_context_t *ctp, io_msg_t *msg, RESMGR_OCB_T *ocb)
{
my_msg_t my_msg;
MsgRead (ctp->rcvid, &my_msg, sizeof (my_msg), 0);
if (my_msg.hdr.mgrid != MY_MGR_ID)
{
return (ENOSYS);
}
/* Process the data as required. */
/* Reply if necessary and tell the library that we've already replied. */
MsgReply( ctp->rcvid, 0, &my_reply, sizeof(my_reply));
return (_RESMGR_NOREPLY);
}
Note that the handler returns ENOSYS if the mgrid member of the header isn't the correct manager ID. This handler replies to the client, and then returns _RESMGR_NOREPLY to tell the library that there's no need for it to do the reply.