[RFC/PATCH 18/22] W1: cleanup family implementation

Dmitry Torokhov dtor_core at ameritech.net
Thu Apr 21 09:25:05 CEST 2005


W1: clean-up family implementation:
    - get rid of w1_family_ops and template attributes in w1_slave
      structure and have family drivers create necessary attributes
      themselves. There are too many different devices using 1-Wire
      interface and it is impossible to fit them all into single
      attribute model. If interface unification is needed it can be
      done by building cross-bus class hierarchy.
    - rename w1_smem to w1_sernum because devices are called Silicon
      serial numbers, they have address (ID) but don't have memory
      in regular sense.
    - rename w1_therm to w1_thermal.

Signed-off-by: Dmitry Torokhov <dtor at mail.ru>
---

 drivers/w1/w1_smem.c         |  103 -----------------------
 drivers/w1/w1_therm.c        |  188 -------------------------------------------
 dtor/drivers/w1/Kconfig      |   13 +-
 dtor/drivers/w1/Makefile     |    4 
 dtor/drivers/w1/w1.c         |  148 +++++++++------------------------
 dtor/drivers/w1/w1.h         |    5 -
 dtor/drivers/w1/w1_family.c  |   37 +++++---
 dtor/drivers/w1/w1_family.h  |   23 +----
 dtor/drivers/w1/w1_sernum.c  |   58 +++++++++++++
 dtor/drivers/w1/w1_thermal.c |  173 +++++++++++++++++++++++++++++++++++++++
 10 files changed, 317 insertions(+), 435 deletions(-)

Index: dtor/drivers/w1/w1_therm.c
===================================================================
--- dtor.orig/drivers/w1/w1_therm.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- *	w1_therm.c
- *
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol at 2ka.mipt.ru>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the therms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <asm/types.h>
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-
-#include "w1.h"
-#include "w1_io.h"
-#include "w1_family.h"
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <johnpol at 2ka.mipt.ru>");
-MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family.");
-
-static u8 bad_roms[][9] = {
-				{0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87},
-				{}
-			};
-
-static ssize_t w1_therm_read_temp(struct device *, char *);
-static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t);
-
-static struct w1_family_ops w1_therm_fops = {
-	.rbin = &w1_therm_read_bin,
-	.rval = &w1_therm_read_temp,
-	.rvalname = "temp1_input",
-};
-
-static inline int w1_convert_temp(u8 rom[9])
-{
-	int t, h;
-
-	if (rom[1] == 0)
-		t = ((s32)rom[0] >> 1)*1000;
-	else
-		t = 1000*(-1*(s32)(0x100-rom[0]) >> 1);
-
-	t -= 250;
-	h = 1000*((s32)rom[7] - (s32)rom[6]);
-	h /= (s32)rom[7];
-	t += h;
-
-	return t;
-}
-
-static ssize_t w1_therm_read_temp(struct device *dev, char *buf)
-{
-	struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
-
-	return sprintf(buf, "%d\n", w1_convert_temp(sl->rom));
-}
-
-static int w1_therm_check_rom(u8 rom[9])
-{
-	int i;
-
-	for (i=0; i<sizeof(bad_roms)/9; ++i)
-		if (!memcmp(bad_roms[i], rom, 9))
-			return 1;
-
-	return 0;
-}
-
-static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
-	struct w1_slave *sl = container_of(container_of(kobj, struct device, kobj),
-					   struct w1_slave, dev);
-	struct w1_master *dev = sl->master;
-	u8 rom[9], crc, verdict;
-	int i, max_trying = 10;
-
-	if (down_interruptible(&sl->master->mutex))
-		return 0;
-
-	if (off > W1_SLAVE_DATA_SIZE) {
-		count = 0;
-		goto out;
-	}
-	if (off + count > W1_SLAVE_DATA_SIZE) {
-		count = 0;
-		goto out;
-	}
-
-	memset(buf, 0, count);
-	memset(rom, 0, sizeof(rom));
-
-	count = 0;
-	verdict = 0;
-	crc = 0;
-
-	while (max_trying--) {
-		if (!w1_reset_bus (dev)) {
-			int count = 0;
-			u8 match[9] = {W1_MATCH_ROM, };
-			unsigned int tm = 750;
-
-			memcpy(&match[1], (u64 *) & sl->reg_num, 8);
-
-			w1_write_block(dev, match, 9);
-
-			w1_write_8(dev, W1_CONVERT_TEMP);
-
-			while (tm) {
-				tm = msleep_interruptible(tm);
-				if (signal_pending(current))
-					flush_signals(current);
-			}
-
-			if (!w1_reset_bus (dev)) {
-				w1_write_block(dev, match, 9);
-
-				w1_write_8(dev, W1_READ_SCRATCHPAD);
-				if ((count = w1_read_block(dev, rom, 9)) != 9) {
-					dev_warn(&dev->dev, "w1_read_block() returned %d instead of 9.\n", count);
-				}
-
-				crc = w1_calc_crc8(rom, 8);
-
-				if (rom[8] == crc && rom[0])
-					verdict = 1;
-
-			}
-		}
-
-		if (!w1_therm_check_rom(rom))
-			break;
-	}
-
-	for (i = 0; i < 9; ++i)
-		count += sprintf(buf + count, "%02x ", rom[i]);
-	count += sprintf(buf + count, ": crc=%02x %s\n",
-			   crc, (verdict) ? "YES" : "NO");
-	if (verdict)
-		memcpy(sl->rom, rom, sizeof(sl->rom));
-	else
-		dev_warn(&dev->dev, "18S20 doesn't respond to CONVERT_TEMP.\n");
-
-	for (i = 0; i < 9; ++i)
-		count += sprintf(buf + count, "%02x ", sl->rom[i]);
-
-	count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom));
-out:
-	up(&dev->mutex);
-
-	return count;
-}
-
-static struct w1_family w1_therm_family = {
-	.fid = W1_FAMILY_THERM,
-	.fops = &w1_therm_fops,
-};
-
-static int __init w1_therm_init(void)
-{
-	return w1_register_family(&w1_therm_family);
-}
-
-static void __exit w1_therm_fini(void)
-{
-	w1_unregister_family(&w1_therm_family);
-}
-
-module_init(w1_therm_init);
-module_exit(w1_therm_fini);
Index: dtor/drivers/w1/w1_smem.c
===================================================================
--- dtor.orig/drivers/w1/w1_smem.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- *	w1_smem.c
- *
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol at 2ka.mipt.ru>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the smems of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <asm/types.h>
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/types.h>
-
-#include "w1.h"
-#include "w1_io.h"
-#include "w1_family.h"
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <johnpol at 2ka.mipt.ru>");
-MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family.");
-
-static ssize_t w1_smem_read_val(struct device *, char *);
-static ssize_t w1_smem_read_bin(struct kobject *, char *, loff_t, size_t);
-
-static struct w1_family_ops w1_smem_fops = {
-	.rbin = &w1_smem_read_bin,
-	.rval = &w1_smem_read_val,
-	.rvalname = "id",
-};
-
-static ssize_t w1_smem_read_val(struct device *dev, char *buf)
-{
-	struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
-	int i;
-	ssize_t count = 0;
-
-	for (i = 0; i < 9; ++i)
-		count += sprintf(buf + count, "%02x ", ((u8 *)&sl->reg_num)[i]);
-	count += sprintf(buf + count, "\n");
-
-	return count;
-}
-
-static ssize_t w1_smem_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
-	struct w1_slave *sl = container_of(container_of(kobj, struct device, kobj),
-					   struct w1_slave, dev);
-	int i;
-
-	if (down_interruptible(&sl->master->mutex))
-		return 0;
-
-	if (off > W1_SLAVE_DATA_SIZE) {
-		count = 0;
-		goto out;
-	}
-	if (off + count > W1_SLAVE_DATA_SIZE) {
-		count = 0;
-		goto out;
-	}
-	for (i = 0; i < 9; ++i)
-		count += sprintf(buf + count, "%02x ", ((u8 *)&sl->reg_num)[i]);
-	count += sprintf(buf + count, "\n");
-
-out:
-	up(&sl->master->mutex);
-
-	return count;
-}
-
-static struct w1_family w1_smem_family = {
-	.fid = W1_FAMILY_SMEM,
-	.fops = &w1_smem_fops,
-};
-
-static int __init w1_smem_init(void)
-{
-	return w1_register_family(&w1_smem_family);
-}
-
-static void __exit w1_smem_fini(void)
-{
-	w1_unregister_family(&w1_smem_family);
-}
-
-module_init(w1_smem_init);
-module_exit(w1_smem_fini);
Index: dtor/drivers/w1/w1.c
===================================================================
--- dtor.orig/drivers/w1/w1.c
+++ dtor/drivers/w1/w1.c
@@ -2,6 +2,7 @@
  *	w1.c
  *
  * Copyright (c) 2004 Evgeniy Polyakov <johnpol at 2ka.mipt.ru>
+ * Copyright (c) 2005 Dmitry Torokhov <dtor at mail.ru>
  *
  *
  * This program is free software; you can redistribute it and/or modify
@@ -97,30 +98,6 @@ static struct attribute_group w1_slave_d
 	.attrs = w1_slave_default_attrs,
 };
 
-static ssize_t w1_default_read_name(struct device *dev, char *buf)
-{
-	return sprintf(buf, "No family registered.\n");
-}
-
-static ssize_t w1_default_read_bin(struct kobject *kobj, char *buf, loff_t off,
-		     size_t count)
-{
-	return sprintf(buf, "No family registered.\n");
-}
-
-static struct device_attribute w1_slave_attribute_val =
-	__ATTR(value, S_IRUGO, w1_default_read_name, NULL);
-
-static struct bin_attribute w1_slave_bin_attribute = {
-	.attr = {
-		.name = "w1_slave",
-		.mode = S_IRUGO,
-		.owner = THIS_MODULE,
-	},
-	.size = W1_SLAVE_DATA_SIZE,
-	.read = &w1_default_read_bin,
-};
-
 static void w1_slave_release(struct device *dev)
 {
 	struct w1_slave *slave = to_w1_slave(dev);
@@ -130,79 +107,10 @@ static void w1_slave_release(struct devi
 	module_put(THIS_MODULE);
 }
 
-static int __w1_attach_slave_device(struct w1_slave *slave)
-{
-	int err;
-
-	slave->dev.parent = &slave->master->dev;
-	slave->dev.bus = &w1_bus_type;
-	slave->dev.release = &w1_slave_release;
-
-	snprintf(&slave->dev.bus_id[0], sizeof(slave->dev.bus_id),
-		  "%02x-%012llx",
-		  (unsigned int) slave->reg_num.family,
-		  (unsigned long long) slave->reg_num.id);
-
-	dev_dbg(&slave->dev, "%s: registering %s.\n", __func__,
-		&slave->dev.bus_id[0]);
-
-	err = device_register(&slave->dev);
-	if (err < 0) {
-		dev_err(&slave->dev,
-			 "Device registration [%s] failed. err=%d\n",
-			 slave->dev.bus_id, err);
-		return err;
-	}
-
-	__module_get(THIS_MODULE);
-
-	memcpy(&slave->attr_bin, &w1_slave_bin_attribute, sizeof(slave->attr_bin));
-	memcpy(&slave->attr_val, &w1_slave_attribute_val, sizeof(slave->attr_val));
-
-	slave->attr_bin.read = slave->family->fops->rbin;
-	slave->attr_val.show = slave->family->fops->rval;
-	slave->attr_val.attr.name = slave->family->fops->rvalname;
-
-	err = device_create_file(&slave->dev, &slave->attr_val);
-	if (err < 0) {
-		dev_err(&slave->dev,
-			 "sysfs file creation for [%s] failed. err=%d\n",
-			 slave->dev.bus_id, err);
-		device_unregister(&slave->dev);
-		return err;
-	}
-
-	err = sysfs_create_bin_file(&slave->dev.kobj, &slave->attr_bin);
-	if (err < 0) {
-		dev_err(&slave->dev,
-			 "sysfs file creation for [%s] failed. err=%d\n",
-			 slave->dev.bus_id, err);
-		device_remove_file(&slave->dev, &slave->attr_val);
-		device_unregister(&slave->dev);
-		return err;
-	}
-
-	err = sysfs_create_group(&slave->dev.kobj, &w1_slave_defattr_group);
-	if (err < 0) {
-		dev_err(&slave->dev,
-			 "sysfs group creation for [%s] failed. err=%d\n",
-			 slave->dev.bus_id, err);
-		sysfs_remove_bin_file(&slave->dev.kobj, &slave->attr_bin);
-		device_remove_file(&slave->dev, &slave->attr_val);
-		device_unregister(&slave->dev);
-		return err;
-	}
-
-	list_add_tail(&slave->node, &slave->master->slist);
-
-	return 0;
-}
-
 static int w1_attach_slave_device(struct w1_master *master, struct w1_reg_num *rn)
 {
 	struct w1_slave *slave;
-	struct w1_family *f;
-	int err;
+	int error;
 
 	slave = kcalloc(1, sizeof(struct w1_slave), GFP_KERNEL);
 	if (!slave) {
@@ -212,13 +120,16 @@ static int w1_attach_slave_device(struct
 		return -ENOMEM;
 	}
 
+	init_MUTEX(&slave->mutex);
+	INIT_LIST_HEAD(&slave->node);
 	slave->master = master;
 	slave->reg_num = *rn;
 	set_bit(W1_SLAVE_ACTIVE, &slave->flags);
+	slave->ttl = master->slave_ttl;
 
 	spin_lock(&w1_flock);
-	f = w1_family_registered(rn->family);
-	if (!f) {
+	slave->family = w1_family_registered(rn->family);
+	if (!slave->family) {
 		spin_unlock(&w1_flock);
 		dev_info(&master->dev,
 			 "Family %x for %02x.%012llx.%02x is not registered.\n",
@@ -227,21 +138,45 @@ static int w1_attach_slave_device(struct
 		kfree(slave);
 		return -ENODEV;
 	}
-	__w1_family_get(f);
+	__w1_family_get(slave->family);
 	spin_unlock(&w1_flock);
 
-	slave->family = f;
+	slave->dev.parent = &slave->master->dev;
+	slave->dev.bus = &w1_bus_type;
+	slave->dev.release = &w1_slave_release;
+
+	snprintf(&slave->dev.bus_id[0], sizeof(slave->dev.bus_id),
+		  "%02x-%012llx",
+		  (unsigned int) slave->reg_num.family,
+		  (unsigned long long) slave->reg_num.id);
+
+	dev_dbg(&slave->dev, "%s: registering %s.\n", __func__,
+		&slave->dev.bus_id[0]);
 
-	err = __w1_attach_slave_device(slave);
-	if (err < 0) {
-		dev_err(&master->dev, "%s: Attaching %s failed.\n", __func__,
-			slave->dev.bus_id);
+	error = device_register(&slave->dev);
+	if (error < 0) {
+		dev_err(&slave->dev,
+			 "Device registration [%s] failed. err=%d\n",
+			 slave->dev.bus_id, error);
 		w1_family_put(slave->family);
 		kfree(slave);
-		return err;
+		return error;
 	}
 
-	slave->ttl = master->slave_ttl;
+	__module_get(THIS_MODULE);
+
+	error = sysfs_create_group(&slave->dev.kobj, &w1_slave_defattr_group);
+	if (error < 0) {
+		dev_err(&slave->dev,
+			 "sysfs group creation for [%s] failed. err=%d\n",
+			 slave->dev.bus_id, error);
+		device_unregister(&slave->dev);
+		return error;
+	}
+
+	w1_family_join(slave);	/* assume it always succeeds for now */
+
+	list_add_tail(&slave->node, &slave->master->slist);
 
 	return 0;
 }
@@ -251,9 +186,8 @@ static void w1_slave_detach(struct w1_sl
 	dev_info(&slave->dev, "%s: detaching %s.\n",
 		 __func__, slave->dev.bus_id);
 
+	w1_family_leave(slave);
 	sysfs_remove_group(&slave->dev.kobj, &w1_slave_defattr_group);
-	sysfs_remove_bin_file(&slave->dev.kobj, &slave->attr_bin);
-	device_remove_file(&slave->dev, &slave->attr_val);
 	device_unregister(&slave->dev);
 }
 
@@ -519,10 +453,12 @@ void w1_remove_master_device(struct w1_m
 
 	w1_stop_master_device(master);
 
+	down(&master->mutex);
 	list_for_each_entry_safe(slave, next, &master->slist, node) {
 		list_del(&slave->node);
 		w1_slave_detach(slave);
 	}
+	up(&master->mutex);
 
 	sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group);
 	device_unregister(&master->dev);
Index: dtor/drivers/w1/w1.h
===================================================================
--- dtor.orig/drivers/w1/w1.h
+++ dtor/drivers/w1/w1.h
@@ -47,7 +47,6 @@ struct w1_reg_num
 #include "w1_family.h"
 
 #define W1_MAXNAMELEN		32
-#define W1_SLAVE_DATA_SIZE	128
 
 #define W1_SEARCH		0xF0
 #define W1_CONDITIONAL_SEARCH	0xEC
@@ -71,9 +70,7 @@ struct w1_slave
 	struct w1_master	*master;
 	struct w1_family	*family;
 	struct device		dev;
-
-	struct bin_attribute	attr_bin;
-	struct device_attribute	attr_name, attr_val;
+	struct semaphore	mutex;
 };
 #define to_w1_slave(dev)	container_of((dev), struct w1_slave, dev)
 
Index: dtor/drivers/w1/w1_thermal.c
===================================================================
--- /dev/null
+++ dtor/drivers/w1/w1_thermal.c
@@ -0,0 +1,173 @@
+/*
+ *	w1_thermal.c
+ *
+ * Copyright (c) 2004 Evgeniy Polyakov <johnpol at 2ka.mipt.ru>
+ * Copyright (c) 2005 Dmitry Torokhov <dtor at mail.ru>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the therms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+
+#include "w1.h"
+#include "w1_io.h"
+#include "w1_family.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Evgeniy Polyakov <johnpol at 2ka.mipt.ru>");
+MODULE_DESCRIPTION("1-Wire Digital Thermometer");
+
+static ssize_t w1_thermal_show_temp(struct device *, char *);
+
+static struct device_attribute w1_thermal_temperature_attr =
+	__ATTR(temp, S_IRUGO, w1_thermal_show_temp, NULL);
+
+static int w1_thermal_join(struct w1_slave *slave)
+{
+	return device_create_file(&slave->dev, &w1_thermal_temperature_attr);
+}
+
+static void w1_thermal_leave(struct w1_slave *slave)
+{
+	device_remove_file(&slave->dev, &w1_thermal_temperature_attr);
+}
+
+static struct w1_family w1_thermal_family = {
+	.fid		= W1_FAMILY_THERMAL,
+	.join		= w1_thermal_join,
+	.leave		= w1_thermal_leave,
+};
+
+static u8 bad_roms[][9] = {
+	{ 0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87 },
+	{ }
+};
+
+static inline int w1_convert_temp(u8 rom[9])
+{
+	int t, h;
+
+	if (rom[1] == 0)
+		t = ((s32)rom[0] >> 1) * 1000;
+	else
+		t = 1000 * (-1 * (s32)(0x100 - rom[0]) >> 1);
+
+	t -= 250;
+	h = 1000 * ((s32)rom[7] - (s32)rom[6]);
+	h /= (s32)rom[7];
+	t += h;
+
+	return t;
+}
+
+static int w1_therm_check_rom(u8 rom[9])
+{
+	int i;
+
+	for (i = 0; i < sizeof(bad_roms) / 9; i++)
+		if (!memcmp(bad_roms[i], rom, 9))
+			return 1;
+
+	return 0;
+}
+
+static int w1_thermal_read_data(struct w1_slave *slave, u8 data[])
+{
+	struct w1_master *dev = slave->master;
+	u8 match[9] = { W1_MATCH_ROM, };
+	u8 crc;
+	int count;
+	int error;
+
+	memset(data, 0, 9);
+
+	error = w1_reset_bus(dev);
+	if (error)
+		return error;
+
+	memcpy(&match[1], (u64 *)&slave->reg_num, sizeof(u64));
+
+	w1_write_block(dev, match, 9);
+	w1_write_8(dev, W1_CONVERT_TEMP);
+	msleep(750);
+
+	error = w1_reset_bus(dev);
+	if (error)
+		return error;
+
+	w1_write_block(dev, match, 9);
+	w1_write_8(dev, W1_READ_SCRATCHPAD);
+	if ((count = w1_read_block(dev, data, 9)) != 9)
+		dev_warn(&dev->dev, "w1_read_block() returned %d instead of 9.\n", count);
+
+	crc = w1_calc_crc8(data, 8);
+	if (data[8] != crc || !data[0] || w1_therm_check_rom(data))
+		return -EIO;
+
+	return 0;
+}
+
+static ssize_t w1_thermal_show_temp(struct device *dev, char *buf)
+{
+	struct w1_slave *slave = to_w1_slave(dev);
+	int attempts = 10;
+	u8 data[9];
+	int error;
+	ssize_t count = 0;
+
+	error = down_interruptible(&slave->master->mutex);
+	if (error)
+		return error;
+
+	error = down_interruptible(&slave->mutex);
+	if (error)
+		goto out;
+
+	if (slave->family != &w1_thermal_family) {
+		error = -ENODEV;
+		goto out;
+	}
+
+	do {
+		error = w1_thermal_read_data(slave, data);
+		if (!error)
+			count = sprintf(buf, "%d\n", w1_convert_temp(data));
+
+	} while (error && attempts-- > 0);
+
+	up(&slave->mutex);
+out:
+	up(&slave->master->mutex);
+	return error ? error : count;
+}
+
+static int __init w1_thermal_init(void)
+{
+	return w1_register_family(&w1_thermal_family);
+}
+
+static void __exit w1_thermal_exit(void)
+{
+	w1_unregister_family(&w1_thermal_family);
+}
+
+module_init(w1_thermal_init);
+module_exit(w1_thermal_exit);
Index: dtor/drivers/w1/Makefile
===================================================================
--- dtor.orig/drivers/w1/Makefile
+++ dtor/drivers/w1/Makefile
@@ -10,8 +10,8 @@ obj-$(CONFIG_W1)	+= wire.o
 wire-objs		:= w1.o w1_family.o w1_io.o
 
 obj-$(CONFIG_W1_MATROX)		+= matrox_w1.o
-obj-$(CONFIG_W1_THERM)		+= w1_therm.o
-obj-$(CONFIG_W1_SMEM)		+= w1_smem.o
+obj-$(CONFIG_W1_THERMAL)	+= w1_thermal.o
+obj-$(CONFIG_W1_SERNUM)		+= w1_sernum.o
 
 obj-$(CONFIG_W1_DS9490)		+= ds9490r.o
 ds9490r-objs    := dscore.o
Index: dtor/drivers/w1/w1_sernum.c
===================================================================
--- /dev/null
+++ dtor/drivers/w1/w1_sernum.c
@@ -0,0 +1,58 @@
+/*
+ *	w1_sernum.c
+ *
+ * Copyright (c) 2004 Evgeniy Polyakov <johnpol at 2ka.mipt.ru>
+ * Copyright (c) 2005 Dmitry Torokhov <dtor at mail.ru>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the smems of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/types.h>
+
+#include "w1.h"
+#include "w1_family.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Evgeniy Polyakov <johnpol at 2ka.mipt.ru>");
+MODULE_DESCRIPTION("1-Wire Silicon Serial Number Driver");
+
+/*
+ * This is a very dumb device. It just has an unique ID and
+ * sits on the bus doing nothing. So the driver does not do
+ * anything fancy either; access to device's ID is provided
+ * by W1 core.
+ */
+
+static struct w1_family w1_serial_num_family = {
+	.fid		= W1_FAMILY_SERIAL_NUM,
+};
+
+static int __init w1_serial_num_init(void)
+{
+	return w1_register_family(&w1_serial_num_family);
+}
+
+static void __exit w1_serial_num_exit(void)
+{
+	w1_unregister_family(&w1_serial_num_family);
+}
+
+module_init(w1_serial_num_init);
+module_exit(w1_serial_num_exit);
Index: dtor/drivers/w1/Kconfig
===================================================================
--- dtor.orig/drivers/w1/Kconfig
+++ dtor/drivers/w1/Kconfig
@@ -40,18 +40,19 @@ config W1_DS9490_BRIDGE
 	  This support is also available as a module.  If so, the module
 	  will be called ds_w1_bridge.ko.
 
-config W1_THERM
-	tristate "Thermal family implementation"
+config W1_THERMAL
+	tristate "Thermal sensor devices"
 	depends on W1
 	help
-	  Say Y here if you want to connect 1-wire thermal sensors to you
+	  Say Y here if you want to connect 1-wire thermal sensors to your
 	  wire.
 
-config W1_SMEM
-	tristate "Simple 64bit memory family implementation"
+config W1_SERNUM
+	tristate "Silicon Serial Number devices"
 	depends on W1
 	help
 	  Say Y here if you want to connect 1-wire
-	  simple 64bit memory rom(ds2401/ds2411/ds1990*) to you wire.
+	  simple addressable devices (Silicon Serial Nnumbers -
+	  ds2401/ds2411/ds1990*) to your wire.
 
 endmenu
Index: dtor/drivers/w1/w1_family.c
===================================================================
--- dtor.orig/drivers/w1/w1_family.c
+++ dtor/drivers/w1/w1_family.c
@@ -23,28 +23,18 @@
 #include <linux/list.h>
 #include <linux/delay.h>
 
+#include "w1.h"
 #include "w1_family.h"
 
 DEFINE_SPINLOCK(w1_flock);
 static LIST_HEAD(w1_families);
 
-static int w1_check_family(struct w1_family *f)
-{
-	if (!f->fops->rbin || !f->fops->rval || !f->fops->rvalname)
-		return -EINVAL;
-
-	return 0;
-}
-
 int w1_register_family(struct w1_family *newf)
 {
 	struct list_head *ent, *n;
 	struct w1_family *f;
 	int ret = 0;
 
-	if (w1_check_family(newf))
-		return -EINVAL;
-
 	spin_lock(&w1_flock);
 	list_for_each_safe(ent, n, &w1_families) {
 		f = list_entry(ent, struct w1_family, family_entry);
@@ -115,6 +105,31 @@ struct w1_family * w1_family_registered(
 	return (ret) ? f : NULL;
 }
 
+int w1_family_join(struct w1_slave *slave)
+{
+	int retval;
+
+	retval = down_interruptible(&slave->mutex);
+	if (retval)
+		return retval;
+
+	if (slave->family->join)
+		retval = slave->family->join(slave);
+
+	up(&slave->mutex);
+	return retval;
+}
+
+void w1_family_leave(struct w1_slave *slave)
+{
+	down(&slave->mutex);
+
+	if (slave->family->leave)
+		slave->family->leave(slave);
+
+	up(&slave->mutex);
+}
+
 void w1_family_put(struct w1_family *f)
 {
 	spin_lock(&w1_flock);
Index: dtor/drivers/w1/w1_family.h
===================================================================
--- dtor.orig/drivers/w1/w1_family.h
+++ dtor/drivers/w1/w1_family.h
@@ -26,28 +26,20 @@
 #include <linux/device.h>
 #include <asm/atomic.h>
 
-#define W1_FAMILY_DEFAULT	0
-#define W1_FAMILY_THERM		0x10
-#define W1_FAMILY_SMEM		0x01
+#define W1_FAMILY_SERIAL_NUM	0x01
+#define W1_FAMILY_THERMAL	0x10
 
-#define MAXNAMELEN		32
-
-struct w1_family_ops
-{
-	ssize_t (* rbin)(struct kobject *, char *, loff_t, size_t);
-	ssize_t (* rval)(struct device *, char *);
-	unsigned char rvalname[MAXNAMELEN];
-};
+struct w1_slave;
 
 struct w1_family
 {
 	struct list_head	family_entry;
 	u8			fid;
-
-	struct w1_family_ops	*fops;
-
 	atomic_t		refcnt;
 	u8			need_exit;
+
+	int (*join)(struct w1_slave *);
+	void (*leave)(struct w1_slave *);
 };
 
 extern spinlock_t w1_flock;
@@ -57,7 +49,8 @@ void w1_family_put(struct w1_family *);
 void __w1_family_get(struct w1_family *);
 void __w1_family_put(struct w1_family *);
 struct w1_family * w1_family_registered(u8);
+int w1_family_join(struct w1_slave *);
+void w1_family_leave(struct w1_slave *);
 void w1_unregister_family(struct w1_family *);
 int w1_register_family(struct w1_family *);
-
 #endif /* __W1_FAMILY_H */



More information about the lm-sensors mailing list