Project Home
Project Home
Wiki
Wiki
Discussion Forums
Discussions
Project Information
Project Info
Forum Topic - ioctl_socket copyout not working: (4 Items)
   
ioctl_socket copyout not working  
Hi All,

I'd like to use ioctl operation to read data from the network driver. ioctl_socket() function returns success, but no 
data is copied back from the driver - looks like copyout() function doesn't work as expected. I use network driver 'as 
is' - I haven't modified its source code.

Here's sample code from the application:

memcpy(ifd.ifd_name, "dm0", 4);
ifd.ifd_len = sizeof(time);
ifd.ifd_data = &time;
ifd.ifd_cmd = PTP_GET_TIME;

ret = ioctl_socket(sk, SIOCGDRVSPEC, &ifd);
printf("sec=%d, nsec=%d\n", time.sec, time.nsec);


And driver code:

case PTP_GET_TIME:
	if (ifd->ifd_len != sizeof(time)) {
		return EINVAL;
	}

	ti814x_get_time(ti814x,&time);
	if (ISSTACK) {
		return (copyout(&time, (((uint8_t *)ifd) + sizeof(*ifd)),
				sizeof(time)));
	} else {
		memcpy((((uint8_t *)ifd) + sizeof(*ifd)), &time, sizeof(time));
		return EOK;
	}
	break;


copyout() function copies data 'just after' ifd struct. I believe it's some kind of QNX magic to make embedded pointers 
work across virtual address spaces. However, from the application side, no data is actually copied to the time structure
. Any ideas why copyout might not work?

regards,
Marcin
Re: ioctl_socket copyout not working  
Hi Marcin,
Several points here.
1) We already have a PTP implementation including 802.1AS support. That may be easier than writing your own.
2) ioctl_socket() isn't necessary in 6.5.0 and later, ioctl() handles everything.
3) This ioctl is a fixed length with variable length data afterwards. From the client side (i.e. PTP application) it's 
best to use MsgSendv with some IOVs e.g.:

static int imx6x_ioctl( int fd, struct ifdrv *ifd) {

	#define IMX6X_IOCTL_ARRAY_SZ 3

	iov_t siov[IMX6X_IOCTL_ARRAY_SZ];
	io_devctl_t msg;

	msg.i.type        = _IO_DEVCTL;
	msg.i.combine_len = sizeof msg.i;
	msg.i.dcmd        = PTP_IMX6X_INTERNAL_COMMAND;
	msg.i.nbytes      = IOCPARM_LEN((unsigned)PTP_IMX6X_INTERNAL_COMMAND);
	msg.i.zero        = 0;

	SETIOV(&siov[0], &msg, sizeof(io_devctl_t));
	SETIOV(&siov[1], ifd, sizeof(struct ifdrv));
	SETIOV(&siov[2], ifd->ifd_data, ifd->ifd_len);

	return MsgSendv_r(fd, siov, IMX6X_IOCTL_ARRAY_SZ,
					siov, IMX6X_IOCTL_ARRAY_SZ);
}

The fd is still the same one that you would use for an ioctl() call.

Regards,
Nick.
Re: ioctl_socket copyout not working  
Hi Nick,

Thank you for your reply, it works like a charm now.

> 1) We already have a PTP implementation including 802.1AS support. That may be easier than writing your own.
At the moment I am only interested in this particular ioctl, but I will keep that in mind.

> 2) ioctl_socket() isn't necessary in 6.5.0 and later, ioctl() handles everything
I already knew that, i just copied last version which happened to use ioctl_socket.

To clear things up - is it common that ioctl doesn't handle nested/embedded pointers and I shall always use my own ioctl
 implementation (like in your example)?

Marcin
Re: ioctl_socket copyout not working  
It's really only SIOCGDRVSPEC and SIOCSDRVSPEC that need this. Most of the time ioctl() will handle the embedded pointer
 fine.