Interface of the driver
Yong Ma
mayong at mail.com
Thu Nov 3 03:05:48 PST 2005
----- Original Message -----
From: "M. Warner Losh" <imp at bsdimp.com>
To: mayong at mail.com
Subject: Re: Interface of the driver
Date: Wed, 02 Nov 2005 21:36:24 -0700 (MST)
>
> In message: <20051103025038.CAF618401E at ws1-5.us4.outblaze.com>
> "Yong Ma" <mayong at mail.com> writes:
>
> : My driver for the cryptographic accelerator is almost finished, the
> : next job will be the development of user interfaces. I've got some
> : problems now: Is the ioctl() function the only way in which the user
> : implications interact with the driver(mine is a KLD module)?
>
> Yes and no. It is the typical way that most drivers choose to
> interact with userland. In this model, you have to add a device entry
> (see make_dev(9)) wher you give it a 'cdevsw' structure. This is the
> stylized way of doing function potiners for entry points (virtual
> functions in C++ use a similar mechanism) to the driver. You create a
> device, the user opens it and then issues requests. In your case
> ioctl (although I suspect read and write too).
>
> : If so,
> : how can I pass some arguments(such as my private key or the file
> : name that will be encrypted)?
>
> There are a number of macros which help you to pass arguments. The
> ioctl function itself takes a 'function' and a 'arguement'. Since the
> 'function' also encodes the size and direction of the ioctl, it can
> copy the arguments into the kenrel for you and copy them out when you
> are done.
>
> : Can I call some function(with
> : arguments) defined in the driver in my user implications, and how?
>
> Most drivers that define an ioctl interface have a fooio.h header.
> fooio.h will include <sys/ioccom.h> and then device their command
> numbers. For example, mtio.h defines mag tape ioctls:
>
> /* mag tape io control commands */
> #define MTIOCTOP _IOW('m', 1, struct mtop) /* do a mag tape op */
> #define MTIOCGET _IOR('m', 2, struct mtget) /* get tape status */
> /* these two do not appear to be used anywhere */
> #define MTIOCIEOT _IO('m', 3) /* ignore EOT error */
>
> The first one 'writes' a magtape operation to the kernel. This is
> contained in a struct mtop. The struct mtop is defined in mtio.h, but
> I've omitted it here. The driver gets the MTIOCTOP operations, does
> some casting and then extracts data from the passed in structure. The
> kernel code looks something like:
>
> static int
> saioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct
> thread *td)
> {
> int err;
> ...
> err = 0;
> switch (cmd) {
> ...
> case MTIOCTOP:
> {
> struct mtop *mt = (struct mtop *) arg;
> err = sa_process_mt(mt);
> break;
> }
> default:
> err = ENOTTY;
> break;
> }
> ...
> return (err);
> }
>
>
> The sa_process_mt routine would be something the driver wrote to
> interpret the struct mtop from this call. Similarly for other ioctls.
>
> _IOW() is for defining ioctls that write data into the kernel only.
> Most 'set' ioctls are IOW. _IOR are used to extract data from the
> kernel. Most 'get' ioctls are IOR. _IO ioctls are ioctls that pass
> no data to the kernel and do some predefined thing (like set the
> ignore eof flag above). _IOWR are used to pass data both ways, into
> and out of the kernel. These are used for more complicated 'get'
> routines or to communicate data back out of the kernel.
>
> In userland, the user would just include the fooio.h file and use it
> like they would for any other ioctl:
>
> struct foo_state
> {
> ...
> };
>
> #define FOOIOCGETSTATE _IOR('f', 1, struct foo_state);
> ...
> struct foo_state state;
> int foo;
>
> fd = open("/dev/foo0", O_RDWR);
> if (fd == -1)
> err(1, "open");
> if (ioctl(fd, FOOIOCGETSTATE, &state) == -1)
> err(1, "IOOIOCFETSTATE");
> /* Do something with the state */
> close(fd);
> ...
>
> hope this helps..
>
> Warner
Thank you very much,it is just what I need!
I did as you said but came across some problems:
My test application is as follows(ioctltest.c):
1 #include <sys/ioccom.h>
2 #include <string.h>
3 #include <fcntl.h>
4 #include <unistd.h>
5 #include <err.h>
6
7 #define ENCRYPTFILE _IOW("s", 3, struct ioctlinfo)
8
9 struct ioctlinfo{
10 unsigned long addr;
11 char *buffer;
12 };
13
14 int main(void){
15 int fd;
16 struct ioctlinfo info;
17 info.addr=0;
18 char *ibuffer="Ioctl test!\n";
19 printf("Ioctltest:%s\n",ibuffer);
20 info.buffer=ibuffer;
21 fd=open("/dev/sjy22b0",O_RDWR);
22 if(fd==-1)
23 err(1,"open");
24 if(ioctl(fd,ENCRYPTFILE,&info)==-1)
25 err(1,"CRYPTFILE!");
26 close(fd);
27 return (0);
28 }
A really simple one:),and the ioctl() in driver adjust as this:
...
313 case ENCRYPTFILE:
314 ioinfo=(struct ioctlinfo *)addr;
315 printf("Ioctlinfo :\n addr=%ld\nbuffer:%s\n",ioinfo->addr,ioinfo->buffer);
316
317 break;
...
but when I complie the test application(ioctltest.c),it told me:
ioctltest.c: In function `main':
ioctltest.c:24: error: invalid operands to binary <<
*** Error code 1 ~~~~~~~~~~~~~~~~~~~~~~~~~~
what's wrong?did I lose any headers or anything else?
Thanks
Yong
--
___________________________________________________
Play 100s of games for FREE! http://games.mail.com/
More information about the freebsd-drivers
mailing list