devctl messages, passing data with pointers, help!!!!

// resouce manager
//---------------------

int io_devctl(resmgr_context_t *ctp, io_devctl_t *msg,
RESMGR_OCB_T *ocb) {

int nbytes, status, previous;
ADMXRC_IOCTLS_GETVERSIONINFO *pver ;

union {
data_t data;
int data32;
// … other devctl types you can receive
} *rx_data;

/*
Let common code handle DCMD ALL * cases.
You can do this before or after you intercept devctl’s depending
on your intentions. Here we aren’t using any pre-defined values
so let the system ones be handled first.
*/

if ((status = iofunc_devctl_default(ctp, msg,
ocb)) != _RESMGR_DEFAULT) {
return(status);
}
status = nbytes = 0;

/*
Note this assumes that you can fit the entire data portion of
the devctl into one message. In reality you should probably
perform a MsgReadv() once you know the type of message you
have received to suck all of the data in rather than assuming
it all fits in the message. We have set in our main routine
that we’ll accept a total message size of up to 2k so we
don’t worry about it in this example where we deal with ints.
*/
rx_data = _DEVCTL_DATA(msg->i);

/*
Three examples of devctl operations.
SET: Setting a value (int) in the server
GET: Getting a value (int) from the server
SETGET: Setting a new value and returning with the previous value

*/
switch (msg->i.dcmd) {
case MY_DEVCTL_SETVAL:
global_integer = rx_data->data32;
nbytes = 0;
break;
case MY_DEVCTL_GETVAL:
rx_data->data32 = global_integer;
nbytes = sizeof(rx_data->data32);
break;
case MY_DEVCTL_SETGET:
previous = global_integer;
global_integer = rx_data->data.tx;
rx_data->data.rx = previous; //Overwrites tx data
nbytes = sizeof(rx_data->data.rx);

pver = (ADMXRC_IOCTLS_GETVERSIONINFO*)
rx_data->data.p ;
printf (“addr %p \n”, pver);
pver->out.major = (unsigned char) 3 ;
pver->out.minor = (unsigned char) 6 ;

break;
default:
return(ENOSYS);
}

/* Clear the return message … note we saved our data after this /
memset(&msg->o, 0, sizeof(msg->o));
/

If you wanted to pass something different to the return
field of the devctl() you could do it through this member.
/
msg->o.ret_val = status;
/
Indicate the number of bytes and return the message */
msg->o.nbytes = nbytes;
return( _RESMGR_PTR(ctp, &msg->o,
sizeof(msg->o) + nbytes));
}

//----------------------




//----------------------------
program client
//---------------------------


typedef union _ADMXRC_IOCTLS_GETVERSIONINFO {
struct {
unsigned char major;
unsigned char minor;
} out;
} ADMXRC_IOCTLS_GETVERSIONINFO;


typedef union my_devctl_msg {
int tx; //Filled by client on send
int rx; //Filled by server on reply
void * p ;

} data_t;

#define MY_CMD_CODE 1
#define MY_DEVCTL_GETVAL __DIOF( _DCMD_MISC, MY_CMD_CODE + 0, int
)
#define MY_DEVCTL_SETVAL __DIOT( _DCMD_MISC, MY_CMD_CODE + 1, int
)
#define MY_DEVCTL_SETGET __DIOTF( _DCMD_MISC, MY_CMD_CODE + 2,
union my_devc
tl_msg )



int main(int argc, char **argv)
{
int fd, ret, val;
ADMXRC_IOCTLS_GETVERSIONINFO info;
data_t data;



if ((fd = open("/dev/sample0",
O_RDONLY)) == -1) {
return(1);
}


//…
memset(&data, 0, sizeof(data));
data.tx = 50;
data.p = &info ;

ret = devctl(fd, MY_DEVCTL_SETGET, &data,
sizeof(data), NULL);
printf (“version %d.%d”,info.out.major,
info.out.minor) ;

return(0);

}


the output of program client is:

vesion 0.0 , when it must be 3.6

the problem is the following:

I think that when calls io_devctl(----)

pver = (ADMXRC_IOCTLS_GETVERSIONINFO*)
rx_data->data.p ;

[b:aad0ffa63d]pver[/b:aad0ffa63d] aims to address of memory, but in
memory space of driver and not of client.

then I read and I write in memory but of driver, when i would have to
read and write in memory but of the process client.

somebody can say to me, how I do that? read and write in the space of
memory but of the process client

is possible that?

please! help!!!

On Tue, Apr 18, 2006 at 11:57:52PM +0000, stjosue wrote:

// resouce manager
//---------------------

int io_devctl(resmgr_context_t *ctp, io_devctl_t *msg,
RESMGR_OCB_T *ocb) {

int nbytes, status, previous;
ADMXRC_IOCTLS_GETVERSIONINFO *pver ;

union {
data_t data;
int data32;
// … other devctl types you can receive
} *rx_data;

/*
Let common code handle DCMD ALL * cases.
You can do this before or after you intercept devctl’s depending
on your intentions. Here we aren’t using any pre-defined values
so let the system ones be handled first.
*/

if ((status = iofunc_devctl_default(ctp, msg,
ocb)) != _RESMGR_DEFAULT) {
return(status);
}
status = nbytes = 0;

/*
Note this assumes that you can fit the entire data portion of
the devctl into one message. In reality you should probably
perform a MsgReadv() once you know the type of message you
have received to suck all of the data in rather than assuming
it all fits in the message. We have set in our main routine
that we’ll accept a total message size of up to 2k so we
don’t worry about it in this example where we deal with ints.
*/
rx_data = _DEVCTL_DATA(msg->i);

/*
Three examples of devctl operations.
SET: Setting a value (int) in the server
GET: Getting a value (int) from the server
SETGET: Setting a new value and returning with the previous value

*/
switch (msg->i.dcmd) {
case MY_DEVCTL_SETVAL:
global_integer = rx_data->data32;
nbytes = 0;
break;
case MY_DEVCTL_GETVAL:
rx_data->data32 = global_integer;
nbytes = sizeof(rx_data->data32);
break;
case MY_DEVCTL_SETGET:
previous = global_integer;
global_integer = rx_data->data.tx;
rx_data->data.rx = previous; //Overwrites tx data
nbytes = sizeof(rx_data->data.rx);

pver = (ADMXRC_IOCTLS_GETVERSIONINFO*)
rx_data->data.p ;
printf (“addr %p \n”, pver);
pver->out.major = (unsigned char) 3 ;
pver->out.minor = (unsigned char) 6 ;

break;
default:
return(ENOSYS);
}

/* Clear the return message … note we saved our data after this /
memset(&msg->o, 0, sizeof(msg->o));
/

If you wanted to pass something different to the return
field of the devctl() you could do it through this member.
/
msg->o.ret_val = status;
/
Indicate the number of bytes and return the message */
msg->o.nbytes = nbytes;
return( _RESMGR_PTR(ctp, &msg->o,
sizeof(msg->o) + nbytes));
}

//----------------------




//----------------------------
program client
//---------------------------


typedef union _ADMXRC_IOCTLS_GETVERSIONINFO {
struct {
unsigned char major;
unsigned char minor;
} out;
} ADMXRC_IOCTLS_GETVERSIONINFO;


typedef union my_devctl_msg {
int tx; //Filled by client on send
int rx; //Filled by server on reply
void * p ;

} data_t;

#define MY_CMD_CODE 1
#define MY_DEVCTL_GETVAL __DIOF( _DCMD_MISC, MY_CMD_CODE + 0, int
)
#define MY_DEVCTL_SETVAL __DIOT( _DCMD_MISC, MY_CMD_CODE + 1, int
)
#define MY_DEVCTL_SETGET __DIOTF( _DCMD_MISC, MY_CMD_CODE + 2,
union my_devc
tl_msg )



int main(int argc, char **argv)
{
int fd, ret, val;
ADMXRC_IOCTLS_GETVERSIONINFO info;
data_t data;



if ((fd = open("/dev/sample0",
O_RDONLY)) == -1) {
return(1);
}


//…
memset(&data, 0, sizeof(data));
data.tx = 50;
data.p = &info ;

ret = devctl(fd, MY_DEVCTL_SETGET, &data,
sizeof(data), NULL);
printf (“version %d.%d”,info.out.major,
info.out.minor) ;

return(0);

}


the output of program client is:

vesion 0.0 , when it must be 3.6

the problem is the following:

I think that when calls io_devctl(----)

pver = (ADMXRC_IOCTLS_GETVERSIONINFO*)
rx_data->data.p ;

[b:aad0ffa63d]pver[/b:aad0ffa63d] aims to address of memory, but in
memory space of driver and not of client.

then I read and I write in memory but of driver, when i would have to
read and write in memory but of the process client.

somebody can say to me, how I do that? read and write in the space of
memory but of the process client

is possible that?

please! help!!!

A non-root resource manager process can’t read the memory of another
process. The easiest thing to do is to get rid of the pointer:

typedef union my_devctl_msg {
int tx; //Filled by client on send
int rx; //Filled by server on reply
ADMXRC_IOCTLS_GETVERSIONINFO pver;
} data_t;


Gilles

thanks for reply.

that is the solution for this case, the problem is I need to pass a
pointer, because not always send that structure
“ADMXRC_IOCTLS_GETVERSIONINFO”, in other cases send other structures
with pointers also.

now, I have been reading and I believe that the solution is to use
shared memory, or somebody can say me that other options i have?

On Wed, Apr 19, 2006 at 11:58:14PM +0000, stjosue wrote:

thanks for reply.

that is the solution for this case, the problem is I need to pass a
pointer, because not always send that structure
“ADMXRC_IOCTLS_GETVERSIONINFO”, in other cases send other structures
with pointers also.

If you can’t avoid having pointers in your structures, you can use a
devctlv() (notice the extra v). It’s basically the same as devctl(), but
your messages can be spread out in memory. In the previous example you
could have the first iov by the address/size of your my_devctl_msg, and
then the second iov is the address/size of your
ADMXRC_IOCTLS_GETVERSIONINFO structure.

from devctl.h:
extern int devctlv(int fd, int dcmd, int sparts, int rparts, const
struct iovec *sv, const struct iovec *rv, int *dev_info_ptr);


now, I have been reading and I believe that the solution is to use
shared memory, or somebody can say me that other options i have?

I think shared memory would be more complicated to manage.


Gilles

Gilles Roywrote:


If you can’t avoid having pointers in your structures, you can use
a
devctlv() (notice the extra v). It’s basically the same as devctl(),
but
your messages can be spread out in memory. In the previous example
you
could have the first iov by the address/size of your my_devctl_msg,
and
then the second iov is the address/size of your
ADMXRC_IOCTLS_GETVERSIONINFO structure.

from devctl.h:
extern int devctlv(int fd, int dcmd, int sparts, int rparts, const
struct iovec *sv, const struct iovec *rv, int *dev_info_ptr);


I think shared memory would be more complicated to manage.

Gilles

thanks!

I have been looking for information details about devctlv() or some
examples, but I have not found anything :frowning:, I will try to implement
it .

look, to be more specify the structure that send with the function
devctl() is the following:

typedef struct _ADMXRC_IOCTL_PARAMS {
struct {
void* lpBuffer;
unsigned long nSize;
} in;
struct {
unsigned long nSize;
void* lpBuffer;
} out;
struct {
void* lpBuffer;
unsigned long nSize;
} mass;
} ADMXRC_IOCTL_PARAMS;


//------------------------------------
ADMXRC_IOCTL_PARAMS ibp;
int err;

err = devctl (hDevice, cmd , &ibp , sizeof(ibp) ,
NULL );
//-------------------------------------


where the pointers
in.lpBuffer
out.lpBuffer
mass.lpBuffer

aim at other structures and these can as well also contain pointers.

tell me, is devctlv the solution for this case??

On Thu, Apr 20, 2006 at 05:58:06PM +0000, stjosue wrote:

I have been looking for information details about devctlv() or some
examples, but I have not found anything > :frowning:> , I will try to implement
it .

Follow the documentation of devctl() for the dcmd, fd, and info_ptr. The
other parameters are similar to other functions ending in v, like
MsgSendv().

look, to be more specify the structure that send with the function
devctl() is the following:

where the pointers
in.lpBuffer
out.lpBuffer
mass.lpBuffer

aim at other structures and these can as well also contain pointers.

tell me, is devctlv the solution for this case??

You could write a cover function for the devctlv() which collects all of
the IOV’s and then call devctlv() for you. Seems to me like it would
work OK for what you are doing.


Gilles

thanks you so much!

I do not understand that it happens with this source code.

//resource manager process

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


#define THREAD POOL PARAM T dispatch context t
#include <sys/iofunc.h>
#include <sys/dispatch.h>

#include <sys/types.h>
#include <unistd.h>
#include <devctl.h>

typedef union _ADMXRC_IOCTLS_GETVERSIONINFO {
struct {
unsigned char major;
unsigned char minor;
} out;
} ADMXRC_IOCTLS_GETVERSIONINFO;



typedef union _ADMXRC_IOCTL_PARAMS {
union {
unsigned long nSize ;
void * lpBuffer ;
} in ;

union {
void * lpBuffer;
unsigned long nSize;

} out;
} ADMXRC_IOCTL_PARAMS;


#define MY_CMD_CODE 1
#define MY_DEVCTL_SETGET2 __DIOTF( _DCMD_MISC, MY_CMD_CODE + 1,
union _ADMXRC_IOCTL_PARAMS)


static resmgr_connect_funcs_t connect_funcs;
static resmgr_io_funcs_t io_funcs;
static iofunc_attr_t attr;



int io_devctl(resmgr_context_t *ctp, io_devctl_t *msg,
RESMGR_OCB_T *ocb) {

int nbytes, status;
ADMXRC_IOCTLS_GETVERSIONINFO *pver ;

union {
ADMXRC_IOCTL_PARAMS io;
// … other devctl types you can receive
} *rx_data;


if ((status = iofunc_devctl_default(ctp, msg,
ocb)) != _RESMGR_DEFAULT) {
return(status);
}
status = nbytes = 0;

rx_data = _DEVCTL_DATA(msg->i);

switch (msg->i.dcmd) {
case MY_DEVCTL_SETGET2:

printf (“in MY_DEVCTL_SETGET2 size %d \n”,
rx_data->io.out.nSize);
rx_data->io.out.nSize = 10 ;

pver = (ADMXRC_IOCTLS_GETVERSIONINFO*)
rx_data->io.out.lpBuffer ;

printf (“in MY_DEVCTL_SETGET2 addr %p \n”, pver
);

// (pver->out.major) = (unsigned char) 3 ;
// (pver->out.minor) = (unsigned char) 6 ;
// printf (“out MY_DEVCTL_SETGET2 addr %p data
%d.%d\n”, pver, pver->out.major, pver->out.minor);


nbytes = sizeof (rx_data->io.out.nSize);
break;

default:
printf (“command unknown \n” );
return(ENOSYS);
}

/* Clear the return message … note we saved our data after this */

memset(&msg->o, 0, sizeof(msg->o));
/*
If you wanted to pass something different to the return
field of the devctl() you could do it through this member.
/
msg->o.ret_val = status;
/
Indicate the number of bytes and return the message */
msg->o.nbytes = nbytes;
return( _RESMGR_PTR(ctp, &msg->o,
sizeof(msg->o) + nbytes));
}



main(int argc, char *argv)
{
/
declare variables we’ll be using */
thread_pool_attr_t pool_attr;
resmgr_attr_t resmgr_attr;
dispatch_t *dpp;
thread_pool_t *tpp;
dispatch_context_t *ctp;
int id;

/* initialize dispatch interface /
if((dpp = dispatch_create()) == NULL)
{
fprintf(stderr, “%s: Unable to allocate dispatch
handle.\n”,
argv[0]);
return EXIT_FAILURE;
}
/
initialize resource manager attributes */

memset(&resmgr_attr, 0, sizeof resmgr_attr);
resmgr_attr.nparts_max = 1;
resmgr_attr.msg_max_size = 2048;
/* initialize functions for handling messages */
iofunc_func_init( _RESMGR_CONNECT_NFUNCS, &connect_funcs,
_RESMGR_IO_NFUNCS, &io_funcs);

io_funcs.devctl = io_devctl ;
/* initialize attribute structure used by the device /
iofunc_attr_init(&attr, _S_IFNAM | 0666, 0, 0);
/
attach our device name /
id = resmgr_attach(dpp, /
dispatch handle /
&resmgr_attr, /
resource manager attrs */

“/dev/sample0”, /* device name /
_FTYPE_ANY, /
open type /
0, /
flags /
&connect_funcs, /
connect routines /
&io_funcs, /
I/O routines /
&attr); /
handle /
if(id == -1) {
fprintf(stderr, “%s: Unable to attach name.\n”,
argv[0]);
return EXIT_FAILURE;
}
/
initialize thread pool attributes /
memset(&pool_attr, 0, sizeof pool_attr);
pool_attr.handle = dpp;
pool_attr.context_alloc = dispatch_context_alloc;
pool_attr.block_func = dispatch_block;
pool_attr.handler_func = dispatch_handler;
pool_attr.context_free = dispatch_context_free;
pool_attr.lo_water = 2;
pool_attr.hi_water = 4;
pool_attr.increment = 1;
pool_attr.maximum = 50;
/
allocate a thread pool handle */

if((tpp = thread_pool_create(&pool_attr,
POOL_FLAG_EXIT_SELF)) == NULL) {
fprintf(stderr, “%s: Unable to initialize thread
pool.\n”,
argv[0]);
return EXIT_FAILURE;
}
/* start the threads, will not return */
thread_pool_start(tpp);

}



[b:4d467f37c8]//testing aplication[/b:4d467f37c8]

[code:1:4d467f37c8]
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <devctl.h>
#include <sys/mman.h>


#include <sys/stat.h>
#include <fcntl.h>

typedef union _ADMXRC_IOCTLS_GETVERSIONINFO {
struct {
unsigned char major;
unsigned char minor;
} out;
} ADMXRC_IOCTLS_GETVERSIONINFO;


typedef union _ADMXRC_IOCTL_PARAMS {
union {
unsigned long nSize ;
void * lpBuffer ;
} in ;

union {
void * lpBuffer;
unsigned long nSize;
} out;
} ADMXRC_IOCTL_PARAMS;



#define MY_CMD_CODE 1
#define MY_DEVCTL_SETGET2 __DIOTF( _DCMD_MISC, MY_CMD_CODE +1 ,
union _ADMXRC_IOCTL_PARAMS)


int main(int argc, char **argv)
{
int fd, ret, val;
ADMXRC_IOCTL_PARAMS par;
ADMXRC_IOCTLS_GETVERSIONINFO ver ;


if ((fd = open("/dev/sample0",
O_RDONLY)) == -1) {
return(1);
}

memset (&ver, 0, sizeof (ver));
memset (&par, 0, sizeof (par));

ver.out.major = (unsigned char)5 ;

par.in.nSize = 0 ;
par.in.lpBuffer = NULL ;


par.out.lpBuffer = &ver.out ;
par.out.nSize = sizeof (ver.out);

printf (" addr %p, nSize %d \n", par.out.lpBuffer,
par.out.nSize );

ret = devctl(fd, MY_DEVCTL_SETGET2, &par, sizeof
(par) , NULL);

printf(“SETGET2 returned with %d w/ server value
%d.%d\n”, ret, ver.out.major, ver.out.minor);
printf(“SETGET2 returned with %d w/ server value nSize
%d\n”, ret, par.out.nSize );

return(0);

}
[/code:1:4d467f37c8]


output:

bash-2.05a# ./resm
in MY_DEVCTL_SETGET2 size 2
in MY_DEVCTL_SETGET2 addr a


bash-2.05a# ./test
addr 2, nSize 2
SETGET2 returned with 0 w/ server value 5.0
SETGET2 returned with 0 w/ server value nSize 10
bash-2.05a#


why

par.out.lpBuffer = &ver.out ;
par.out.nSize = sizeof (ver.out);

are same

now if I declare like a structure all are ok, but i don´t overwrite
the data in resorce manager…

what happen?


I believe that I have many problems, you can help me to provide
examples to me of devctlv and handle io_devctl messages I need to
pass pointers, so far single I was checking that example, playing
with struct and unions in the messages.

thanks friend!
plaease help, on this my work depends.
i can to give you all my source code, well i’m porting device driver
for vxwork to QNX.

stjosue wrote:

I do not understand that it happens with this source code.

output:

bash-2.05a# ./resm
in MY_DEVCTL_SETGET2 size 2
in MY_DEVCTL_SETGET2 addr a


bash-2.05a# ./test
addr 2, nSize 2
SETGET2 returned with 0 w/ server value 5.0
SETGET2 returned with 0 w/ server value nSize 10
bash-2.05a#


why

par.out.lpBuffer = &ver.out ;
par.out.nSize = sizeof (ver.out);

are same

They are members of a union, and therefore the same. When you set
par.out.nsize you overwrite par.out.lpBuffer. Check the declaration
of your structures.

Murf

ok, thanks!

retaking the subject: “passing message data with pointer”.

can be a solution the follow? …


ADMXRC_IOCTL_PARAMS bp;


1.- get physical address of bp
2.- send it to driver process
3.- driver: map it to his memory space
4.- do work
5.- unmap
6.- return.

you tell if that can be work…

thanks folks.

On Sun, Apr 23, 2006 at 05:57:26PM +0000, stjosue wrote:

ok, thanks!

retaking the subject: “passing message data with pointer”.

can be a solution the follow? …


ADMXRC_IOCTL_PARAMS bp;


1.- get physical address of bp
2.- send it to driver process
3.- driver: map it to his memory space
4.- do work
5.- unmap
6.- return.

you tell if that can be work…

thanks folks.

You can use shared memory to do this, although the complexity will
probably be higher then using devctlv.

If you really want to do something like this, you can (if your
resmgr/driver is running as root) actually open the address space of the
client process. Basically you just call open("/proc/PID/as"), where PID
is the pid of the client and you can then use read(), write() and
lseek() to get info. For example, if the client passes in the addres
0x3456323, you would just open() their address space, and then lseek to
their address, and then read() the amount of bytes you want from the
address.

There are several examples of this kind of stuff in some of the QNX
books written by Robert Krten. A partial example in the link below (it
does’t do any writes, but does do reads). More info in the link below:
http://www.parse.com/products/books/book_v2/sample.html

One big drawback to this approach is that only one process can open
another process’s address space for writing at any time, this kind of
code won’t work if you have the driver/resmgr’s client open with GDB.


Gilles

ok, thanks.



iov_t riov[4];
ADMXRC_IOCTL_PARAMS par;

if ((fd = open("/dev/sample0",
O_RDONLY)) == -1) {
return(1);
}

memset (&ver, 0, sizeof (ver));
memset (&par, 0, sizeof (par));


ver.out.major = (unsigned char)5 ;

par.in.nSize = 100 ;
par.in.lpBuffer = NULL ;

par.out.lpBuffer = &ver.out ;
par.out.nSize = sizeof (ver.out);

par.mass.nSize = 0 ;
par.mass.lpBuffer = NULL ;

riov[0].iov_base = ∥
riov[0].iov_len = sizeof(par);

riov[1].iov_base = par.in.lpBuffer;
riov[1].iov_len = sizeof(*par.in.lpBuffer);

riov[2].iov_base = par.out.lpBuffer ;
riov[2].iov_len = sizeof( *par.out.lpBuffer) ;
riov[3].iov_base = par.mass.lpBuffer ;
riov[3].iov_len = sizeof( *par.mass.lpBuffer) ;

printf (“addr %p, nSize %d \n”, par.out.lpBuffer,
par.out.nSize );

// ret = devctl(fd, MY_DEVCTL_SETGET2, &par, sizeof
(par) , NULL);
ret = devctlv( fd, MY_DEVCTL_SETGET2 , 0, 4, 0 , riov ,
NULL);


is correct??

ahmm, why no work when i use 3th and 5th arguments ? the handle
io_devctl no called.

and tell em how to read the data in the handle io_devctl , with
_DEVCTL_DATA(msg->i); or resmgr_msgreadv( ctp, riov, 4, 0 );

please help!

thanks

On Tue, Apr 25, 2006 at 01:57:18AM +0000, stjosue wrote:

riov[0].iov_base = ∥
riov[0].iov_len = sizeof(par);

Instead of doing the above you can also use SETIOV:
SETIOV(&riov[0], &pas, sizeof(par));

riov[1].iov_base = par.in.lpBuffer;
riov[1].iov_len = sizeof(*par.in.lpBuffer);

riov[2].iov_base = par.out.lpBuffer ;
riov[2].iov_len = sizeof( *par.out.lpBuffer) ;
riov[3].iov_base = par.mass.lpBuffer ;
riov[3].iov_len = sizeof( *par.mass.lpBuffer) ;

The lpBuffers are just generic pointers right? I don’t think you want to
use sizeof(*par.lpBuffer) here, buecause that would be the sizeof the
pointer type, not the size of the buffer.

I.e. if I do:
char *ptr = malloc(100);

sizeof(*ptr) is only 4, not 100.

printf (“addr %p, nSize %d \n”, par.out.lpBuffer,
par.out.nSize );

// ret = devctl(fd, MY_DEVCTL_SETGET2, &par, sizeof
(par) , NULL);
ret = devctlv( fd, MY_DEVCTL_SETGET2 , 0, 4, 0 , riov ,
NULL);


is correct??

ahmm, why no work when i use 3th and 5th arguments ? the handle
io_devctl no called.

The 3rd and 5th arguments are the send iovs, and the 4th and 6th are the
receiver iovs. I’m not sure exactly what you need to do, but you will
need to at least do some send and recv iovs. In devctl() (without v) you
were sending and receiving the same structure. Here is you want to send
and receive everything you would do:

ret = devctlv(fd, MY_DEVCTL_SETGET2, 4, 4, riov, riov, NULL);

and tell em how to read the data in the handle io_devctl , with
_DEVCTL_DATA(msg->i); or resmgr_msgreadv( ctp, riov, 4, 0 );

Internally it could all end up in one big buffer. You need to parse out
the stuff yourself. If you used the devctlv I showed above, you would do
something like:

char *data = _DEVCTL_DATA(msg->i);

will give you the start of the buffer (actually a pointer the par
strcutre you passed in. Then data + sizeof(ADMXRC_IOCTL_PARAMS) will
point the par.in.lpBuffer from the riov[1] you had setup. Then data +
sizeof(ADMXRC_IOCTL_PARAMS) + the riov[1].iov_len will be a pointer to
the riov[2].iov_base you had setup, etc…

This assumes the resmgr received all of them in one buffer. You could
also read them out into your own iovs with resmgr_msgreadv(). You could
also just read out what you need MsgRead() one buffer at a time, once
you know it’s length.


Gilles

ok…
thanks!.

typedef struct _ADMXRC_IOCTL_PARAMS {
struct {
void* lpBuffer; /* pointer to buffer to supply input data /
unsigned long nSize; /
size of input buffer /
} in;
struct {
unsigned long nSize; /
size of output buffer /
void
lpBuffer; /* pointer to buffer to receive output data */

} out;
struct {
void* lpBuffer; /* pointer to buffer to receive output data /
unsigned long nSize; /
size of output buffer */
} mass;
} ADMXRC_IOCTL_PARAMS;


well, i’m porting device driver for vxWork to QNX 6.3
in vxworks use the function for send and receive data

[code:1:bb82a89dc7]ioctl(hDevice, IoControlCode, (unsigned
int) &ibp);[/code:1:bb82a89dc7]
where
hDevice is the descriptor returned for
the function Open(…).
[b:bb82a89dc7]IoControlCode[/b:bb82a89dc7] is the type command or
work to will do.
[b:bb82a89dc7]ibp [/b:bb82a89dc7]is the type ADMXRC_IOCTL_PARAMS.

like in vxWork there isn’t memory manager then the addreses are
physicals… ( lpBuffer … ) and the results it’s written in
out.lpBuffer and mass.lpBuffer addreses.

well., when i try the same with devctl and send the same structure,
the problem was that the addreses are virtuals, then you recommended
me use devctlv(…)

well i think that have to do the following:
// send data

[code:1:bb82a89dc7]
siov[0].iov_base = ∥
siov[0].iov_len = sizeof(par);
siov[1].iov_base = par.in.lpBuffer;
siov[1].iov_len = size ;
[/code:1:bb82a89dc7]
// receive data

[code:1:bb82a89dc7]
riov[0].iov_base = par.out.lpBuffer ;
riov[0].iov_len = size;
riov[1].iov_base = par.mass.lpBuffer ;
riov[1].iov_len = size ;
[/code:1:bb82a89dc7]
or with SETIOV for each…
and then calls…

[code:1:bb82a89dc7]devctlv(int fd, int dcmd, 2, 2, siov , riov ,
NULL);
[/code:1:bb82a89dc7]
is correct or it would be:

[code:1:bb82a89dc7]devctlv(int fd, int dcmd, 2, 2,
&siov[0] , &riov[0] ,
NULL);[/code:1:bb82a89dc7]
the problem that in both cases no work, no called handle io_devctl in
resorce manger and when i don’t use the 3th and 5th parameter, yes,
called the handle io_devctl, why??

other question…

the second parameter (dcmd), as it must be declared?
so.

[code:1:bb82a89dc7]
#define MY_DEVCTL_SETGET2 __DIOTF( _DCMD_MISC, 4 , struct
_ADMXRC_IOCTL_PARAMS)
[/code:1:bb82a89dc7]
or can i put anything?, like:

[code:1:bb82a89dc7]devctlv(int fd, 1000 , 2, 2,
&siov[0] , &riov[0] ,
NULL);[/code:1:bb82a89dc7]
??

ahmm, in.lpBuffer, out.lpBuffer and mass.lpBuffer are pointers
generics.
ie. they can point to others structures, like:

[code:1:bb82a89dc7]
typedef union _ADMXRC_IOCTLS_DODMA2D {
struct {
ADMXRC2_DMADESC dmadesc;
unsigned long offset;
unsigned long length;
unsigned long local;
unsigned long width;
unsigned long skip;
unsigned long local_skip;
unsigned long direction;
unsigned long channel;
unsigned long mode;
unsigned long flags;
unsigned long timeout;
} in;
} ADMXRC_IOCTLS_DODMA2D;

typedef union _ADMXRC_IOCTLS_DODMAIMMEDIATE {
struct {
void* buffer;
unsigned long length;
unsigned long local;
unsigned long direction;
unsigned long channel;
unsigned long mode;
unsigned long flags;
unsigned long timeout;
} in;
} ADMXRC_IOCTLS_DODMAIMMEDIATE;
[/code:1:bb82a89dc7]
when the pointed structure for out.lpBuffer also contains pointers,
for example that point to ADMXRC_IOCTLS_DODMAIMMEDIATE, i think that
have add other iov ie. riov[3].io_base = out.lpBuffer->in.buffer
and then calls devctlv, true?

the advantage is that this new pointer no point at another structure
with other pointers.

well then the pointers in,out,mass (.lpBuffer) they can point to
others structures with or without new pointers, but these last no
can point at other structures with new pointers.

thanks!!!.

Code:
devctlv(int fd, int dcmd, 2, 2, siov , riov , NULL);

is correct or it would be:
Code:
devctlv(int fd, int dcmd, 2, 2, &siov[0] , &riov[0] ,
NULL);

the problem that in both cases no work, no called handle io_devctl
in resorce manger and when i don’t use the 3th and 5th parameter,

yes, called the handle io_devctl, why??

now work ok, i use SETIOV

now my problem is how to return the data?

//resource manager - handle io_devctl

int io_devctl(resmgr_context_t *ctp, io_devctl_t *msg,
RESMGR_OCB_T *ocb) {
int nbytes, status;
ADMXRC_IOCTL_PARAMS iob;
ADMXRC_IOCTLS_GETVERSIONINFO *pver ;
char *data;

if ((status = iofunc_devctl_default(ctp, msg,
ocb)) != _RESMGR_DEFAULT) {
return(status);
}
status = nbytes = 0;

data = _DEVCTL_DATA(msg->i);

switch (msg->i.dcmd) {
case 90:

memcpy (&iob, data ,sizeof (iob));

printf(“IN: addr %p size %d \n”,
iob.in.lpBuffer, iob.in.nSize );
printf(“OUT: addr %p size %d \n”,
iob.out.lpBuffer, iob.out.nSize );
printf(“MASS: addr %p size %d \n”,
iob.mass.lpBuffer, iob.mass.nSize );

pver = (ADMXRC_IOCTLS_GETVERSIONINFO*) (data +
sizeof (iob) + iob.in.nSize) ;
printf (“read out - addr %p data: %d.%d
\n”, pver, pver->out.major, pver->out.minor );

pver->out.major = (unsigned char) 3 ;
pver->out.minor = (unsigned char) 6 ;

nbytes = 2;
break;

default:
printf (“command unknown \n” );
return(ENOSYS);
}

/* Clear the return message … note we saved our data after this */

memset(&msg->o, 0, sizeof(msg->o));
/*
If you wanted to pass something different to the return
field of the devctl() you could do it through this member.
/
msg->o.ret_val = status;
/
Indicate the number of bytes and return the message */
msg->o.nbytes = nbytes;

SETIOV(&ctp->iov[0], pver, 2 );
SETIOV(&ctp->iov[1], NULL , 0);

return (_RESMGR_NPARTS(2));

// return( _RESMGR_PTR(ctp, &msg->o,
sizeof(msg->o) + nbytes));
}

// testing aplication

[code:1:6a7800a3e8]
int main(int argc, char **argv)
{
int fd, ret, val;
iov_t siov[4];
iov_t riov[4];
ADMXRC_IOCTL_PARAMS par;
ADMXRC_IOCTLS_GETVERSIONINFO ver ;

if ((fd = open("/dev/sample0",
O_RDONLY)) == -1) {
return(1);
}

memset (&ver, 0, sizeof (ver));
memset (&par, 0, sizeof (par));

ver.out.major = (unsigned char)5 ;

par.in.nSize = 0 ;
par.in.lpBuffer = NULL ;
par.out.lpBuffer = &ver.out ;
par.out.nSize = sizeof (ver.out);
par.mass.nSize = 0 ;
par.mass.lpBuffer = NULL ;

SETIOV(&siov[0], &par, sizeof
(par));
SETIOV(&siov[1], par.in.lpBuffer,
par.in.nSize);

SETIOV(&riov[0], par.out.lpBuffer,
par.out.nSize);
SETIOV(&riov[1], par.mass.lpBuffer,
par.mass.nSize);

printf (“addr %p, nSize %d \n”,
riov[0].iov_base, riov[0].iov_len );

// ret = devctl(fd, MY_DEVCTL_SETGET2 , &par, sizeof
(par) , NULL);

ret = devctlv( fd, 90 , 2, 2, siov , &riov[0] ,
NULL);

printf(“returned with %d w/ server value %d.%d\n”,
ret, ver.out.major, ver.out.minor);

return(0);
}[/code:1:6a7800a3e8]

output:
resource manager:

bash-2.05a# ./resm
IN: addr 0 size 0
OUT: addr 8047706 size 2
MASS: addr 0 size 0
read out - addr 804f32c data: 0.0

testing aplication:

bash-2.05a# ./test
addr 8047706, nSize 2
returned with 0 w/ server value 5.0
/-----------------------------------------
in this line:

pver = (ADMXRC_IOCTLS_GETVERSIONINFO*) (data + sizeof (iob) +
iob.in.nSize) ;


[b:6a7800a3e8]pver[/b:6a7800a3e8] point to riov[0] ?
or only can i read data of siov and not of riov?

if pver is not a pointer, ie.

[code:1:6a7800a3e8]
ADMXRC_IOCTLS_GETVERSIONINFO pver ;


// pver = (ADMXRC_IOCTLS_GETVERSIONINFO*) (data + sizeof
(iob) + iob.in.nSize) ;

pver.out.major = (unsigned char) 3 ;
pver.out.minor = (unsigned char) 6 ;


SETIOV(&ctp->iov[0], &pver, 2 );
SETIOV(&ctp->iov[1], NULL , 0);

return (_RESMGR_NPARTS(2));

[/code:1:6a7800a3e8]


the results is the same. :frowning:

help how to return the data??

thanks for your help!!

On Tue, Apr 25, 2006 at 11:57:13PM +0000, stjosue wrote:

now work ok, i use SETIOV

now my problem is how to return the data?

//resource manager - handle io_devctl

int io_devctl(resmgr_context_t *ctp, io_devctl_t *msg,
RESMGR_OCB_T *ocb) {

msg->o.ret_val = status;
/* Indicate the number of bytes and return the message */
msg->o.nbytes = nbytes;

SETIOV(&ctp->iov[0], pver, 2 );
SETIOV(&ctp->iov[1], NULL , 0);

return (_RESMGR_NPARTS(2));

This is bad. The first part of the message needs to be &msg->o.

// return( _RESMGR_PTR(ctp, &msg->o,
sizeof(msg->o) + nbytes));

Your old code returned the date at &msg->o, which is the io_devctl_t
message (needed by the resmgr code) followed by the data buffer.

If you want to do the same now you would need to do something like:

SETIOV(&ctp->iov[0], &msg->o, sizeof(msg->o));
SETIOV(&ctp->iov[0], &pver->out, sizeof(pver->out));
return (_RESMGR_NPARTS(2));

One important point to remember is that the resource manager device
driver doesn’t know if the application called devctl(), or devctlv().
Both look identical, so this means you don’t need to change the way the
resmgr handles the data.


Gilles