Re: w83781d i2c driver updated for 2.5.66 (without sysfs support)

Greg KH
2003-03-26T20:16:18Z

On Wed, Mar 26, 2003 at 08:40:58PM +0100, Jan Dittmer wrote:
> Martin Schlemmer wrote:
> >
> >I did look at the changes needed for sysfs, but this beast have
> >about 6 ctl_tables, and is hairy in general. I am not sure what
> >is the best way to do it for the different chips, so here is what
> >I have until I or somebody else can do the sysfs stuff.
> >
> I've just done this with the via686a driver. Saves about 100 lines of code.
>
> Comments?

<snip>

> +/* following are the sysfs callback functions */
> +static ssize_t show_in(struct device *dev, char *buf, int nr) {
> + struct i2c_client *client = to_i2c_client(dev);
> + struct via686a_data *data = i2c_get_clientdata(client);
> + via686a_update_client(client);
> +
> + return sprintf(buf,"%ld %ld %ld\n",
> + IN_FROM_REG(data->in_min[nr], nr),
> + IN_FROM_REG(data->in_max[nr], nr),
> + IN_FROM_REG(data->in[nr], nr) );
> +}

We should really split these multivalue files up into individual files,
as sysfs is for single value files. Makes parsing easier too.

Here's a patch for the lm75.c driver that does this. As we are going to
need a "generic" read and write for the "real" values that the i2c
drivers use, I added these files to the i2c-proc.c file.

Yes, i2c_read_real() doesn't really work just yet :)

Anyway, I think this is the direction we should be moving to. And what
is "temp_os" and "temp_hyst"? Should these files be named something a
bit more descriptive?

thanks,

greg k-h

diff -Nru a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c
--- a/drivers/i2c/chips/lm75.c Wed Mar 26 12:28:45 2003
+++ b/drivers/i2c/chips/lm75.c Wed Mar 26 12:28:45 2003
@@ -102,6 +102,49 @@

static int lm75_id = 0;

+#define show(value) \
+static ssize_t show_##value(struct device *dev, char *buf) \
+{ \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct lm75_data *data = i2c_get_clientdata(client); \
+ int temp; \
+ \
+ lm75_update_client(client); \
+ temp = TEMP_FROM_REG(data->value); \
+ return i2c_write_real(buf, temp, 1); \
+}
+show(temp);
+show(temp_os);
+show(temp_hyst);
+
+static ssize_t set_temp_os(struct device *dev, const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm75_data *data = i2c_get_clientdata(client);
+ int temp;
+
+ i2c_read_real(buf, &temp, 1);
+ data->temp_os = TEMP_TO_REG(temp);
+ lm75_write_value(client, LM75_REG_TEMP_OS, data->temp_os);
+ return count;
+}
+
+static ssize_t set_temp_hyst(struct device *dev, const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm75_data *data = i2c_get_clientdata(client);
+ int temp;
+
+ i2c_read_real(buf, &temp, 1);
+ data->temp_hyst = TEMP_TO_REG(temp);
+ lm75_write_value(client, LM75_REG_TEMP_HYST, data->temp_hyst);
+ return count;
+}
+
+static DEVICE_ATTR(temp, S_IRUGO, show_temp, NULL);
+static DEVICE_ATTR(temp_os, 0644, show_temp_os, set_temp_os);
+static DEVICE_ATTR(temp_hyst, 0644, show_temp_hyst, set_temp_hyst);
+
static int lm75_attach_adapter(struct i2c_adapter *adapter)
{
return i2c_detect(adapter, &addr_data, lm75_detect);
@@ -192,6 +235,10 @@
if ((err = i2c_attach_client(new_client)))
goto error3;

+ device_create_file(&new_client->dev, &dev_attr_temp);
+ device_create_file(&new_client->dev, &dev_attr_temp_os);
+ device_create_file(&new_client->dev, &dev_attr_temp_hyst);
+
/* Register a new directory entry with module sensors */
i = i2c_register_entry(new_client, type_name, lm75_dir_table_template);
if (i < 0) {
diff -Nru a/drivers/i2c/i2c-proc.c b/drivers/i2c/i2c-proc.c
--- a/drivers/i2c/i2c-proc.c Wed Mar 26 12:28:45 2003
+++ b/drivers/i2c/i2c-proc.c Wed Mar 26 12:28:45 2003
@@ -381,6 +381,14 @@
return ret;
}

+int i2c_read_real(const char *buf, int *real, int magnitude)
+{
+ char *temp;
+
+ *real = simple_strtoul(buf, &temp, 10);
+
+ return 0;
+}

/* nrels contains initially the maximum number of elements which can be
put in results, and finally the number of elements actually put there.
@@ -499,6 +507,29 @@
return 0;
}

+int i2c_write_real(char *buf, int real, int magnitude)
+{
+ char printfstr[12];
+ int mag;
+ int times;
+ int field_location;
+
+ mag = magnitude;
+ for (times = 1; mag-- > 0; times *= 10)
+ ;
+
+ if (real < 0) {
+ strcpy(printfstr, "-%ld.%0Xld");
+ field_location = 7;
+ } else {
+ strcpy(printfstr, "%ld.%0Xld");
+ field_location = 6;
+ }
+ printfstr[field_location] = magnitude + '0';
+ real = abs(real);
+ return sprintf(buf, printfstr, real / times, real % times);
+}
+
static int i2c_write_reals(int nrels, void *buffer, size_t *bufsize,
long *results, int magnitude)
{
@@ -724,6 +755,8 @@
EXPORT_SYMBOL(i2c_proc_real);
EXPORT_SYMBOL(i2c_sysctl_real);
EXPORT_SYMBOL(i2c_detect);
+EXPORT_SYMBOL(i2c_write_real);
+EXPORT_SYMBOL(i2c_read_real);

MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
MODULE_DESCRIPTION("i2c-proc driver");
diff -Nru a/include/linux/i2c-proc.h b/include/linux/i2c-proc.h
--- a/include/linux/i2c-proc.h Wed Mar 26 12:28:45 2003
+++ b/include/linux/i2c-proc.h Wed Mar 26 12:28:45 2003
@@ -410,5 +410,8 @@
char name[SENSORS_PREFIX_MAX + 13];
};

+extern int i2c_write_real(char *buf, int real, int magnitude);
+extern int i2c_read_real(const char *buf, int *real, int magnitude);
+
#endif /* def _LINUX_I2C_PROC_H */