Patrik Lahti
11/02/2009 10:29 AM
post41160
|
Hi,
> How to copy the data using ioctl function.
You can't.
Because you use #define MY_CMD _IOWR('i',1,struct ifreq) the ioctl API
will copy sizeof(struct ifreq) bytes from the data pointer in the app to
the stack. Once in your driver code, it has only the struct ifreq. The
data which ifr_data points to needs to also be copied to the stack.
You can do this by using MsgSend APIs like ioctl_socket() does. This
will mean that inside your driver code, the data pointer points to a
block of memory which first has the struct ifreq and directly after
follows whatever ifr_data pointed to.
As you see, ioctl_socket() will use IOVs and MsgSendv(). It does so
because the ifr and the ifr_data pointers are scattered so IOVs are
convenient. It puts the data pointer of sizeof(struct ifreq) in the
first IOV, and puts the ifr_data pointer and its length, which depends
on what type of ioctl command is being processed, in the second IOV.
E.g. in the case of SIOCGETVLAN ifr_data points to a struct vlanreq and
so the size of the second IOV is sizeof(struct vlanreq).
In the MsgSendv() API, the two IOVs gets copied and "gathered" so that
they are linear (one after the other) when they arrive at the stack.
Following the example of SIOCGETVLAN, it means data points to a place in
memory where there is first a struct ifreq AND a struct vlanreq follows
right after it.
In your code you have a string in ifr_data. You've therefore got to
change your app to use MsgSend like ioctl_socket() does and put the
length of the string in the second IOV.
The only alternative is to change your app code to always pass a
concatenated ifr and ifr_data buffer to ioctl() and change the define of
MY_CMD to use a type which represent that concatenation, but that's not
advisable and really not customary.
In addition, as I pointed out earlier, there is a bug in your driver
code here:
> memcpy(data,"driver",5);
You're copying "driver" straight into data, ie. into where the struct
ifreq is, not where the ifr_data is. And the length of the copy is wrong.
You want to copy into the place where ifr_data is:
> memcpy(ifr+1,"driver",strlen("driver") + 1);
Hope this helps!
/P
|
|
|