[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