patch-2.3.34 linux/Documentation/i2c/writing-clients

Next file: linux/Documentation/kernel-parameters.txt
Previous file: linux/Documentation/i2c/ten-bit-addresses
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.33/linux/Documentation/i2c/writing-clients linux/Documentation/i2c/writing-clients
@@ -0,0 +1,862 @@
+This is a small guide for those who want to write kernel drivers for I2C
+or SMBus devices.
+
+To set up a driver, you need to do several things. Some are optional, and
+some things can be done slightly or completely different. Use this as a
+guide, not as a rule book!
+
+
+General remarks
+===============
+
+Try to keep the kernel namespace as clean as possible. The best way to
+do this is to use a unique prefix for all global symbols. This is 
+especially important for exported symbols, but it is a good idea to do
+it for non-exported symbols too. We will use the prefix `foo_' in this
+tutorial, and `FOO_' for preprocessor variables.
+
+
+The driver structure
+====================
+
+Usually, you will implement a single driver structure, and instantiate
+all clients from it. Remember, a driver structure contains general access 
+routines, a client structure specific information like the actual I2C
+address.
+
+  struct i2c_driver foo_driver
+  {  
+    /* name           */  "Foo version 2.3 and later driver",
+    /* id             */  I2C_DRIVERID_FOO,
+    /* flags          */  I2C_DF_NOTIFY,
+    /* attach_adapter */  &foo_attach_adapter,
+    /* detach_client  */  &foo_detach_client,
+    /* command        */  &foo_command,   /* May be NULL */
+    /* inc_use        */  &foo_inc_use,   /* May be NULL */
+    /* dec_use        */  &foo_dev_use    /* May be NULL */
+  }
+ 
+The name can be choosen freely, and may be upto 40 characters long. Please
+use something descriptive here.
+
+The id should be a unique ID. The range 0xf000 to 0xffff is reserved for
+local use, and you can use one of those until you start distributing the
+driver. Before you do that, contact the i2c authors to get your own ID(s).
+
+Don't worry about the flags field; just put I2C_DF_NOTIFY into it. This
+means that your driver will be notified when new adapters are found.
+This is almost always what you want.
+
+All other fields are for call-back functions which will be explained 
+below.
+
+
+Module usage count
+==================
+
+If your driver can also be compiled as a module, there are moments at 
+which the module can not be removed from memory. For example, when you
+are doing a lengthy transaction, or when you create a /proc directory,
+and some process has entered that directory (this last case is the
+main reason why these call-backs were introduced).
+
+To increase or decrease the module usage count, you can use the
+MOD_{INC,DEC}_USE_COUNT macros. They must be called from the module
+which needs to get its usage count changed; that is why each driver
+module has to implement its own callback.
+
+  void foo_inc_use (struct i2c_client *client)
+  {
+  #ifdef MODULE
+    MOD_INC_USE_COUNT;
+  #endif
+  }
+
+  void foo_dec_use (struct i2c_client *client)
+  {
+  #ifdef MODULE
+    MOD_DEC_USE_COUNT;
+  #endif
+  }
+
+Do not call these call-back functions directly; instead, use one of the
+following functions defined in i2c.h:
+  void i2c_inc_use_client(struct i2c_client *);
+  void i2c_dec_use_client(struct i2c_client *);
+
+You should *not* increase the module count just because a device is
+detected and a client created. This would make it impossible to remove
+an adapter driver! 
+
+
+Extra client data
+=================
+
+The client structure has a special `data' field that can point to any
+structure at all. You can use this to keep client-specific data. You
+do not always need this, but especially for `sensors' drivers, it can
+be very useful.
+
+An example structure is below.
+
+  struct foo_data {
+    struct semaphore lock; /* For ISA access in `sensors' drivers. */
+    int sysctl_id;         /* To keep the /proc directory entry for 
+                              `sensors' drivers. */
+    enum chips type;       /* To keep the chips type for `sensors' drivers. */
+   
+    /* Because the i2c bus is slow, it is often useful to cache the read
+       information of a chip for some time (for example, 1 or 2 seconds).
+       It depends of course on the device whether this is really worthwhile
+       or even sensible. */
+    struct semaphore update_lock; /* When we are reading lots of information,
+                                     another process should not update the
+                                     below information */
+    char valid;                   /* != 0 if the following fields are valid. */
+    unsigned long last_updated;   /* In jiffies */
+    /* Add the read information here too */
+  };
+
+
+Accessing the client
+====================
+
+Let's say we have a valid client structure. At some time, we will need
+to gather information from the client, or write new information to the
+client. How we will export this information to user-space is less 
+important at this moment (perhaps we do not need to do this at all for
+some obscure clients). But we need generic reading and writing routines.
+
+I have found it useful to define foo_read and foo_write function for this.
+For some cases, it will be easier to call the i2c functions directly,
+but many chips have some kind of register-value idea that can easily
+be encapsulated. Also, some chips have both ISA and I2C interfaces, and
+it useful to abstract from this (only for `sensors' drivers).
+
+The below functions are simple examples, and should not be copied
+literally.
+
+  int foo_read_value(struct i2c_client *client, u8 reg)
+  {
+    if (reg < 0x10) /* byte-sized register */
+      return i2c_smbus_read_byte_data(client,reg);
+    else /* word-sized register */
+      return i2c_smbus_read_word_data(client,reg);
+  }
+
+  int foo_write_value(struct i2c_client *client, u8 reg, u16 value)
+  {
+    if (reg == 0x10) /* Impossible to write - driver error! */ {
+      return -1;
+    else if (reg < 0x10) /* byte-sized register */
+      return i2c_smbus_write_byte_data(client,reg,value);
+    else /* word-sized register */
+      return i2c_smbus_write_word_data(client,reg,value);
+  }
+
+For sensors code, you may have to cope with ISA registers too. Something
+like the below often works. Note the locking! 
+
+  int foo_read_value(struct i2c_client *client, u8 reg)
+  {
+    int res;
+    if (i2c_is_isa_client(client)) {
+      down(&(((struct foo_data *) (client->data)) -> lock));
+      outb_p(reg,client->addr + FOO_ADDR_REG_OFFSET);
+      res = inb_p(client->addr + FOO_DATA_REG_OFFSET);
+      up(&(((struct foo_data *) (client->data)) -> lock));
+      return res;
+    } else
+      return i2c_smbus_read_byte_data(client,reg);
+  }
+
+Writing is done the same way.
+
+
+Probing and attaching
+=====================
+
+Most i2c devices can be present on several i2c addresses; for some this
+is determined in hardware (by soldering some chip pins to Vcc or Ground),
+for others this can be changed in software (by writing to specific client
+registers). Some devices are usually on a specific address, but not always;
+and some are even more tricky. So you will probably need to scan several
+i2c addresses for your clients, and do some sort of detection to see
+whether it is actually a device supported by your driver.
+
+To give the user a maximum of possibilities, some default module parameters
+are defined to help determine what addresses are scanned. Several macros
+are defined in i2c.h to help you support them, as well as a generic
+detection algorithm.
+
+You do not have to use this parameter interface; but don't try to use
+function i2c_probe() (or sensors_detect()) if you don't.
+
+NOTE: If you want to write a `sensors' driver, the interface is slightly
+      different! See below.
+
+
+
+Probing classes (i2c)
+---------------------
+
+All parameters are given as lists of unsigned 16-bit integers. Lists are
+terminated by I2C_CLIENT_END.
+The following lists are used internally:
+
+  normal_i2c: filled in by the module writer. 
+     A list of I2C addresses which should normally be examined.
+   normal_i2c_range: filled in by the module writer.
+     A list of pairs of I2C addresses, each pair being an inclusive range of
+     addresses which should normally be examined.
+   probe: insmod parameter. 
+     A list of pairs. The first value is a bus number (-1 for any I2C bus), 
+     the second is the address. These addresses are also probed, as if they 
+     were in the 'normal' list.
+   probe_range: insmod parameter. 
+     A list of triples. The first value is a bus number (-1 for any I2C bus), 
+     the second and third are addresses.  These form an inclusive range of 
+     addresses that are also probed, as if they were in the 'normal' list.
+   ignore: insmod parameter.
+     A list of pairs. The first value is a bus number (-1 for any I2C bus), 
+     the second is the I2C address. These addresses are never probed. 
+     This parameter overrules 'normal' and 'probe', but not the 'force' lists.
+   ignore_range: insmod parameter. 
+     A list of triples. The first value is a bus number (-1 for any I2C bus), 
+     the second and third are addresses. These form an inclusive range of 
+     I2C addresses that are never probed.
+     This parameter overrules 'normal' and 'probe', but not the 'force' lists.
+   force: insmod parameter. 
+     A list of pairs. The first value is a bus number (-1 for any I2C bus),
+     the second is the I2C address. A device is blindly assumed to be on
+     the given address, no probing is done. 
+
+Fortunately, as a module writer, you just have to define the `normal' 
+and/or `normal_range' parameters. The complete declaration could look
+like this:
+
+  /* Scan 0x20 to 0x2f, 0x37, and 0x40 to 0x4f */
+  static unsigned short normal_i2c[] = { 0x37,I2C_CLIENT_END }; 
+  static unsigned short normal_i2c_range[] = { 0x20, 0x2f, 0x40, 0x4f, 
+                                               I2C_CLIENT_END };
+
+  /* Magic definition of all other variables and things */
+  I2C_CLIENT_INSMOD;
+
+Note that you *have* to call the two defined variables `normal_i2c' and
+`normal_i2c_range', without any prefix!
+
+
+Probing classes (sensors)
+-------------------------
+
+If you write a `sensors' driver, you use a slightly different interface.
+As well as I2C addresses, we have to cope with ISA addresses. Also, we
+use a enum of chip types. Don't forget to include `sensors.h'.
+
+The following lists are used internally. They are all lists of integers.
+
+   normal_i2c: filled in by the module writer. Terminated by SENSORS_I2C_END.
+     A list of I2C addresses which should normally be examined.
+   normal_i2c_range: filled in by the module writer. Terminated by 
+     SENSORS_I2C_END
+     A list of pairs of I2C addresses, each pair being an inclusive range of
+     addresses which should normally be examined.
+   normal_isa: filled in by the module writer. Terminated by SENSORS_ISA_END.
+     A list of ISA addresses which should normally be examined.
+   normal_isa_range: filled in by the module writer. Terminated by 
+     SENSORS_ISA_END
+     A list of triples. The first two elements are ISA addresses, being an
+     range of addresses which should normally be examined. The third is the
+     modulo parameter: only addresses which are 0 module this value relative
+     to the first address of the range are actually considered.
+   probe: insmod parameter. Initialize this list with SENSORS_I2C_END values.
+     A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
+     the ISA bus, -1 for any I2C bus), the second is the address. These
+     addresses are also probed, as if they were in the 'normal' list.
+   probe_range: insmod parameter. Initialize this list with SENSORS_I2C_END 
+     values.
+     A list of triples. The first value is a bus number (SENSORS_ISA_BUS for
+     the ISA bus, -1 for any I2C bus), the second and third are addresses. 
+     These form an inclusive range of addresses that are also probed, as
+     if they were in the 'normal' list.
+   ignore: insmod parameter. Initialize this list with SENSORS_I2C_END values.
+     A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
+     the ISA bus, -1 for any I2C bus), the second is the I2C address. These
+     addresses are never probed. This parameter overrules 'normal' and 
+     'probe', but not the 'force' lists.
+   ignore_range: insmod parameter. Initialize this list with SENSORS_I2C_END 
+      values.
+     A list of triples. The first value is a bus number (SENSORS_ISA_BUS for
+     the ISA bus, -1 for any I2C bus), the second and third are addresses. 
+     These form an inclusive range of I2C addresses that are never probed.
+     This parameter overrules 'normal' and 'probe', but not the 'force' lists.
+
+Also used is a list of pointers to sensors_force_data structures:
+   force_data: insmod parameters. A list, ending with an element of which
+     the force field is NULL.
+     Each element contains the type of chip and a list of pairs.
+     The first value is a bus number (SENSORS_ISA_BUS for the ISA bus, 
+     -1 for any I2C bus), the second is the address. 
+     These are automatically translated to insmod variables of the form
+     force_foo.
+
+So we have a generic insmod variabled `force', and chip-specific variables
+`force_CHIPNAME'.
+
+Fortunately, as a module writer, you just have to define the `normal' 
+and/or `normal_range' parameters, and define what chip names are used. 
+The complete declaration could look like this:
+  /* Scan i2c addresses 0x20 to 0x2f, 0x37, and 0x40 to 0x4f
+  static unsigned short normal_i2c[] = {0x37,SENSORS_I2C_END};
+  static unsigned short normal_i2c_range[] = {0x20,0x2f,0x40,0x4f,
+                                              SENSORS_I2C_END};
+  /* Scan ISA address 0x290 */
+  static unsigned int normal_isa[] = {0x0290,SENSORS_ISA_END};
+  static unsigned int normal_isa_range[] = {SENSORS_ISA_END};
+
+  /* Define chips foo and bar, as well as all module parameters and things */
+  SENSORS_INSMOD_2(foo,bar);
+
+If you have one chip, you use macro SENSORS_INSMOD_1(chip), if you have 2
+you use macro SENSORS_INSMOD_2(chip1,chip2), etc. If you do not want to
+bother with chip types, you can use SENSORS_INSMOD_0.
+
+A enum is automatically defined as follows:
+  enum chips { any_chip, chip1, chip2, ... }
+
+
+Attaching to an adapter
+-----------------------
+
+Whenever a new adapter is inserted, or for all adapters if the driver is
+being registered, the callback attach_adapter() is called. Now is the
+time to determine what devices are present on the adapter, and to register
+a client for each of them.
+
+The attach_adapter callback is really easy: we just call the generic
+detection function. This function will scan the bus for us, using the
+information as defined in the lists explained above. If a device is
+detected at a specific address, another callback is called.
+
+  int foo_attach_adapter(struct i2c_adapter *adapter)
+  {
+    return i2c_probe(adapter,&addr_data,&foo_detect_client);
+  }
+
+For `sensors' drivers, use the sensors_detect function instead:
+  
+  int foo_attach_adapter(struct i2c_adapter *adapter)
+  { 
+    return sensors_detect(adapter,&addr_data,&foo_detect_client);
+  }
+
+Remember, structure `addr_data' is defined by the macros explained above,
+so you do not have to define it yourself.
+
+The i2c_probe or sensors_detect function will call the foo_detect_client
+function only for those i2c addresses that actually have a device on
+them (unless a `force' parameter was used).
+
+
+The detect client function
+--------------------------
+
+The detect client function is called by i2c_probe or sensors_detect.
+The `kind' parameter contains 0 if this call is due to a `force'
+parameter, and 0 otherwise (for sensors_detect, it contains 0 if
+this call is due to the generic `force' parameter, and the chip type
+number if it is due to a specific `force' parameter).
+
+Below, some things are only needed if this is a `sensors' driver. Those
+parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */
+markers. 
+
+This function should only return an error (any value != 0) if there is
+some reason why no more detection should be done anymore. If the
+detection just fails for this address, return 0.
+
+For now, you can ignore the `flags' parameter. It is there for future use.
+
+  /* Unique ID allocation */
+  static int foo_id = 0;
+
+  int foo_detect_client(struct i2c_adapter *adapter, int address, 
+                        unsigned short flags, int kind)
+  {
+    int err = 0;
+    int i;
+    struct i2c_client *new_client;
+    struct foo_data *data;
+    const char *client_name = ""; /* For non-`sensors' drivers, put the real
+                                     name here! */
+   
+    /* Let's see whether this adapter can support what we need.
+       Please substitute the things you need here! 
+       For `sensors' drivers, add `! is_isa &&' to the if statement */
+    if (i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA |
+                                        I2C_FUNC_SMBUS_WRITE_BYTE))
+       goto ERROR0;
+
+    /* SENSORS ONLY START */
+    const char *type_name = "";
+    int is_isa = i2c_is_isa_adapter(adapter);
+
+    if (is_isa) {
+
+      /* If this client can't be on the ISA bus at all, we can stop now
+         (call `goto ERROR0'). But for kicks, we will assume it is all
+         right. */
+
+      /* Discard immediately if this ISA range is already used */
+      if (check_region(address,FOO_EXTENT))
+        goto ERROR0;
+
+      /* Probe whether there is anything on this address.
+         Some example code is below, but you will have to adapt this
+         for your own driver */
+
+      if (kind < 0) /* Only if no force parameter was used */ {
+        /* We may need long timeouts at least for some chips. */
+        #define REALLY_SLOW_IO
+        i = inb_p(address + 1);
+        if (inb_p(address + 2) != i)
+          goto ERROR0;
+        if (inb_p(address + 3) != i)
+          goto ERROR0;
+        if (inb_p(address + 7) != i)
+          goto ERROR0;
+        #undef REALLY_SLOW_IO
+
+        /* Let's just hope nothing breaks here */
+        i = inb_p(address + 5) & 0x7f;
+        outb_p(~i & 0x7f,address+5);
+        if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
+          outb_p(i,address+5);
+          return 0;
+        }
+      }
+    }
+
+    /* SENSORS ONLY END */
+
+    /* OK. For now, we presume we have a valid client. We now create the
+       client structure, even though we cannot fill it completely yet.
+       But it allows us to access several i2c functions safely */
+    
+    /* Note that we reserve some space for foo_data too. If you don't
+       need it, remove it. We do it here to help to lessen memory
+       fragmentation. */
+    if (! (new_client = kmalloc(sizeof(struct i2c_client)) + 
+                                sizeof(struct foo_data),
+                                GFP_KERNEL)) {
+      err = -ENOMEM;
+      goto ERROR0;
+    }
+
+    /* This is tricky, but it will set the data to the right value. */
+    client->data = new_client + 1;
+    data = (struct foo_data *) (client->data);
+
+    new_client->addr = address;
+    new_client->data = data;
+    new_client->adapter = adapter;
+    new_client->driver = &foo_driver;
+    new_client->flags = 0;
+
+    /* Now, we do the remaining detection. If no `force' parameter is used. */
+
+    /* First, the generic detection (if any), that is skipped if any force
+       parameter was used. */
+    if (kind < 0) {
+      /* The below is of course bogus */
+      if (foo_read(new_client,FOO_REG_GENERIC) != FOO_GENERIC_VALUE)
+         goto ERROR1;
+    }
+
+    /* SENSORS ONLY START */
+
+    /* Next, specific detection. This is especially important for `sensors'
+       devices. */
+
+    /* Determine the chip type. Not needed if a `force_CHIPTYPE' parameter
+       was used. */
+    if (kind <= 0) {
+      i = foo_read(new_client,FOO_REG_CHIPTYPE);
+      if (i == FOO_TYPE_1) 
+        kind = chip1; /* As defined in the enum */
+      else if (i == FOO_TYPE_2)
+        kind = chip2;
+      else {
+        printk("foo: Ignoring 'force' parameter for unknown chip at "
+               "adapter %d, address 0x%02x\n",i2c_adapter_id(adapter),address);
+        goto ERROR1;
+      }
+    }
+
+    /* Now set the type and chip names */
+    if (kind == chip1) {
+      type_name = "chip1"; /* For /proc entry */
+      client_name = "CHIP 1";
+    } else if (kind == chip2) {
+      type_name = "chip2"; /* For /proc entry */
+      client_name = "CHIP 2";
+    }
+   
+    /* Reserve the ISA region */
+    if (is_isa)
+      request_region(address,FOO_EXTENT,type_name);
+
+    /* SENSORS ONLY END */
+
+    /* Fill in the remaining client fields. */
+    strcpy(new_client->name,client_name);
+
+    /* SENSORS ONLY BEGIN */
+    data->type = kind;
+    /* SENSORS ONLY END */
+
+    new_client->id = foo_id++; /* Automatically unique */
+    data->valid = 0; /* Only if you use this field */
+    init_MUTEX(&data->update_lock); /* Only if you use this field */
+
+    /* Any other initializations in data must be done here too. */
+
+    /* Tell the i2c layer a new client has arrived */
+    if ((err = i2c_attach_client(new_client)))
+      goto ERROR3;
+
+    /* SENSORS ONLY BEGIN */
+    /* Register a new directory entry with module sensors. See below for
+       the `template' structure. */
+    if ((i = sensors_register_entry(new_client, type_name,
+                                    foo_dir_table_template,THIS_MODULE)) < 0) {
+      err = i;
+      goto ERROR4;
+    }
+    data->sysctl_id = i;
+
+    /* SENSORS ONLY END */
+
+    /* This function can write default values to the client registers, if
+       needed. */
+    foo_init_client(new_client);
+    return 0;
+
+    /* OK, this is not exactly good programming practice, usually. But it is
+       very code-efficient in this case. */
+
+    ERROR4:
+      i2c_detach_client(new_client);
+    ERROR3:
+    ERROR2:
+    /* SENSORS ONLY START */
+      if (is_isa)
+        release_region(address,FOO_EXTENT);
+    /* SENSORS ONLY END */
+    ERROR1:
+      kfree(new_client);
+    ERROR0:
+      return err;
+  }
+
+
+Removing the client
+===================
+
+The detach_client call back function is called when a client should be
+removed. It may actually fail, but only when panicking. This code is
+much simpler than the attachment code, fortunately!
+
+  int foo_detach_client(struct i2c_client *client)
+  {
+    int err,i;
+
+    /* SENSORS ONLY START */
+    /* Deregister with the `sensors' module. */
+    sensors_deregister_entry(((struct lm78_data *)(client->data))->sysctl_id);
+    /* SENSORS ONLY END */
+
+    /* Try to detach the client from i2c space */
+    if ((err = i2c_detach_client(client))) {
+      printk("foo.o: Client deregistration failed, client not detached.\n");
+      return err;
+    }
+
+    /* SENSORS ONLY START */
+    if i2c_is_isa_client(client)
+      release_region(client->addr,LM78_EXTENT);
+    /* SENSORS ONLY END */
+
+    kfree(client); /* Frees client data too, if allocated at the same time */
+    return 0;
+  }
+
+
+Initializing the module or kernel
+=================================
+
+When the kernel is booted, or when your foo driver module is inserted, 
+you have to do some initializing. Fortunately, just attaching (registering)
+the driver module is usually enough.
+
+  /* Keep track of how far we got in the initialization process. If several
+     things have to initialized, and we fail halfway, only those things
+     have to be cleaned up! */
+  static int __initdata foo_initialized = 0;
+
+  int __init foo_init(void)
+  {
+    int res;
+    printk("foo version %s (%s)\n",FOO_VERSION,FOO_DATE);
+    
+    if ((res = i2c_add_driver(&foo_driver))) {
+      printk("foo: Driver registration failed, module not inserted.\n");
+      foo_cleanup();
+      return res;
+    }
+    foo_initialized ++;
+    return 0;
+  }
+
+  int __init foo_cleanup(void)
+  {
+    int res;
+    if (foo_initialized == 1) {
+      if ((res = i2c_del_driver(&foo_driver))) {
+        printk("foo: Driver registration failed, module not removed.\n");
+        return res;
+      }
+      foo_initialized --;
+    }
+    return 0;
+  }
+
+  #ifdef MODULE
+
+  /* Substitute your own name and email address */
+  MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"
+  MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices");
+
+  int init_module(void)
+  {
+    return foo_init();
+  }
+
+  int cleanup_module(void)
+  {
+    return foo_cleanup();
+  }
+
+  #endif /* def MODULE */
+
+Note that some functions are marked by `__init', and some data structures
+by `__init_data'. If this driver is compiled as part of the kernel (instead
+of as a module), those functions and structures can be removed after
+kernel booting is completed.
+
+Command function
+================
+
+A generic ioctl-like function call back is supported. You will seldomly
+need this. You may even set it to NULL.
+
+  /* No commands defined */
+  int foo_command(struct i2c_client *client, unsigned int cmd, void *arg)
+  {
+    return 0;
+  }
+
+You should never directly call this function, but instead use the 
+general function below:
+
+  extern int i2c_control(struct i2c_client *,unsigned int, unsigned long);
+
+
+
+Sending and receiving
+=====================
+
+If you want to communicate with your device, there are several functions
+to do this. You can find all of them in i2c.h.
+
+If you can choose between plain i2c communication and SMBus level
+communication, please use the last. All adapters understand SMBus level
+commands, but only some of them understand plain i2c!
+
+
+Plain i2c communication
+-----------------------
+
+  extern int i2c_master_send(struct i2c_client *,const char* ,int);
+  extern int i2c_master_recv(struct i2c_client *,char* ,int);
+
+These routines read and write some bytes from/to a client. The client
+contains the i2c address, so you do not have to include it. The second
+parameter contains the bytes the read/write, the third the length of the
+buffer. Returned is the actual number of bytes read/written.
+  
+  extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+                          int num);
+
+This sends a series of messages. Each message can be a read or write,
+and they can be mixed in any way. The transactions are combined: no
+stop bit is sent between transaction. The i2c_msg structure contains
+for each message the client address, the number of bytes of the message
+and the message data itself.
+
+You can read the file `i2c-protocol' for more information about the
+actual i2c protocol.
+
+
+SMBus communication
+-------------------
+
+  extern s32 i2c_smbus_xfer (struct i2c_adapter * adapter, u16 addr, 
+                             unsigned short flags,
+                             char read_write, u8 command, int size,
+                             union i2c_smbus_data * data);
+
+  This is the generic SMBus function. All functions below are implemented
+  in terms of it. Never use this function directly!
+
+
+  extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value);
+  extern s32 i2c_smbus_read_byte(struct i2c_client * client);
+  extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value);
+  extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command);
+  extern s32 i2c_smbus_write_byte_data(struct i2c_client * client,
+                                       u8 command, u8 value);
+  extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command);
+  extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
+                                       u8 command, u16 value);
+  extern s32 i2c_smbus_process_call(struct i2c_client * client,
+                                    u8 command, u16 value);
+  extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
+                                       u8 command, u8 *values);
+  extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
+                                        u8 command, u8 length,
+                                        u8 *values);
+
+All these tranactions return -1 on failure. The 'write' transactions 
+return 0 on success; the 'read' transactions return the read value, except 
+for read_block, which returns the number of values read. The block buffers 
+need not be longer than 32 bytes.
+
+You can read the file `smbus-protocol' for more information about the
+actual SMBus protocol.
+
+
+General purpose routines
+========================
+
+Below all general purpose routines are listed, that were not mentioned
+before.
+
+  /* This call returns a unique low identifier for each registered adapter,
+   * or -1 if the adapter was not regisitered.
+   */
+  extern int i2c_adapter_id(struct i2c_adapter *adap);
+
+
+The sensors sysctl/proc interface
+=================================
+
+This section only applies if you write `sensors' drivers.
+
+Each sensors driver creates a directory in /proc/sys/dev/sensors for each
+registered client. The directory is called something like foo-i2c-4-65.
+The sensors module helps you to do this as easily as possible.
+
+The template
+------------
+
+You will need to define a ctl_table template. This template will automatically
+be copied to a newly allocated structure and filled in where necessary when
+you call sensors_register_entry.
+
+First, I will give an example definition.
+  static ctl_table foo_dir_table_template[] = {
+    { FOO_SYSCTL_FUNC1, "func1", NULL, 0, 0644, NULL, &sensors_proc_real,
+      &sensors_sysctl_real,NULL,&foo_func },
+    { FOO_SYSCTL_FUNC2, "func2", NULL, 0, 0644, NULL, &sensors_proc_real,
+      &sensors_sysctl_real,NULL,&foo_func },
+    { FOO_SYSCTL_DATA, "data", NULL, 0, 0644, NULL, &sensors_proc_real,
+      &sensors_sysctl_real,NULL,&foo_data },
+    { 0 }
+  };
+
+In the above example, three entries are defined. They can either be
+accessed through the /proc interface, in the /proc/sys/dev/sensors/*
+directories, as files named func1, func2 and data, or alternatively 
+through the sysctl interface, in the appropriate table, with identifiers
+FOO_SYSCTL_FUNC1, FOO_SYSCTL_FUNC2 and FOO_SYSCTL_DATA.
+
+The third, sixth and ninth parameters should always be NULL, and the
+fourth should always be 0. The fifth is the mode of the /proc file;
+0644 is safe, as the file will be owned by root:root. 
+
+The seventh and eigth parameters should be &sensors_proc_real and
+&sensors_sysctl_real if you want to export lists of reals (scaled
+integers). You can also use your own function for them, as usual.
+Finally, the last parameter is the call-back to gather the data
+(see below) if you use the *_proc_real functions. 
+
+
+Gathering the data
+------------------
+
+The call back functions (foo_func and foo_data in the above example)
+can be called in several ways; the operation parameter determines
+what should be done:
+
+  * If operation == SENSORS_PROC_REAL_INFO, you must return the
+    magnitude (scaling) in nrels_mag;
+  * If operation == SENSORS_PROC_REAL_READ, you must read information
+    from the chip and return it in results. The number of integers
+    to display should be put in nrels_mag;
+  * If operation == SENSORS_PROC_REAL_WRITE, you must write the
+    supplied information to the chip. nrels_mag will contain the number
+    of integers, results the integers themselves.
+
+The *_proc_real functions will display the elements as reals for the
+/proc interface. If you set the magnitude to 2, and supply 345 for
+SENSORS_PROC_REAL_READ, it would display 3.45; and if the user would
+write 45.6 to the /proc file, it would be returned as 4560 for
+SENSORS_PROC_REAL_WRITE. A magnitude may even be negative!
+
+An example function:
+
+  /* FOO_FROM_REG and FOO_TO_REG translate between scaled values and
+     register values. Note the use of the read cache. */
+  void foo_in(struct i2c_client *client, int operation, int ctl_name, 
+              int *nrels_mag, long *results)
+  {
+    struct foo_data *data = client->data;
+    int nr = ctl_name - FOO_SYSCTL_FUNC1; /* reduce to 0 upwards */
+    
+    if (operation == SENSORS_PROC_REAL_INFO)
+      *nrels_mag = 2;
+    else if (operation == SENSORS_PROC_REAL_READ) {
+      /* Update the readings cache (if necessary) */
+      foo_update_client(client);
+      /* Get the readings from the cache */
+      results[0] = FOO_FROM_REG(data->foo_func_base[nr]);
+      results[1] = FOO_FROM_REG(data->foo_func_more[nr]);
+      results[2] = FOO_FROM_REG(data->foo_func_readonly[nr]);
+      *nrels_mag = 2;
+    } else if (operation == SENSORS_PROC_REAL_WRITE) {
+      if (*nrels_mag >= 1) {
+        /* Update the cache */
+        data->foo_base[nr] = FOO_TO_REG(results[0]);
+        /* Update the chip */
+        foo_write_value(client,FOO_REG_FUNC_BASE(nr),data->foo_base[nr]);
+      }
+      if (*nrels_mag >= 2) {
+        /* Update the cache */
+        data->foo_more[nr] = FOO_TO_REG(results[1]);
+        /* Update the chip */
+        foo_write_value(client,FOO_REG_FUNC_MORE(nr),data->foo_more[nr]);
+      }
+    }
+  }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)