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