Handling devctl() messages
int devctl( int fd,
int dcmd,
void * data,
size_t nbytes,
int * return_info );
struct _io_devctl {
uint16_t type;
uint16_t combine_len;
int32_t dcmd;
uint32_t nbytes;
int32_t zero;
/* char data[nbytes]; */
};
struct _io_devctl_reply {
uint32_t zero;
int32_t ret_val;
uint32_t nbytes;
int32_t zero2;
/* char data[nbytes]; */
} ;
typedef union {
struct _io_devctl i;
struct _io_devctl_reply o;
} io_devctl_t;
io_devctl_t *msg
which is the pointer to the union containing the message.
The type member has the value _IO_DEVCTL.
The combine_len field has meaning for a combine message; see the Combine Messages chapter.
The nbytes value should not be used to determine the length of the message because the value is unreliable. Use the methods described in the Message Checking section instead.
#define _POSIX_DEVDIR_NONE 0
#define _POSIX_DEVDIR_TO 0x80000000
#define _POSIX_DEVDIR_FROM 0x40000000
#define __DIOF(class, cmd, data) ((sizeof(data)<<16) + ((class)<<8) + (cmd) + _POSIX_DEVDIR_FROM)
#define __DIOT(class, cmd, data) ((sizeof(data)<<16) + ((class)<<8) + (cmd) + _POSIX_DEVDIR_TO)
#define __DIOTF(class, cmd, data) ((sizeof(data)<<16) + ((class)<<8) + (cmd) + _POSIX_DEVDIR_TOFROM)
#define __DION(class, cmd) (((class)<<8) + (cmd) + _POSIX_DEVDIR_NONE)
It's important to understand how these macros pack data to create a command. An 8-bit class (defined in <devctl.h>) is combined with an 8-bit subtype that's manager-specific, and put together in the lower 16 bits of the integer.
The upper 16 bits contain the direction (TO, FROM) as well as a hint about the size of the data structure being passed. This size is only a hint put in to uniquely identify messages that may use the same class and code but pass different data structures.
struct _my_devctl_msg {
...
}
#define MYDCMD __DIOT(_DCMD_MISC, 0x54, struct _my_devctl_msg)
The data directly follows this message structure,
as indicated by the /* char data[nbytes] */
comment in the _io_devctl structure.