[i2c] i2c-dev i2c_smbus_read_i2c_block_data update

Mark M. Hoffman mhoffman at lightlink.com
Sun May 27 18:40:26 CEST 2007


Hi Jean:

* Jean Delvare <khali at linux-fr.org> [2007-05-23 21:43:25 +0200]:
> On Tue, 15 May 2007 14:48:07 +0200, Jean Delvare wrote:
> > On Sat, 12 May 2007 12:32:49 +0200, Jean Delvare wrote:
> > > Here comes the user-space patch completing the
> > > i2c_smbus_read_i2c_block_data kernel patch I sent yesterday. It finally
> > > makes it possible to do I2C block reads from user-space with size less
> > > than 32 bytes.
> > > 
> > > I'm not too sure about the python changes, I'm not even sure the
> > > original code was correct and I can't test it. Mark, can you please
> > > take a look and comment?
> > 
> > Here is an updated version that matches the kernel patch update I just
> > posted. Note that "i2cdump i" would then only work with kernels >=
> > 2.6.23, which is not very wise, so maybe we want to delay this change
> > (after all, the new kernel patch guarantees binary compatibility) or do
> > it differently, maybe falling back to the old block read if the new one
> > fails? Opinions welcome.
> 
> I came up with something better. When the block read length is 32, as
> was always the case before, we use the old code (6). Only when the block
> read length is less than 32, we use the new code (8). This means that
> the call will only fail if the kernel is old (< 2.6.23) and the length
> is less than 32, i.e. if the kernel is really not able to fulfill the
> request. This is the approach which gives the best binary compatibility
> in both directions. I tested an old and a new i2cdump with an old and a
> new kernel, all combinations work.

I like it.

> The only drawback is that it doesn't encourage the use of the new code.
> But I guess we can't have it all. Comments anyone? Mark, your feedback
> on the py-smbus changes is still needed.

I suggest a couple slight modifications... 1) make the len arg an optional one
defaulting to 32, so that existing Python code need not be modified at all, and
2) add a couple #defines to be sure it builds in all possible environments.

I couldn't test it fully; I don't have a bus w/ I2C_SMBUS_I2C_BLOCK_DATA at the
moment.  Here's the patch...

Index: smbusmodule.c
===================================================================
--- smbusmodule.c	(revision 4412)
+++ smbusmodule.c	(working copy)
@@ -1,6 +1,6 @@
 /*
  * smbusmodule.c - Python bindings for Linux SMBus access through i2c-dev
- * Copyright (C) 2005,2006 Mark M. Hoffman <mhoffman at lightlink.com>
+ * Copyright (C) 2005-2007 Mark M. Hoffman <mhoffman at lightlink.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -23,6 +23,15 @@
 #include <fcntl.h>
 #include <linux/i2c-dev.h>
 
+/*
+** These are required to build this module against Linux older than 2.6.23.
+*/
+#ifndef I2C_SMBUS_I2C_BLOCK_BROKEN
+#undef I2C_SMBUS_I2C_BLOCK_DATA
+#define I2C_SMBUS_I2C_BLOCK_BROKEN	6
+#define I2C_SMBUS_I2C_BLOCK_DATA	8
+#endif
+
 PyDoc_STRVAR(SMBus_module_doc,
 	"This module defines an object type that allows SMBus transactions\n"
 	"on Linux hosts.  The host kernel must have I2C support, I2C device\n"
@@ -486,22 +495,25 @@
 }
 
 PyDoc_STRVAR(SMBus_read_i2c_block_data_doc,
-	"read_i2c_block_data(addr, cmd) -> results\n\n"
+	"read_i2c_block_data(addr, cmd, len=32) -> results\n\n"
 	"Perform I2C Block Read transaction.\n");
 
 static PyObject *
 SMBus_read_i2c_block_data(SMBus *self, PyObject *args)
 {
-	int addr, cmd;
+	int addr, cmd, len=32;
 	union i2c_smbus_data data;
 
-	if (!PyArg_ParseTuple(args, "ii:read_i2c_block_data", &addr, &cmd))
+	if (!PyArg_ParseTuple(args, "ii|i:read_i2c_block_data", &addr, &cmd,
+			&len))
 		return NULL;
 
 	SMBus_SET_ADDR(self, addr);
 
+	data.block[0] = len;
 	/* save a bit of code by calling the access function directly */
 	if (i2c_smbus_access(self->fd, I2C_SMBUS_READ, (__u8)cmd,
+				len = 32 ? I2C_SMBUS_I2C_BLOCK_BROKEN:
 				I2C_SMBUS_I2C_BLOCK_DATA, &data)) {
 		PyErr_SetFromErrno(PyExc_IOError);
 		return NULL;
@@ -529,7 +541,7 @@
 
 	/* save a bit of code by calling the access function directly */
 	if (i2c_smbus_access(self->fd, I2C_SMBUS_WRITE, (__u8)cmd,
-				I2C_SMBUS_I2C_BLOCK_DATA, &data)) {
+				I2C_SMBUS_I2C_BLOCK_BROKEN, &data)) {
 		PyErr_SetFromErrno(PyExc_IOError);
 		return NULL;
 	}
-- 
Mark M. Hoffman
mhoffman at lightlink.com




More information about the i2c mailing list