implement a real variadic ioctl() handler

From: Ulrich Eckhardt (doomster_at_knuut.de)
Date: 03/27/04

  • Next message: Jan Panteltje: "Re: Playing .WAV files on Linux"
    Date: Sat, 27 Mar 2004 11:40:44 +0100
    
    

    Hello!

    I'm trying to implement a chardevice driver for communication with a
    realtime controller. My problem is that I call something like
      uint8_t buffer[size];
      ioftl( fd, READ_AREA, offset, size, buffer);

    However, at kernel level, I only have
      int ioctl_handler( ..., int cmd, unsigned long arg)
      { ... }

    With 'cmd' being READ_AREA and and 'arg' being the 'offset' parameter of
    the call above. All code that I found in Linux seems to either not use
    more than one argument or it uses a struct to wrap them and pass a pointer
    to it. For all practical purposes, ioctl thus decays from
      int ioctl( int fd, int cmd, ...);
    to just
      int ioctl( int fd, int cmd, void*);
    with the last parameter being optional, right?

    Now, I simply did the same as is done in other drivers, I wrapped it in a
    struct:
      typedef struct {
        unsigned offset;
        unsigned size;
        uint8_t buffer[256];//luckily I'll never need more...
      } rw_request_block;

    However, that way, I have lots of memcpy()ing going on, too much for my
    taste:

      // user level
      read( unsigned offset, unsigned count, uint8_t* buffer)
      {
        rw_request_block req = { offset, size };
        ioctl( fd, READ_AREA, &req);
        // copy result here ***
        memcpy( buffer, req.buffer, size);
      }

      // kernel level
      ioctl_handler( ..., unsigned long arg)
      {
        rw_request_block req;
        // copy from user level to kernel level ***
        copy_from_user( &req, (rw_request_block*)arg, sizeof req);
        
        // eval content, handle request, fill buffer
        
        // copy from user kernel to user level ***
        copy_to_user( (rw_request_block*)arg, &req, sizeof req);
      }

    Using a real variadic function, I believe I could prevent some copying, but
    it seems that's not possible. I'm happy with the solution as is, because
    it works and doesn't seem to be a bottleneck, but I don't find it really
    satisfactory.

    I'm happy for any comment.

    Uli


  • Next message: Jan Panteltje: "Re: Playing .WAV files on Linux"

    Relevant Pages