This file documents how to handle the callback function that returns the
information displayed in a (non-/proc/sys) /proc file.

For kernels before 2.1.29, you have to declare a proc_dir_entry, with
in the get_info field the procedure handler. For kernels 2.1.29 and later,
you can use the create_proc_entry function and assign a new value (the
procedure handler address) to the read_proc field:



#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)
  static int read_bus_i2c(char *buf, char **start, off_t offset, int len,
                          int unused);
  static struct proc_dir_entry proc_bus_i2c_dir =
    {
      /* low_ino */       0,     /* Set by proc_register_dynamic */
      /* namelen */       3,     /* The length of the name field */
      /* name */          "i2c",
      /* mode */          S_IRUGO | S_IFREG,
      /* nlink */         1,     
      /* uid */           0,
      /* gid */           0,
      /* size */          0,
      /* ops */           NULL,
      /* get_info */      &read_bus_i2c
    };
  
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)
  static int read_bus_i2c(char *buf, char **start, off_t offset, int len,
                             int *eof , void *private);
#endif


  /* This code fragment is part of the initialization code. You should do
     several safety checks, like whether create_proc_entry does not return
     NULL. */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)
  proc_register_dynamic(&proc_root, &proc_bus_i2c_dir);
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)
  proc_bus_i2c = create_proc_entry("i2c",0,proc_root);
  proc_bus_i2c->read_proc = &read_bus_i2c;
#endif



Now for the function itself.

   LINUX KERNEL 2.0.x, and 2.1.x upto 2.1.28
   =========================================
   This function is known as the get_info function.

   int get_info(char *buf, char **start, off_t offset, int len, int unused);

   (INPUT)
     buf: A kernel-space buffer where we can put the information.
     len: The buffer length (we have a bit of slack here: if we write 
          'a little' beyond this, things will still work out)
   (OUTPUT)
     *buf: The complete contents of the /proc file, starting at the
           beginning.
     return value: the number of chars written to buf.

   This is all you have to do if all information fits in the buffer (it is 
   about 3K in length). You can safely ignore offset and start in this case.

   If your /proc entry gets larger, you have to do a bit more work.

   (INPUT)
     buf: See above
     len: see above
     offset: The offset from the beginning of the /proc file where the user
             wants to start reading
   (OUTPUT)
     *buf: A part of the /proc file. The requested information does not
           have to start at the beginning.
     start: this is the place within buf where the information starts (ie.
            you must use offset to compute this!).
     return value: The number of valid characters written to buf. Begin
                   counting at start, not at buf!

   You do not have to worry about not the whole information being in buf.
   Another call will be done (with a higher offset value) if more is
   needed.


   LINUX KERNEL 2.1.x, from 2.1.29 upwards
   =======================================

   This function is known as the read_proc function.

   int read_proc(char *buf, char **start, off_t offset, int len, int *eof,
                 void *private);
   (INPUT)
     buf: A kernel-space buffer where we can put the information.
     len: The buffer length (we have a bit of slack here: if we write 
          'a little' beyond this, things will still work out)
   (OUTPUT)
     *buf: The complete contents of the /proc file, starting at the
           beginning.
     eof: You can set this to true (anything but 0) to indicate we have
          reached the end of the file with this read. Not strictly
          necessary, but it is more efficient (else this function may be
          called again).
     return value: The number of valid characters written to buf. Begin
                   counting at start, not at buf! 

   If your /proc entry gets larger, you have to do a bit more work.

   (INPUT)
     buf: See above
     len: See above
     offset: The offset from the beginning of the /proc file where the user
             wants to start reading
   (OUTPUT)
     *buf: A part of the /proc file. The requested information does not
           have to start at the beginning.
     eof: See above
     start: this is the place within buf where the information starts (ie.
            you must use offset to compute this!).
     return value: The number of valid characters written to buf.

   You do not have to worry about not the whole information being in buf.
   Another call will be done (with a higher offset value) if more is
   needed. Ignore private.

   A third way to do this:

   (INPUT)
     buf: See above
     len: See above
     offset: The offset from the beginning of the /proc file where the user
             wants to start reading
   (OUTPUT)
     *buf: A part of the /proc file, with the requested information starting
           at the beginning.
     eof: See above
     start: (long)start is added to the offset pointer after reading. This
            allows you to play tricks with the file offset, independent of
            the number of read bytes.
     return value: the number of chars written to buf.
   

This document was written by Frodo Looijaard <frodol@dds.nl>. I do not
accept any responsibility for omissions or errors, but you are free to
drop me a note if something is wrong or if you miss something.
