aboutsummaryrefslogtreecommitdiffstats
path: root/i2c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2006-03-31 16:24:15 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2006-03-31 16:24:15 -0800
commit4e94b51afd61703d88e6d84451fd2bbd10efbeaa (patch)
tree8905e95ee236a20d9aab1272db4ef1b8e1aa20d0 /i2c
parentf58ad68f00c1744fddbf67fd7467912ae6b42eae (diff)
downloadpatches-4e94b51afd61703d88e6d84451fd2bbd10efbeaa.tar.gz
more patches
Diffstat (limited to 'i2c')
-rw-r--r--i2c/w1-added-default-generic-read-write-operations.patch155
-rw-r--r--i2c/w1-move-w1-connector-definitions-into-linux-include-connector.h.patch44
-rw-r--r--i2c/w1-netlink-mark-netlink-group-1-as-unused.patch29
-rw-r--r--i2c/w1-replace-dscore-and-ds_w1_bridge-with-ds2490-driver.patch2185
-rw-r--r--i2c/w1-userspace-communication-protocol-over-connector.patch1045
5 files changed, 3458 insertions, 0 deletions
diff --git a/i2c/w1-added-default-generic-read-write-operations.patch b/i2c/w1-added-default-generic-read-write-operations.patch
new file mode 100644
index 0000000000000..87cce1b0c6efc
--- /dev/null
+++ b/i2c/w1-added-default-generic-read-write-operations.patch
@@ -0,0 +1,155 @@
+From johnpol@2ka.mipt.ru Thu Mar 23 07:59:58 2006
+Cc: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+Subject: [PATCH 1/5] w1: Added default generic read/write operations.
+Date: Thu, 23 Mar 2006 19:11:58 +0300
+Message-Id: <11431303182664@2ka.mipt.ru>
+To: GregKH <greg@kroah.com>
+From: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+
+
+Special file in each w1 slave device's directory called "rw" is created
+each time new slave and no appropriate w1 family is registered.
+"rw" file supports read and write operations, which allows to perform
+almost any kind of operations. Each logical operation is a transaction
+in nature, which can contain several (two or one) low-level operations.
+Let's see how one can read EEPROM context:
+1. one must write control buffer, i.e. buffer containing command byte
+and two byte address. At this step bus is reset and appropriate device
+is selected using either W1_SKIP_ROM or W1_MATCH_ROM command.
+Then provided control buffer is being written to the wire.
+2. reading. This will issue reading eeprom response.
+
+It is possible that between 1. and 2. w1 master thread will reset bus for
+searching and slave device will be even removed, but in this case 0xff will
+be read, since no device was selected.
+
+Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ Documentation/w1/w1.generic | 18 +++++++++--
+ drivers/w1/w1.c | 69 +++++++++++++++++++++++++++++++++++++++++++-
+ drivers/w1/w1.h | 2 -
+ 3 files changed, 84 insertions(+), 5 deletions(-)
+
+--- gregkh-2.6.orig/Documentation/w1/w1.generic
++++ gregkh-2.6/Documentation/w1/w1.generic
+@@ -27,8 +27,19 @@ When a w1 master driver registers with t
+
+ When a device is found on the bus, w1 core checks if driver for it's family is
+ loaded. If so, the family driver is attached to the slave.
+-If there is no driver for the family, a simple sysfs entry is created
+-for the slave device.
++If there is no driver for the family, default one is assigned, which allows to perform
++almost any kind of operations. Each logical operation is a transaction
++in nature, which can contain several (two or one) low-level operations.
++Let's see how one can read EEPROM context:
++1. one must write control buffer, i.e. buffer containing command byte
++and two byte address. At this step bus is reset and appropriate device
++is selected using either W1_SKIP_ROM or W1_MATCH_ROM command.
++Then provided control buffer is being written to the wire.
++2. reading. This will issue reading eeprom response.
++
++It is possible that between 1. and 2. w1 master thread will reset bus for searching
++and slave device will be even removed, but in this case 0xff will
++be read, since no device was selected.
+
+
+ W1 device families
+@@ -89,4 +100,5 @@ driver - (standard) symlink
+ name - the device name, usually the same as the directory name
+ w1_slave - (optional) a binary file whose meaning depends on the
+ family driver
+-
++rw - (optional) created for slave devices which do not have
++ appropriate family driver. Allows to read/write binary data.
+--- gregkh-2.6.orig/drivers/w1/w1.c
++++ gregkh-2.6/drivers/w1/w1.c
+@@ -139,7 +139,74 @@ static struct bin_attribute w1_slave_att
+ };
+
+ /* Default family */
+-static struct w1_family w1_default_family;
++
++static ssize_t w1_default_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
++{
++ struct w1_slave *sl = kobj_to_w1_slave(kobj);
++
++ if (down_interruptible(&sl->master->mutex)) {
++ count = 0;
++ goto out;
++ }
++
++ if (w1_reset_select_slave(sl)) {
++ count = 0;
++ goto out_up;
++ }
++
++ w1_write_block(sl->master, buf, count);
++
++out_up:
++ up(&sl->master->mutex);
++out:
++ return count;
++}
++
++static ssize_t w1_default_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
++{
++ struct w1_slave *sl = kobj_to_w1_slave(kobj);
++
++ if (down_interruptible(&sl->master->mutex)) {
++ count = 0;
++ goto out;
++ }
++
++ w1_read_block(sl->master, buf, count);
++
++ up(&sl->master->mutex);
++out:
++ return count;
++}
++
++static struct bin_attribute w1_default_attr = {
++ .attr = {
++ .name = "rw",
++ .mode = S_IRUGO | S_IWUSR,
++ .owner = THIS_MODULE,
++ },
++ .size = PAGE_SIZE,
++ .read = w1_default_read,
++ .write = w1_default_write,
++};
++
++static int w1_default_add_slave(struct w1_slave *sl)
++{
++ return sysfs_create_bin_file(&sl->dev.kobj, &w1_default_attr);
++}
++
++static void w1_default_remove_slave(struct w1_slave *sl)
++{
++ sysfs_remove_bin_file(&sl->dev.kobj, &w1_default_attr);
++}
++
++static struct w1_family_ops w1_default_fops = {
++ .add_slave = w1_default_add_slave,
++ .remove_slave = w1_default_remove_slave,
++};
++
++static struct w1_family w1_default_family = {
++ .fops = &w1_default_fops,
++};
+
+ static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size);
+
+--- gregkh-2.6.orig/drivers/w1/w1.h
++++ gregkh-2.6/drivers/w1/w1.h
+@@ -60,7 +60,7 @@ struct w1_reg_num
+ #define W1_READ_PSUPPLY 0xB4
+ #define W1_MATCH_ROM 0x55
+
+-#define W1_SLAVE_ACTIVE (1<<0)
++#define W1_SLAVE_ACTIVE 0
+
+ struct w1_slave
+ {
diff --git a/i2c/w1-move-w1-connector-definitions-into-linux-include-connector.h.patch b/i2c/w1-move-w1-connector-definitions-into-linux-include-connector.h.patch
new file mode 100644
index 0000000000000..6f7f458703e22
--- /dev/null
+++ b/i2c/w1-move-w1-connector-definitions-into-linux-include-connector.h.patch
@@ -0,0 +1,44 @@
+From johnpol@2ka.mipt.ru Thu Mar 23 08:00:09 2006
+Cc: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+Subject: [PATCH 4/5] w1: Move w1-connector definitions into linux/include/connector.h
+Date: Thu, 23 Mar 2006 19:11:58 +0300
+Message-Id: <11431303183514@2ka.mipt.ru>
+To: GregKH <greg@kroah.com>
+From: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+
+
+Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/w1/w1_netlink.h | 3 ---
+ include/linux/connector.h | 5 ++++-
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+--- gregkh-2.6.orig/drivers/w1/w1_netlink.h
++++ gregkh-2.6/drivers/w1/w1_netlink.h
+@@ -27,9 +27,6 @@
+
+ #include "w1.h"
+
+-#define CN_W1_IDX 3
+-#define CN_W1_VAL 1
+-
+ enum w1_netlink_message_types {
+ W1_SLAVE_ADD = 0,
+ W1_SLAVE_REMOVE,
+--- gregkh-2.6.orig/include/linux/connector.h
++++ gregkh-2.6/include/linux/connector.h
+@@ -34,8 +34,11 @@
+ #define CN_VAL_PROC 0x1
+ #define CN_IDX_CIFS 0x2
+ #define CN_VAL_CIFS 0x1
++#define CN_W1_IDX 0x3 /* w1 communication */
++#define CN_W1_VAL 0x1
+
+-#define CN_NETLINK_USERS 1
++
++#define CN_NETLINK_USERS 4
+
+ /*
+ * Maximum connector's message size.
diff --git a/i2c/w1-netlink-mark-netlink-group-1-as-unused.patch b/i2c/w1-netlink-mark-netlink-group-1-as-unused.patch
new file mode 100644
index 0000000000000..b09b6d27a49b2
--- /dev/null
+++ b/i2c/w1-netlink-mark-netlink-group-1-as-unused.patch
@@ -0,0 +1,29 @@
+From johnpol@2ka.mipt.ru Thu Mar 23 08:00:20 2006
+Cc: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+Subject: [PATCH 5/5] w1: netlink: Mark netlink group 1 as unused.
+Date: Thu, 23 Mar 2006 19:11:58 +0300
+Message-Id: <11431303183286@2ka.mipt.ru>
+To: GregKH <greg@kroah.com>
+From: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+
+
+netlink_w1 was moved to connector.
+
+Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/linux/netlink.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- gregkh-2.6.orig/include/linux/netlink.h
++++ gregkh-2.6/include/linux/netlink.h
+@@ -5,7 +5,7 @@
+ #include <linux/types.h>
+
+ #define NETLINK_ROUTE 0 /* Routing/device hook */
+-#define NETLINK_W1 1 /* 1-wire subsystem */
++#define NETLINK_UNUSED 1 /* Unused number */
+ #define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */
+ #define NETLINK_FIREWALL 3 /* Firewalling hook */
+ #define NETLINK_INET_DIAG 4 /* INET socket monitoring */
diff --git a/i2c/w1-replace-dscore-and-ds_w1_bridge-with-ds2490-driver.patch b/i2c/w1-replace-dscore-and-ds_w1_bridge-with-ds2490-driver.patch
new file mode 100644
index 0000000000000..ba266a9aa2205
--- /dev/null
+++ b/i2c/w1-replace-dscore-and-ds_w1_bridge-with-ds2490-driver.patch
@@ -0,0 +1,2185 @@
+From johnpol@2ka.mipt.ru Thu Mar 23 08:00:09 2006
+Cc: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+Subject: [PATCH 2/5] w1: Replace dscore and ds_w1_bridge with ds2490 driver.
+Date: Thu, 23 Mar 2006 19:11:58 +0300
+Message-Id: <11431303181703@2ka.mipt.ru>
+To: GregKH <greg@kroah.com>
+From: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+
+
+---
+ Documentation/w1/masters/ds2490 | 18
+ drivers/w1/masters/Kconfig | 27 -
+ drivers/w1/masters/Makefile | 7
+ drivers/w1/masters/ds2490.c | 947 ++++++++++++++++++++++++++++++++++++++
+ drivers/w1/masters/ds_w1_bridge.c | 174 ------
+ drivers/w1/masters/dscore.c | 795 -------------------------------
+ drivers/w1/masters/dscore.h | 166 ------
+ 7 files changed, 975 insertions(+), 1159 deletions(-)
+
+--- /dev/null
++++ gregkh-2.6/Documentation/w1/masters/ds2490
+@@ -0,0 +1,18 @@
++Kernel driver ds2490
++====================
++
++Supported chips:
++ * Maxim DS2490 based
++
++Author: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
++
++
++Description
++-----------
++
++The Maixm/Dallas Semiconductor DS2490 is a chip
++which allows to build USB <-> W1 bridges.
++
++DS9490(R) is a USB <-> W1 bus master device
++which has 0x81 family ID integrated chip and DS2490
++low-level operational chip.
+--- gregkh-2.6.orig/drivers/w1/masters/Kconfig
++++ gregkh-2.6/drivers/w1/masters/Kconfig
+@@ -15,24 +15,15 @@ config W1_MASTER_MATROX
+ This support is also available as a module. If so, the module
+ will be called matrox_w1.ko.
+
+-config W1_MASTER_DS9490
+- tristate "DS9490R transport layer driver"
+- depends on W1 && USB
+- help
+- Say Y here if you want to have a driver for DS9490R UWB <-> W1 bridge.
+-
+- This support is also available as a module. If so, the module
+- will be called ds9490r.ko.
+-
+-config W1_MASTER_DS9490_BRIDGE
+- tristate "DS9490R USB <-> W1 transport layer for 1-wire"
+- depends on W1_MASTER_DS9490
+- help
+- Say Y here if you want to communicate with your 1-wire devices
+- using DS9490R USB bridge.
+-
+- This support is also available as a module. If so, the module
+- will be called ds_w1_bridge.ko.
++config W1_MASTER_DS2490
++ tristate "DS2490 USB <-> W1 transport layer for 1-wire"
++ depends on W1 && USB
++ help
++ Say Y here if you want to have a driver for DS2490 based USB <-> W1 bridges,
++ for example DS9490*.
++
++ This support is also available as a module. If so, the module
++ will be called ds2490.ko.
+
+ config W1_MASTER_DS2482
+ tristate "Maxim DS2482 I2C to 1-Wire bridge"
+--- gregkh-2.6.orig/drivers/w1/masters/Makefile
++++ gregkh-2.6/drivers/w1/masters/Makefile
+@@ -3,11 +3,6 @@
+ #
+
+ obj-$(CONFIG_W1_MASTER_MATROX) += matrox_w1.o
+-
+-obj-$(CONFIG_W1_MASTER_DS9490) += ds9490r.o
+-ds9490r-objs := dscore.o
+-
+-obj-$(CONFIG_W1_MASTER_DS9490_BRIDGE) += ds_w1_bridge.o
+-
++obj-$(CONFIG_W1_MASTER_DS2490) += ds2490.o
+ obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o
+
+--- /dev/null
++++ gregkh-2.6/drivers/w1/masters/ds2490.c
+@@ -0,0 +1,947 @@
++/*
++ * dscore.c
++ *
++ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
++ *
++ *
++ * 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
++ * 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/module.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/usb.h>
++
++#include "../w1_int.h"
++#include "../w1.h"
++
++/* COMMAND TYPE CODES */
++#define CONTROL_CMD 0x00
++#define COMM_CMD 0x01
++#define MODE_CMD 0x02
++
++/* CONTROL COMMAND CODES */
++#define CTL_RESET_DEVICE 0x0000
++#define CTL_START_EXE 0x0001
++#define CTL_RESUME_EXE 0x0002
++#define CTL_HALT_EXE_IDLE 0x0003
++#define CTL_HALT_EXE_DONE 0x0004
++#define CTL_FLUSH_COMM_CMDS 0x0007
++#define CTL_FLUSH_RCV_BUFFER 0x0008
++#define CTL_FLUSH_XMT_BUFFER 0x0009
++#define CTL_GET_COMM_CMDS 0x000A
++
++/* MODE COMMAND CODES */
++#define MOD_PULSE_EN 0x0000
++#define MOD_SPEED_CHANGE_EN 0x0001
++#define MOD_1WIRE_SPEED 0x0002
++#define MOD_STRONG_PU_DURATION 0x0003
++#define MOD_PULLDOWN_SLEWRATE 0x0004
++#define MOD_PROG_PULSE_DURATION 0x0005
++#define MOD_WRITE1_LOWTIME 0x0006
++#define MOD_DSOW0_TREC 0x0007
++
++/* COMMUNICATION COMMAND CODES */
++#define COMM_ERROR_ESCAPE 0x0601
++#define COMM_SET_DURATION 0x0012
++#define COMM_BIT_IO 0x0020
++#define COMM_PULSE 0x0030
++#define COMM_1_WIRE_RESET 0x0042
++#define COMM_BYTE_IO 0x0052
++#define COMM_MATCH_ACCESS 0x0064
++#define COMM_BLOCK_IO 0x0074
++#define COMM_READ_STRAIGHT 0x0080
++#define COMM_DO_RELEASE 0x6092
++#define COMM_SET_PATH 0x00A2
++#define COMM_WRITE_SRAM_PAGE 0x00B2
++#define COMM_WRITE_EPROM 0x00C4
++#define COMM_READ_CRC_PROT_PAGE 0x00D4
++#define COMM_READ_REDIRECT_PAGE_CRC 0x21E4
++#define COMM_SEARCH_ACCESS 0x00F4
++
++/* Communication command bits */
++#define COMM_TYPE 0x0008
++#define COMM_SE 0x0008
++#define COMM_D 0x0008
++#define COMM_Z 0x0008
++#define COMM_CH 0x0008
++#define COMM_SM 0x0008
++#define COMM_R 0x0008
++#define COMM_IM 0x0001
++
++#define COMM_PS 0x4000
++#define COMM_PST 0x4000
++#define COMM_CIB 0x4000
++#define COMM_RTS 0x4000
++#define COMM_DT 0x2000
++#define COMM_SPU 0x1000
++#define COMM_F 0x0800
++#define COMM_NTP 0x0400
++#define COMM_ICP 0x0200
++#define COMM_RST 0x0100
++
++#define PULSE_PROG 0x01
++#define PULSE_SPUE 0x02
++
++#define BRANCH_MAIN 0xCC
++#define BRANCH_AUX 0x33
++
++/*
++ * Duration of the strong pull-up pulse in milliseconds.
++ */
++#define PULLUP_PULSE_DURATION 750
++
++/* Status flags */
++#define ST_SPUA 0x01 /* Strong Pull-up is active */
++#define ST_PRGA 0x02 /* 12V programming pulse is being generated */
++#define ST_12VP 0x04 /* external 12V programming voltage is present */
++#define ST_PMOD 0x08 /* DS2490 powered from USB and external sources */
++#define ST_HALT 0x10 /* DS2490 is currently halted */
++#define ST_IDLE 0x20 /* DS2490 is currently idle */
++#define ST_EPOF 0x80
++
++#define SPEED_NORMAL 0x00
++#define SPEED_FLEXIBLE 0x01
++#define SPEED_OVERDRIVE 0x02
++
++#define NUM_EP 4
++#define EP_CONTROL 0
++#define EP_STATUS 1
++#define EP_DATA_OUT 2
++#define EP_DATA_IN 3
++
++struct ds_device
++{
++ struct list_head ds_entry;
++
++ struct usb_device *udev;
++ struct usb_interface *intf;
++
++ int ep[NUM_EP];
++
++ struct w1_bus_master master;
++};
++
++struct ds_status
++{
++ u8 enable;
++ u8 speed;
++ u8 pullup_dur;
++ u8 ppuls_dur;
++ u8 pulldown_slew;
++ u8 write1_time;
++ u8 write0_time;
++ u8 reserved0;
++ u8 status;
++ u8 command0;
++ u8 command1;
++ u8 command_buffer_status;
++ u8 data_out_buffer_status;
++ u8 data_in_buffer_status;
++ u8 reserved1;
++ u8 reserved2;
++
++};
++
++static struct usb_device_id ds_id_table [] = {
++ { USB_DEVICE(0x04fa, 0x2490) },
++ { },
++};
++MODULE_DEVICE_TABLE(usb, ds_id_table);
++
++static int ds_probe(struct usb_interface *, const struct usb_device_id *);
++static void ds_disconnect(struct usb_interface *);
++
++static inline void ds_dump_status(unsigned char *, unsigned char *, int);
++static int ds_send_control(struct ds_device *, u16, u16);
++static int ds_send_control_cmd(struct ds_device *, u16, u16);
++
++static LIST_HEAD(ds_devices);
++static DECLARE_MUTEX(ds_mutex);
++
++static struct usb_driver ds_driver = {
++ .name = "DS9490R",
++ .probe = ds_probe,
++ .disconnect = ds_disconnect,
++ .id_table = ds_id_table,
++};
++
++static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)
++{
++ int err;
++
++ err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
++ CONTROL_CMD, 0x40, value, index, NULL, 0, 1000);
++ if (err < 0) {
++ printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n",
++ value, index, err);
++ return err;
++ }
++
++ return err;
++}
++#if 0
++static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
++{
++ int err;
++
++ err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
++ MODE_CMD, 0x40, value, index, NULL, 0, 1000);
++ if (err < 0) {
++ printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n",
++ value, index, err);
++ return err;
++ }
++
++ return err;
++}
++#endif
++static int ds_send_control(struct ds_device *dev, u16 value, u16 index)
++{
++ int err;
++
++ err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
++ COMM_CMD, 0x40, value, index, NULL, 0, 1000);
++ if (err < 0) {
++ printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n",
++ value, index, err);
++ return err;
++ }
++
++ return err;
++}
++
++static inline void ds_dump_status(unsigned char *buf, unsigned char *str, int off)
++{
++ printk("%45s: %8x\n", str, buf[off]);
++}
++
++static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,
++ unsigned char *buf, int size)
++{
++ int count, err;
++
++ memset(st, 0, sizeof(st));
++
++ count = 0;
++ err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100);
++ if (err < 0) {
++ printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err);
++ return err;
++ }
++
++ if (count >= sizeof(*st))
++ memcpy(st, buf, sizeof(*st));
++
++ return count;
++}
++
++static int ds_recv_status(struct ds_device *dev, struct ds_status *st)
++{
++ unsigned char buf[64];
++ int count, err = 0, i;
++
++ memcpy(st, buf, sizeof(*st));
++
++ count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
++ if (count < 0)
++ return err;
++
++ printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count);
++ for (i=0; i<count; ++i)
++ printk("%02x ", buf[i]);
++ printk("\n");
++
++ if (count >= 16) {
++ ds_dump_status(buf, "enable flag", 0);
++ ds_dump_status(buf, "1-wire speed", 1);
++ ds_dump_status(buf, "strong pullup duration", 2);
++ ds_dump_status(buf, "programming pulse duration", 3);
++ ds_dump_status(buf, "pulldown slew rate control", 4);
++ ds_dump_status(buf, "write-1 low time", 5);
++ ds_dump_status(buf, "data sample offset/write-0 recovery time", 6);
++ ds_dump_status(buf, "reserved (test register)", 7);
++ ds_dump_status(buf, "device status flags", 8);
++ ds_dump_status(buf, "communication command byte 1", 9);
++ ds_dump_status(buf, "communication command byte 2", 10);
++ ds_dump_status(buf, "communication command buffer status", 11);
++ ds_dump_status(buf, "1-wire data output buffer status", 12);
++ ds_dump_status(buf, "1-wire data input buffer status", 13);
++ ds_dump_status(buf, "reserved", 14);
++ ds_dump_status(buf, "reserved", 15);
++ }
++
++ memcpy(st, buf, sizeof(*st));
++
++ if (st->status & ST_EPOF) {
++ printk(KERN_INFO "Resetting device after ST_EPOF.\n");
++ err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
++ if (err)
++ return err;
++ count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
++ if (count < 0)
++ return err;
++ }
++#if 0
++ if (st->status & ST_IDLE) {
++ printk(KERN_INFO "Resetting pulse after ST_IDLE.\n");
++ err = ds_start_pulse(dev, PULLUP_PULSE_DURATION);
++ if (err)
++ return err;
++ }
++#endif
++
++ return err;
++}
++
++static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
++{
++ int count, err;
++ struct ds_status st;
++
++ count = 0;
++ err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]),
++ buf, size, &count, 1000);
++ if (err < 0) {
++ printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]);
++ usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]));
++ ds_recv_status(dev, &st);
++ return err;
++ }
++
++#if 0
++ {
++ int i;
++
++ printk("%s: count=%d: ", __func__, count);
++ for (i=0; i<count; ++i)
++ printk("%02x ", buf[i]);
++ printk("\n");
++ }
++#endif
++ return count;
++}
++
++static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
++{
++ int count, err;
++
++ count = 0;
++ err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000);
++ if (err < 0) {
++ printk(KERN_ERR "Failed to read 1-wire data from 0x02: err=%d.\n", err);
++ return err;
++ }
++
++ return err;
++}
++
++#if 0
++
++int ds_stop_pulse(struct ds_device *dev, int limit)
++{
++ struct ds_status st;
++ int count = 0, err = 0;
++ u8 buf[0x20];
++
++ do {
++ err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0);
++ if (err)
++ break;
++ err = ds_send_control(dev, CTL_RESUME_EXE, 0);
++ if (err)
++ break;
++ err = ds_recv_status_nodump(dev, &st, buf, sizeof(buf));
++ if (err)
++ break;
++
++ if ((st.status & ST_SPUA) == 0) {
++ err = ds_send_control_mode(dev, MOD_PULSE_EN, 0);
++ if (err)
++ break;
++ }
++ } while(++count < limit);
++
++ return err;
++}
++
++int ds_detect(struct ds_device *dev, struct ds_status *st)
++{
++ int err;
++
++ err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
++ if (err)
++ return err;
++
++ err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0);
++ if (err)
++ return err;
++
++ err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40);
++ if (err)
++ return err;
++
++ err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG);
++ if (err)
++ return err;
++
++ err = ds_recv_status(dev, st);
++
++ return err;
++}
++
++#endif /* 0 */
++
++static int ds_wait_status(struct ds_device *dev, struct ds_status *st)
++{
++ u8 buf[0x20];
++ int err, count = 0;
++
++ do {
++ err = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
++#if 0
++ if (err >= 0) {
++ int i;
++ printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err);
++ for (i=0; i<err; ++i)
++ printk("%02x ", buf[i]);
++ printk("\n");
++ }
++#endif
++ } while(!(buf[0x08] & 0x20) && !(err < 0) && ++count < 100);
++
++
++ if (((err > 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) {
++ ds_recv_status(dev, st);
++ return -1;
++ } else
++ return 0;
++}
++
++static int ds_reset(struct ds_device *dev, struct ds_status *st)
++{
++ int err;
++
++ //err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_F | COMM_IM | COMM_SE, SPEED_FLEXIBLE);
++ err = ds_send_control(dev, 0x43, SPEED_NORMAL);
++ if (err)
++ return err;
++
++ ds_wait_status(dev, st);
++#if 0
++ if (st->command_buffer_status) {
++ printk(KERN_INFO "Short circuit.\n");
++ return -EIO;
++ }
++#endif
++
++ return 0;
++}
++
++#if 0
++static int ds_set_speed(struct ds_device *dev, int speed)
++{
++ int err;
++
++ if (speed != SPEED_NORMAL && speed != SPEED_FLEXIBLE && speed != SPEED_OVERDRIVE)
++ return -EINVAL;
++
++ if (speed != SPEED_OVERDRIVE)
++ speed = SPEED_FLEXIBLE;
++
++ speed &= 0xff;
++
++ err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed);
++ if (err)
++ return err;
++
++ return err;
++}
++#endif /* 0 */
++
++static int ds_start_pulse(struct ds_device *dev, int delay)
++{
++ int err;
++ u8 del = 1 + (u8)(delay >> 4);
++ struct ds_status st;
++
++#if 0
++ err = ds_stop_pulse(dev, 10);
++ if (err)
++ return err;
++
++ err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE);
++ if (err)
++ return err;
++#endif
++ err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del);
++ if (err)
++ return err;
++
++ err = ds_send_control(dev, COMM_PULSE | COMM_IM | COMM_F, 0);
++ if (err)
++ return err;
++
++ mdelay(delay);
++
++ ds_wait_status(dev, &st);
++
++ return err;
++}
++
++static int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit)
++{
++ int err, count;
++ struct ds_status st;
++ u16 value = (COMM_BIT_IO | COMM_IM) | ((bit) ? COMM_D : 0);
++ u16 cmd;
++
++ err = ds_send_control(dev, value, 0);
++ if (err)
++ return err;
++
++ count = 0;
++ do {
++ err = ds_wait_status(dev, &st);
++ if (err)
++ return err;
++
++ cmd = st.command0 | (st.command1 << 8);
++ } while (cmd != value && ++count < 10);
++
++ if (err < 0 || count >= 10) {
++ printk(KERN_ERR "Failed to obtain status.\n");
++ return -EINVAL;
++ }
++
++ err = ds_recv_data(dev, tbit, sizeof(*tbit));
++ if (err < 0)
++ return err;
++
++ return 0;
++}
++
++static int ds_write_bit(struct ds_device *dev, u8 bit)
++{
++ int err;
++ struct ds_status st;
++
++ err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit) ? COMM_D : 0, 0);
++ if (err)
++ return err;
++
++ ds_wait_status(dev, &st);
++
++ return 0;
++}
++
++static int ds_write_byte(struct ds_device *dev, u8 byte)
++{
++ int err;
++ struct ds_status st;
++ u8 rbyte;
++
++ err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte);
++ if (err)
++ return err;
++
++ err = ds_wait_status(dev, &st);
++ if (err)
++ return err;
++
++ err = ds_recv_data(dev, &rbyte, sizeof(rbyte));
++ if (err < 0)
++ return err;
++
++ ds_start_pulse(dev, PULLUP_PULSE_DURATION);
++
++ return !(byte == rbyte);
++}
++
++static int ds_read_byte(struct ds_device *dev, u8 *byte)
++{
++ int err;
++ struct ds_status st;
++
++ err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM , 0xff);
++ if (err)
++ return err;
++
++ ds_wait_status(dev, &st);
++
++ err = ds_recv_data(dev, byte, sizeof(*byte));
++ if (err < 0)
++ return err;
++
++ return 0;
++}
++
++static int ds_read_block(struct ds_device *dev, u8 *buf, int len)
++{
++ struct ds_status st;
++ int err;
++
++ if (len > 64*1024)
++ return -E2BIG;
++
++ memset(buf, 0xFF, len);
++
++ err = ds_send_data(dev, buf, len);
++ if (err < 0)
++ return err;
++
++ err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
++ if (err)
++ return err;
++
++ ds_wait_status(dev, &st);
++
++ memset(buf, 0x00, len);
++ err = ds_recv_data(dev, buf, len);
++
++ return err;
++}
++
++static int ds_write_block(struct ds_device *dev, u8 *buf, int len)
++{
++ int err;
++ struct ds_status st;
++
++ err = ds_send_data(dev, buf, len);
++ if (err < 0)
++ return err;
++
++ ds_wait_status(dev, &st);
++
++ err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
++ if (err)
++ return err;
++
++ ds_wait_status(dev, &st);
++
++ err = ds_recv_data(dev, buf, len);
++ if (err < 0)
++ return err;
++
++ ds_start_pulse(dev, PULLUP_PULSE_DURATION);
++
++ return !(err == len);
++}
++
++#if 0
++
++static int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search)
++{
++ int err;
++ u16 value, index;
++ struct ds_status st;
++
++ memset(buf, 0, sizeof(buf));
++
++ err = ds_send_data(ds_dev, (unsigned char *)&init, 8);
++ if (err)
++ return err;
++
++ ds_wait_status(ds_dev, &st);
++
++ value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS;
++ index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8);
++ err = ds_send_control(ds_dev, value, index);
++ if (err)
++ return err;
++
++ ds_wait_status(ds_dev, &st);
++
++ err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number);
++ if (err < 0)
++ return err;
++
++ return err/8;
++}
++
++static int ds_match_access(struct ds_device *dev, u64 init)
++{
++ int err;
++ struct ds_status st;
++
++ err = ds_send_data(dev, (unsigned char *)&init, sizeof(init));
++ if (err)
++ return err;
++
++ ds_wait_status(dev, &st);
++
++ err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055);
++ if (err)
++ return err;
++
++ ds_wait_status(dev, &st);
++
++ return 0;
++}
++
++static int ds_set_path(struct ds_device *dev, u64 init)
++{
++ int err;
++ struct ds_status st;
++ u8 buf[9];
++
++ memcpy(buf, &init, 8);
++ buf[8] = BRANCH_MAIN;
++
++ err = ds_send_data(dev, buf, sizeof(buf));
++ if (err)
++ return err;
++
++ ds_wait_status(dev, &st);
++
++ err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0);
++ if (err)
++ return err;
++
++ ds_wait_status(dev, &st);
++
++ return 0;
++}
++
++#endif /* 0 */
++
++static u8 ds9490r_touch_bit(void *data, u8 bit)
++{
++ u8 ret;
++ struct ds_device *dev = data;
++
++ if (ds_touch_bit(dev, bit, &ret))
++ return 0;
++
++ return ret;
++}
++
++static void ds9490r_write_bit(void *data, u8 bit)
++{
++ struct ds_device *dev = data;
++
++ ds_write_bit(dev, bit);
++}
++
++static void ds9490r_write_byte(void *data, u8 byte)
++{
++ struct ds_device *dev = data;
++
++ ds_write_byte(dev, byte);
++}
++
++static u8 ds9490r_read_bit(void *data)
++{
++ struct ds_device *dev = data;
++ int err;
++ u8 bit = 0;
++
++ err = ds_touch_bit(dev, 1, &bit);
++ if (err)
++ return 0;
++
++ return bit & 1;
++}
++
++static u8 ds9490r_read_byte(void *data)
++{
++ struct ds_device *dev = data;
++ int err;
++ u8 byte = 0;
++
++ err = ds_read_byte(dev, &byte);
++ if (err)
++ return 0;
++
++ return byte;
++}
++
++static void ds9490r_write_block(void *data, const u8 *buf, int len)
++{
++ struct ds_device *dev = data;
++
++ ds_write_block(dev, (u8 *)buf, len);
++}
++
++static u8 ds9490r_read_block(void *data, u8 *buf, int len)
++{
++ struct ds_device *dev = data;
++ int err;
++
++ err = ds_read_block(dev, buf, len);
++ if (err < 0)
++ return 0;
++
++ return len;
++}
++
++static u8 ds9490r_reset(void *data)
++{
++ struct ds_device *dev = data;
++ struct ds_status st;
++ int err;
++
++ memset(&st, 0, sizeof(st));
++
++ err = ds_reset(dev, &st);
++ if (err)
++ return 1;
++
++ return 0;
++}
++
++static int ds_w1_init(struct ds_device *dev)
++{
++ memset(&dev->master, 0, sizeof(struct w1_bus_master));
++
++ dev->master.data = dev;
++ dev->master.touch_bit = &ds9490r_touch_bit;
++ dev->master.read_bit = &ds9490r_read_bit;
++ dev->master.write_bit = &ds9490r_write_bit;
++ dev->master.read_byte = &ds9490r_read_byte;
++ dev->master.write_byte = &ds9490r_write_byte;
++ dev->master.read_block = &ds9490r_read_block;
++ dev->master.write_block = &ds9490r_write_block;
++ dev->master.reset_bus = &ds9490r_reset;
++
++ return w1_add_master_device(&dev->master);
++}
++
++static void ds_w1_fini(struct ds_device *dev)
++{
++ w1_remove_master_device(&dev->master);
++}
++
++static int ds_probe(struct usb_interface *intf,
++ const struct usb_device_id *udev_id)
++{
++ struct usb_device *udev = interface_to_usbdev(intf);
++ struct usb_endpoint_descriptor *endpoint;
++ struct usb_host_interface *iface_desc;
++ struct ds_device *dev;
++ int i, err;
++
++ dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL);
++ if (!dev) {
++ printk(KERN_INFO "Failed to allocate new DS9490R structure.\n");
++ return -ENOMEM;
++ }
++ dev->udev = usb_get_dev(udev);
++ if (!dev->udev) {
++ err = -ENOMEM;
++ goto err_out_free;
++ }
++ memset(dev->ep, 0, sizeof(dev->ep));
++
++ usb_set_intfdata(intf, dev);
++
++ err = usb_set_interface(dev->udev, intf->altsetting[0].desc.bInterfaceNumber, 3);
++ if (err) {
++ printk(KERN_ERR "Failed to set alternative setting 3 for %d interface: err=%d.\n",
++ intf->altsetting[0].desc.bInterfaceNumber, err);
++ goto err_out_clear;
++ }
++
++ err = usb_reset_configuration(dev->udev);
++ if (err) {
++ printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err);
++ goto err_out_clear;
++ }
++
++ iface_desc = &intf->altsetting[0];
++ if (iface_desc->desc.bNumEndpoints != NUM_EP-1) {
++ printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints);
++ err = -EINVAL;
++ goto err_out_clear;
++ }
++
++ /*
++ * This loop doesn'd show control 0 endpoint,
++ * so we will fill only 1-3 endpoints entry.
++ */
++ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
++ endpoint = &iface_desc->endpoint[i].desc;
++
++ dev->ep[i+1] = endpoint->bEndpointAddress;
++#if 0
++ printk("%d: addr=%x, size=%d, dir=%s, type=%x\n",
++ i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize),
++ (endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT",
++ endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
++#endif
++ }
++
++ err = ds_w1_init(dev);
++ if (err)
++ goto err_out_clear;
++
++ down(&ds_mutex);
++ list_add_tail(&dev->ds_entry, &ds_devices);
++ up(&ds_mutex);
++
++ return 0;
++
++err_out_clear:
++ usb_set_intfdata(intf, NULL);
++ usb_put_dev(dev->udev);
++err_out_free:
++ kfree(dev);
++ return err;
++}
++
++static void ds_disconnect(struct usb_interface *intf)
++{
++ struct ds_device *dev;
++
++ dev = usb_get_intfdata(intf);
++ if (!dev)
++ return;
++
++ down(&ds_mutex);
++ list_del(&dev->ds_entry);
++ up(&ds_mutex);
++
++ ds_w1_fini(dev);
++
++ usb_set_intfdata(intf, NULL);
++
++ usb_put_dev(dev->udev);
++ kfree(dev);
++}
++
++static int ds_init(void)
++{
++ int err;
++
++ err = usb_register(&ds_driver);
++ if (err) {
++ printk(KERN_INFO "Failed to register DS9490R USB device: err=%d.\n", err);
++ return err;
++ }
++
++ return 0;
++}
++
++static void ds_fini(void)
++{
++ usb_deregister(&ds_driver);
++}
++
++module_init(ds_init);
++module_exit(ds_fini);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
++MODULE_DESCRIPTION("DS2490 USB <-> W1 bus master driver (DS9490*)");
+--- gregkh-2.6.orig/drivers/w1/masters/ds_w1_bridge.c
++++ /dev/null
+@@ -1,174 +0,0 @@
+-/*
+- * ds_w1_bridge.c
+- *
+- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+- *
+- *
+- * 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
+- * 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/module.h>
+-#include <linux/types.h>
+-
+-#include "../w1.h"
+-#include "../w1_int.h"
+-#include "dscore.h"
+-
+-static struct ds_device *ds_dev;
+-static struct w1_bus_master *ds_bus_master;
+-
+-static u8 ds9490r_touch_bit(void *data, u8 bit)
+-{
+- u8 ret;
+- struct ds_device *dev = data;
+-
+- if (ds_touch_bit(dev, bit, &ret))
+- return 0;
+-
+- return ret;
+-}
+-
+-static void ds9490r_write_bit(void *data, u8 bit)
+-{
+- struct ds_device *dev = data;
+-
+- ds_write_bit(dev, bit);
+-}
+-
+-static void ds9490r_write_byte(void *data, u8 byte)
+-{
+- struct ds_device *dev = data;
+-
+- ds_write_byte(dev, byte);
+-}
+-
+-static u8 ds9490r_read_bit(void *data)
+-{
+- struct ds_device *dev = data;
+- int err;
+- u8 bit = 0;
+-
+- err = ds_touch_bit(dev, 1, &bit);
+- if (err)
+- return 0;
+- //err = ds_read_bit(dev, &bit);
+- //if (err)
+- // return 0;
+-
+- return bit & 1;
+-}
+-
+-static u8 ds9490r_read_byte(void *data)
+-{
+- struct ds_device *dev = data;
+- int err;
+- u8 byte = 0;
+-
+- err = ds_read_byte(dev, &byte);
+- if (err)
+- return 0;
+-
+- return byte;
+-}
+-
+-static void ds9490r_write_block(void *data, const u8 *buf, int len)
+-{
+- struct ds_device *dev = data;
+-
+- ds_write_block(dev, (u8 *)buf, len);
+-}
+-
+-static u8 ds9490r_read_block(void *data, u8 *buf, int len)
+-{
+- struct ds_device *dev = data;
+- int err;
+-
+- err = ds_read_block(dev, buf, len);
+- if (err < 0)
+- return 0;
+-
+- return len;
+-}
+-
+-static u8 ds9490r_reset(void *data)
+-{
+- struct ds_device *dev = data;
+- struct ds_status st;
+- int err;
+-
+- memset(&st, 0, sizeof(st));
+-
+- err = ds_reset(dev, &st);
+- if (err)
+- return 1;
+-
+- return 0;
+-}
+-
+-static int __devinit ds_w1_init(void)
+-{
+- int err;
+-
+- ds_bus_master = kmalloc(sizeof(*ds_bus_master), GFP_KERNEL);
+- if (!ds_bus_master) {
+- printk(KERN_ERR "Failed to allocate DS9490R USB<->W1 bus_master structure.\n");
+- return -ENOMEM;
+- }
+-
+- ds_dev = ds_get_device();
+- if (!ds_dev) {
+- printk(KERN_ERR "DS9490R is not registered.\n");
+- err = -ENODEV;
+- goto err_out_free_bus_master;
+- }
+-
+- memset(ds_bus_master, 0, sizeof(*ds_bus_master));
+-
+- ds_bus_master->data = ds_dev;
+- ds_bus_master->touch_bit = &ds9490r_touch_bit;
+- ds_bus_master->read_bit = &ds9490r_read_bit;
+- ds_bus_master->write_bit = &ds9490r_write_bit;
+- ds_bus_master->read_byte = &ds9490r_read_byte;
+- ds_bus_master->write_byte = &ds9490r_write_byte;
+- ds_bus_master->read_block = &ds9490r_read_block;
+- ds_bus_master->write_block = &ds9490r_write_block;
+- ds_bus_master->reset_bus = &ds9490r_reset;
+-
+- err = w1_add_master_device(ds_bus_master);
+- if (err)
+- goto err_out_put_device;
+-
+- return 0;
+-
+-err_out_put_device:
+- ds_put_device(ds_dev);
+-err_out_free_bus_master:
+- kfree(ds_bus_master);
+-
+- return err;
+-}
+-
+-static void __devexit ds_w1_fini(void)
+-{
+- w1_remove_master_device(ds_bus_master);
+- ds_put_device(ds_dev);
+- kfree(ds_bus_master);
+-}
+-
+-module_init(ds_w1_init);
+-module_exit(ds_w1_fini);
+-
+-MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+--- gregkh-2.6.orig/drivers/w1/masters/dscore.c
++++ /dev/null
+@@ -1,795 +0,0 @@
+-/*
+- * dscore.c
+- *
+- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+- *
+- *
+- * 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
+- * 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/module.h>
+-#include <linux/kernel.h>
+-#include <linux/mod_devicetable.h>
+-#include <linux/usb.h>
+-
+-#include "dscore.h"
+-
+-static struct usb_device_id ds_id_table [] = {
+- { USB_DEVICE(0x04fa, 0x2490) },
+- { },
+-};
+-MODULE_DEVICE_TABLE(usb, ds_id_table);
+-
+-static int ds_probe(struct usb_interface *, const struct usb_device_id *);
+-static void ds_disconnect(struct usb_interface *);
+-
+-int ds_touch_bit(struct ds_device *, u8, u8 *);
+-int ds_read_byte(struct ds_device *, u8 *);
+-int ds_read_bit(struct ds_device *, u8 *);
+-int ds_write_byte(struct ds_device *, u8);
+-int ds_write_bit(struct ds_device *, u8);
+-static int ds_start_pulse(struct ds_device *, int);
+-int ds_reset(struct ds_device *, struct ds_status *);
+-struct ds_device * ds_get_device(void);
+-void ds_put_device(struct ds_device *);
+-
+-static inline void ds_dump_status(unsigned char *, unsigned char *, int);
+-static int ds_send_control(struct ds_device *, u16, u16);
+-static int ds_send_control_mode(struct ds_device *, u16, u16);
+-static int ds_send_control_cmd(struct ds_device *, u16, u16);
+-
+-
+-static struct usb_driver ds_driver = {
+- .name = "DS9490R",
+- .probe = ds_probe,
+- .disconnect = ds_disconnect,
+- .id_table = ds_id_table,
+-};
+-
+-static struct ds_device *ds_dev;
+-
+-struct ds_device * ds_get_device(void)
+-{
+- if (ds_dev)
+- atomic_inc(&ds_dev->refcnt);
+- return ds_dev;
+-}
+-
+-void ds_put_device(struct ds_device *dev)
+-{
+- atomic_dec(&dev->refcnt);
+-}
+-
+-static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)
+-{
+- int err;
+-
+- err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
+- CONTROL_CMD, 0x40, value, index, NULL, 0, 1000);
+- if (err < 0) {
+- printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n",
+- value, index, err);
+- return err;
+- }
+-
+- return err;
+-}
+-
+-static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
+-{
+- int err;
+-
+- err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
+- MODE_CMD, 0x40, value, index, NULL, 0, 1000);
+- if (err < 0) {
+- printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n",
+- value, index, err);
+- return err;
+- }
+-
+- return err;
+-}
+-
+-static int ds_send_control(struct ds_device *dev, u16 value, u16 index)
+-{
+- int err;
+-
+- err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
+- COMM_CMD, 0x40, value, index, NULL, 0, 1000);
+- if (err < 0) {
+- printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n",
+- value, index, err);
+- return err;
+- }
+-
+- return err;
+-}
+-
+-static inline void ds_dump_status(unsigned char *buf, unsigned char *str, int off)
+-{
+- printk("%45s: %8x\n", str, buf[off]);
+-}
+-
+-static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,
+- unsigned char *buf, int size)
+-{
+- int count, err;
+-
+- memset(st, 0, sizeof(st));
+-
+- count = 0;
+- err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100);
+- if (err < 0) {
+- printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err);
+- return err;
+- }
+-
+- if (count >= sizeof(*st))
+- memcpy(st, buf, sizeof(*st));
+-
+- return count;
+-}
+-
+-static int ds_recv_status(struct ds_device *dev, struct ds_status *st)
+-{
+- unsigned char buf[64];
+- int count, err = 0, i;
+-
+- memcpy(st, buf, sizeof(*st));
+-
+- count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
+- if (count < 0)
+- return err;
+-
+- printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count);
+- for (i=0; i<count; ++i)
+- printk("%02x ", buf[i]);
+- printk("\n");
+-
+- if (count >= 16) {
+- ds_dump_status(buf, "enable flag", 0);
+- ds_dump_status(buf, "1-wire speed", 1);
+- ds_dump_status(buf, "strong pullup duration", 2);
+- ds_dump_status(buf, "programming pulse duration", 3);
+- ds_dump_status(buf, "pulldown slew rate control", 4);
+- ds_dump_status(buf, "write-1 low time", 5);
+- ds_dump_status(buf, "data sample offset/write-0 recovery time", 6);
+- ds_dump_status(buf, "reserved (test register)", 7);
+- ds_dump_status(buf, "device status flags", 8);
+- ds_dump_status(buf, "communication command byte 1", 9);
+- ds_dump_status(buf, "communication command byte 2", 10);
+- ds_dump_status(buf, "communication command buffer status", 11);
+- ds_dump_status(buf, "1-wire data output buffer status", 12);
+- ds_dump_status(buf, "1-wire data input buffer status", 13);
+- ds_dump_status(buf, "reserved", 14);
+- ds_dump_status(buf, "reserved", 15);
+- }
+-
+- memcpy(st, buf, sizeof(*st));
+-
+- if (st->status & ST_EPOF) {
+- printk(KERN_INFO "Resetting device after ST_EPOF.\n");
+- err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+- if (err)
+- return err;
+- count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
+- if (count < 0)
+- return err;
+- }
+-#if 0
+- if (st->status & ST_IDLE) {
+- printk(KERN_INFO "Resetting pulse after ST_IDLE.\n");
+- err = ds_start_pulse(dev, PULLUP_PULSE_DURATION);
+- if (err)
+- return err;
+- }
+-#endif
+-
+- return err;
+-}
+-
+-static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
+-{
+- int count, err;
+- struct ds_status st;
+-
+- count = 0;
+- err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]),
+- buf, size, &count, 1000);
+- if (err < 0) {
+- printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]);
+- usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]));
+- ds_recv_status(dev, &st);
+- return err;
+- }
+-
+-#if 0
+- {
+- int i;
+-
+- printk("%s: count=%d: ", __func__, count);
+- for (i=0; i<count; ++i)
+- printk("%02x ", buf[i]);
+- printk("\n");
+- }
+-#endif
+- return count;
+-}
+-
+-static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
+-{
+- int count, err;
+-
+- count = 0;
+- err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000);
+- if (err < 0) {
+- printk(KERN_ERR "Failed to read 1-wire data from 0x02: err=%d.\n", err);
+- return err;
+- }
+-
+- return err;
+-}
+-
+-#if 0
+-
+-int ds_stop_pulse(struct ds_device *dev, int limit)
+-{
+- struct ds_status st;
+- int count = 0, err = 0;
+- u8 buf[0x20];
+-
+- do {
+- err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0);
+- if (err)
+- break;
+- err = ds_send_control(dev, CTL_RESUME_EXE, 0);
+- if (err)
+- break;
+- err = ds_recv_status_nodump(dev, &st, buf, sizeof(buf));
+- if (err)
+- break;
+-
+- if ((st.status & ST_SPUA) == 0) {
+- err = ds_send_control_mode(dev, MOD_PULSE_EN, 0);
+- if (err)
+- break;
+- }
+- } while(++count < limit);
+-
+- return err;
+-}
+-
+-int ds_detect(struct ds_device *dev, struct ds_status *st)
+-{
+- int err;
+-
+- err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+- if (err)
+- return err;
+-
+- err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0);
+- if (err)
+- return err;
+-
+- err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40);
+- if (err)
+- return err;
+-
+- err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG);
+- if (err)
+- return err;
+-
+- err = ds_recv_status(dev, st);
+-
+- return err;
+-}
+-
+-#endif /* 0 */
+-
+-static int ds_wait_status(struct ds_device *dev, struct ds_status *st)
+-{
+- u8 buf[0x20];
+- int err, count = 0;
+-
+- do {
+- err = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
+-#if 0
+- if (err >= 0) {
+- int i;
+- printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err);
+- for (i=0; i<err; ++i)
+- printk("%02x ", buf[i]);
+- printk("\n");
+- }
+-#endif
+- } while(!(buf[0x08] & 0x20) && !(err < 0) && ++count < 100);
+-
+-
+- if (((err > 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) {
+- ds_recv_status(dev, st);
+- return -1;
+- } else
+- return 0;
+-}
+-
+-int ds_reset(struct ds_device *dev, struct ds_status *st)
+-{
+- int err;
+-
+- //err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_F | COMM_IM | COMM_SE, SPEED_FLEXIBLE);
+- err = ds_send_control(dev, 0x43, SPEED_NORMAL);
+- if (err)
+- return err;
+-
+- ds_wait_status(dev, st);
+-#if 0
+- if (st->command_buffer_status) {
+- printk(KERN_INFO "Short circuit.\n");
+- return -EIO;
+- }
+-#endif
+-
+- return 0;
+-}
+-
+-#if 0
+-int ds_set_speed(struct ds_device *dev, int speed)
+-{
+- int err;
+-
+- if (speed != SPEED_NORMAL && speed != SPEED_FLEXIBLE && speed != SPEED_OVERDRIVE)
+- return -EINVAL;
+-
+- if (speed != SPEED_OVERDRIVE)
+- speed = SPEED_FLEXIBLE;
+-
+- speed &= 0xff;
+-
+- err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed);
+- if (err)
+- return err;
+-
+- return err;
+-}
+-#endif /* 0 */
+-
+-static int ds_start_pulse(struct ds_device *dev, int delay)
+-{
+- int err;
+- u8 del = 1 + (u8)(delay >> 4);
+- struct ds_status st;
+-
+-#if 0
+- err = ds_stop_pulse(dev, 10);
+- if (err)
+- return err;
+-
+- err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE);
+- if (err)
+- return err;
+-#endif
+- err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del);
+- if (err)
+- return err;
+-
+- err = ds_send_control(dev, COMM_PULSE | COMM_IM | COMM_F, 0);
+- if (err)
+- return err;
+-
+- mdelay(delay);
+-
+- ds_wait_status(dev, &st);
+-
+- return err;
+-}
+-
+-int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit)
+-{
+- int err, count;
+- struct ds_status st;
+- u16 value = (COMM_BIT_IO | COMM_IM) | ((bit) ? COMM_D : 0);
+- u16 cmd;
+-
+- err = ds_send_control(dev, value, 0);
+- if (err)
+- return err;
+-
+- count = 0;
+- do {
+- err = ds_wait_status(dev, &st);
+- if (err)
+- return err;
+-
+- cmd = st.command0 | (st.command1 << 8);
+- } while (cmd != value && ++count < 10);
+-
+- if (err < 0 || count >= 10) {
+- printk(KERN_ERR "Failed to obtain status.\n");
+- return -EINVAL;
+- }
+-
+- err = ds_recv_data(dev, tbit, sizeof(*tbit));
+- if (err < 0)
+- return err;
+-
+- return 0;
+-}
+-
+-int ds_write_bit(struct ds_device *dev, u8 bit)
+-{
+- int err;
+- struct ds_status st;
+-
+- err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit) ? COMM_D : 0, 0);
+- if (err)
+- return err;
+-
+- ds_wait_status(dev, &st);
+-
+- return 0;
+-}
+-
+-int ds_write_byte(struct ds_device *dev, u8 byte)
+-{
+- int err;
+- struct ds_status st;
+- u8 rbyte;
+-
+- err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte);
+- if (err)
+- return err;
+-
+- err = ds_wait_status(dev, &st);
+- if (err)
+- return err;
+-
+- err = ds_recv_data(dev, &rbyte, sizeof(rbyte));
+- if (err < 0)
+- return err;
+-
+- ds_start_pulse(dev, PULLUP_PULSE_DURATION);
+-
+- return !(byte == rbyte);
+-}
+-
+-int ds_read_bit(struct ds_device *dev, u8 *bit)
+-{
+- int err;
+-
+- err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE);
+- if (err)
+- return err;
+-
+- err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | COMM_SPU | COMM_D, 0);
+- if (err)
+- return err;
+-
+- err = ds_recv_data(dev, bit, sizeof(*bit));
+- if (err < 0)
+- return err;
+-
+- return 0;
+-}
+-
+-int ds_read_byte(struct ds_device *dev, u8 *byte)
+-{
+- int err;
+- struct ds_status st;
+-
+- err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM , 0xff);
+- if (err)
+- return err;
+-
+- ds_wait_status(dev, &st);
+-
+- err = ds_recv_data(dev, byte, sizeof(*byte));
+- if (err < 0)
+- return err;
+-
+- return 0;
+-}
+-
+-int ds_read_block(struct ds_device *dev, u8 *buf, int len)
+-{
+- struct ds_status st;
+- int err;
+-
+- if (len > 64*1024)
+- return -E2BIG;
+-
+- memset(buf, 0xFF, len);
+-
+- err = ds_send_data(dev, buf, len);
+- if (err < 0)
+- return err;
+-
+- err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
+- if (err)
+- return err;
+-
+- ds_wait_status(dev, &st);
+-
+- memset(buf, 0x00, len);
+- err = ds_recv_data(dev, buf, len);
+-
+- return err;
+-}
+-
+-int ds_write_block(struct ds_device *dev, u8 *buf, int len)
+-{
+- int err;
+- struct ds_status st;
+-
+- err = ds_send_data(dev, buf, len);
+- if (err < 0)
+- return err;
+-
+- ds_wait_status(dev, &st);
+-
+- err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
+- if (err)
+- return err;
+-
+- ds_wait_status(dev, &st);
+-
+- err = ds_recv_data(dev, buf, len);
+- if (err < 0)
+- return err;
+-
+- ds_start_pulse(dev, PULLUP_PULSE_DURATION);
+-
+- return !(err == len);
+-}
+-
+-#if 0
+-
+-int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search)
+-{
+- int err;
+- u16 value, index;
+- struct ds_status st;
+-
+- memset(buf, 0, sizeof(buf));
+-
+- err = ds_send_data(ds_dev, (unsigned char *)&init, 8);
+- if (err)
+- return err;
+-
+- ds_wait_status(ds_dev, &st);
+-
+- value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS;
+- index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8);
+- err = ds_send_control(ds_dev, value, index);
+- if (err)
+- return err;
+-
+- ds_wait_status(ds_dev, &st);
+-
+- err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number);
+- if (err < 0)
+- return err;
+-
+- return err/8;
+-}
+-
+-int ds_match_access(struct ds_device *dev, u64 init)
+-{
+- int err;
+- struct ds_status st;
+-
+- err = ds_send_data(dev, (unsigned char *)&init, sizeof(init));
+- if (err)
+- return err;
+-
+- ds_wait_status(dev, &st);
+-
+- err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055);
+- if (err)
+- return err;
+-
+- ds_wait_status(dev, &st);
+-
+- return 0;
+-}
+-
+-int ds_set_path(struct ds_device *dev, u64 init)
+-{
+- int err;
+- struct ds_status st;
+- u8 buf[9];
+-
+- memcpy(buf, &init, 8);
+- buf[8] = BRANCH_MAIN;
+-
+- err = ds_send_data(dev, buf, sizeof(buf));
+- if (err)
+- return err;
+-
+- ds_wait_status(dev, &st);
+-
+- err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0);
+- if (err)
+- return err;
+-
+- ds_wait_status(dev, &st);
+-
+- return 0;
+-}
+-
+-#endif /* 0 */
+-
+-static int ds_probe(struct usb_interface *intf,
+- const struct usb_device_id *udev_id)
+-{
+- struct usb_device *udev = interface_to_usbdev(intf);
+- struct usb_endpoint_descriptor *endpoint;
+- struct usb_host_interface *iface_desc;
+- int i, err;
+-
+- ds_dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL);
+- if (!ds_dev) {
+- printk(KERN_INFO "Failed to allocate new DS9490R structure.\n");
+- return -ENOMEM;
+- }
+-
+- ds_dev->udev = usb_get_dev(udev);
+- usb_set_intfdata(intf, ds_dev);
+-
+- err = usb_set_interface(ds_dev->udev, intf->altsetting[0].desc.bInterfaceNumber, 3);
+- if (err) {
+- printk(KERN_ERR "Failed to set alternative setting 3 for %d interface: err=%d.\n",
+- intf->altsetting[0].desc.bInterfaceNumber, err);
+- return err;
+- }
+-
+- err = usb_reset_configuration(ds_dev->udev);
+- if (err) {
+- printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err);
+- return err;
+- }
+-
+- iface_desc = &intf->altsetting[0];
+- if (iface_desc->desc.bNumEndpoints != NUM_EP-1) {
+- printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints);
+- return -ENODEV;
+- }
+-
+- atomic_set(&ds_dev->refcnt, 0);
+- memset(ds_dev->ep, 0, sizeof(ds_dev->ep));
+-
+- /*
+- * This loop doesn'd show control 0 endpoint,
+- * so we will fill only 1-3 endpoints entry.
+- */
+- for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+- endpoint = &iface_desc->endpoint[i].desc;
+-
+- ds_dev->ep[i+1] = endpoint->bEndpointAddress;
+-
+- printk("%d: addr=%x, size=%d, dir=%s, type=%x\n",
+- i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize),
+- (endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT",
+- endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
+- }
+-
+-#if 0
+- {
+- int err, i;
+- u64 buf[3];
+- u64 init=0xb30000002078ee81ull;
+- struct ds_status st;
+-
+- ds_reset(ds_dev, &st);
+- err = ds_search(ds_dev, init, buf, 3, 0);
+- if (err < 0)
+- return err;
+- for (i=0; i<err; ++i)
+- printk("%d: %llx\n", i, buf[i]);
+-
+- printk("Resetting...\n");
+- ds_reset(ds_dev, &st);
+- printk("Setting path for %llx.\n", init);
+- err = ds_set_path(ds_dev, init);
+- if (err)
+- return err;
+- printk("Calling MATCH_ACCESS.\n");
+- err = ds_match_access(ds_dev, init);
+- if (err)
+- return err;
+-
+- printk("Searching the bus...\n");
+- err = ds_search(ds_dev, init, buf, 3, 0);
+-
+- printk("ds_search() returned %d\n", err);
+-
+- if (err < 0)
+- return err;
+- for (i=0; i<err; ++i)
+- printk("%d: %llx\n", i, buf[i]);
+-
+- return 0;
+- }
+-#endif
+-
+- return 0;
+-}
+-
+-static void ds_disconnect(struct usb_interface *intf)
+-{
+- struct ds_device *dev;
+-
+- dev = usb_get_intfdata(intf);
+- usb_set_intfdata(intf, NULL);
+-
+- while (atomic_read(&dev->refcnt)) {
+- printk(KERN_INFO "Waiting for DS to become free: refcnt=%d.\n",
+- atomic_read(&dev->refcnt));
+-
+- if (msleep_interruptible(1000))
+- flush_signals(current);
+- }
+-
+- usb_put_dev(dev->udev);
+- kfree(dev);
+- ds_dev = NULL;
+-}
+-
+-static int ds_init(void)
+-{
+- int err;
+-
+- err = usb_register(&ds_driver);
+- if (err) {
+- printk(KERN_INFO "Failed to register DS9490R USB device: err=%d.\n", err);
+- return err;
+- }
+-
+- return 0;
+-}
+-
+-static void ds_fini(void)
+-{
+- usb_deregister(&ds_driver);
+-}
+-
+-module_init(ds_init);
+-module_exit(ds_fini);
+-
+-MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+-
+-EXPORT_SYMBOL(ds_touch_bit);
+-EXPORT_SYMBOL(ds_read_byte);
+-EXPORT_SYMBOL(ds_read_bit);
+-EXPORT_SYMBOL(ds_read_block);
+-EXPORT_SYMBOL(ds_write_byte);
+-EXPORT_SYMBOL(ds_write_bit);
+-EXPORT_SYMBOL(ds_write_block);
+-EXPORT_SYMBOL(ds_reset);
+-EXPORT_SYMBOL(ds_get_device);
+-EXPORT_SYMBOL(ds_put_device);
+-
+-/*
+- * This functions can be used for EEPROM programming,
+- * when driver will be included into mainline this will
+- * require uncommenting.
+- */
+-#if 0
+-EXPORT_SYMBOL(ds_start_pulse);
+-EXPORT_SYMBOL(ds_set_speed);
+-EXPORT_SYMBOL(ds_detect);
+-EXPORT_SYMBOL(ds_stop_pulse);
+-EXPORT_SYMBOL(ds_search);
+-#endif
+--- gregkh-2.6.orig/drivers/w1/masters/dscore.h
++++ /dev/null
+@@ -1,166 +0,0 @@
+-/*
+- * dscore.h
+- *
+- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+- *
+- *
+- * 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
+- * 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
+- */
+-
+-#ifndef __DSCORE_H
+-#define __DSCORE_H
+-
+-#include <linux/usb.h>
+-#include <asm/atomic.h>
+-
+-/* COMMAND TYPE CODES */
+-#define CONTROL_CMD 0x00
+-#define COMM_CMD 0x01
+-#define MODE_CMD 0x02
+-
+-/* CONTROL COMMAND CODES */
+-#define CTL_RESET_DEVICE 0x0000
+-#define CTL_START_EXE 0x0001
+-#define CTL_RESUME_EXE 0x0002
+-#define CTL_HALT_EXE_IDLE 0x0003
+-#define CTL_HALT_EXE_DONE 0x0004
+-#define CTL_FLUSH_COMM_CMDS 0x0007
+-#define CTL_FLUSH_RCV_BUFFER 0x0008
+-#define CTL_FLUSH_XMT_BUFFER 0x0009
+-#define CTL_GET_COMM_CMDS 0x000A
+-
+-/* MODE COMMAND CODES */
+-#define MOD_PULSE_EN 0x0000
+-#define MOD_SPEED_CHANGE_EN 0x0001
+-#define MOD_1WIRE_SPEED 0x0002
+-#define MOD_STRONG_PU_DURATION 0x0003
+-#define MOD_PULLDOWN_SLEWRATE 0x0004
+-#define MOD_PROG_PULSE_DURATION 0x0005
+-#define MOD_WRITE1_LOWTIME 0x0006
+-#define MOD_DSOW0_TREC 0x0007
+-
+-/* COMMUNICATION COMMAND CODES */
+-#define COMM_ERROR_ESCAPE 0x0601
+-#define COMM_SET_DURATION 0x0012
+-#define COMM_BIT_IO 0x0020
+-#define COMM_PULSE 0x0030
+-#define COMM_1_WIRE_RESET 0x0042
+-#define COMM_BYTE_IO 0x0052
+-#define COMM_MATCH_ACCESS 0x0064
+-#define COMM_BLOCK_IO 0x0074
+-#define COMM_READ_STRAIGHT 0x0080
+-#define COMM_DO_RELEASE 0x6092
+-#define COMM_SET_PATH 0x00A2
+-#define COMM_WRITE_SRAM_PAGE 0x00B2
+-#define COMM_WRITE_EPROM 0x00C4
+-#define COMM_READ_CRC_PROT_PAGE 0x00D4
+-#define COMM_READ_REDIRECT_PAGE_CRC 0x21E4
+-#define COMM_SEARCH_ACCESS 0x00F4
+-
+-/* Communication command bits */
+-#define COMM_TYPE 0x0008
+-#define COMM_SE 0x0008
+-#define COMM_D 0x0008
+-#define COMM_Z 0x0008
+-#define COMM_CH 0x0008
+-#define COMM_SM 0x0008
+-#define COMM_R 0x0008
+-#define COMM_IM 0x0001
+-
+-#define COMM_PS 0x4000
+-#define COMM_PST 0x4000
+-#define COMM_CIB 0x4000
+-#define COMM_RTS 0x4000
+-#define COMM_DT 0x2000
+-#define COMM_SPU 0x1000
+-#define COMM_F 0x0800
+-#define COMM_NTP 0x0400
+-#define COMM_ICP 0x0200
+-#define COMM_RST 0x0100
+-
+-#define PULSE_PROG 0x01
+-#define PULSE_SPUE 0x02
+-
+-#define BRANCH_MAIN 0xCC
+-#define BRANCH_AUX 0x33
+-
+-/*
+- * Duration of the strong pull-up pulse in milliseconds.
+- */
+-#define PULLUP_PULSE_DURATION 750
+-
+-/* Status flags */
+-#define ST_SPUA 0x01 /* Strong Pull-up is active */
+-#define ST_PRGA 0x02 /* 12V programming pulse is being generated */
+-#define ST_12VP 0x04 /* external 12V programming voltage is present */
+-#define ST_PMOD 0x08 /* DS2490 powered from USB and external sources */
+-#define ST_HALT 0x10 /* DS2490 is currently halted */
+-#define ST_IDLE 0x20 /* DS2490 is currently idle */
+-#define ST_EPOF 0x80
+-
+-#define SPEED_NORMAL 0x00
+-#define SPEED_FLEXIBLE 0x01
+-#define SPEED_OVERDRIVE 0x02
+-
+-#define NUM_EP 4
+-#define EP_CONTROL 0
+-#define EP_STATUS 1
+-#define EP_DATA_OUT 2
+-#define EP_DATA_IN 3
+-
+-struct ds_device
+-{
+- struct usb_device *udev;
+- struct usb_interface *intf;
+-
+- int ep[NUM_EP];
+-
+- atomic_t refcnt;
+-};
+-
+-struct ds_status
+-{
+- u8 enable;
+- u8 speed;
+- u8 pullup_dur;
+- u8 ppuls_dur;
+- u8 pulldown_slew;
+- u8 write1_time;
+- u8 write0_time;
+- u8 reserved0;
+- u8 status;
+- u8 command0;
+- u8 command1;
+- u8 command_buffer_status;
+- u8 data_out_buffer_status;
+- u8 data_in_buffer_status;
+- u8 reserved1;
+- u8 reserved2;
+-
+-};
+-
+-int ds_touch_bit(struct ds_device *, u8, u8 *);
+-int ds_read_byte(struct ds_device *, u8 *);
+-int ds_read_bit(struct ds_device *, u8 *);
+-int ds_write_byte(struct ds_device *, u8);
+-int ds_write_bit(struct ds_device *, u8);
+-int ds_reset(struct ds_device *, struct ds_status *);
+-struct ds_device * ds_get_device(void);
+-void ds_put_device(struct ds_device *);
+-int ds_write_block(struct ds_device *, u8 *, int);
+-int ds_read_block(struct ds_device *, u8 *, int);
+-
+-#endif /* __DSCORE_H */
+-
diff --git a/i2c/w1-userspace-communication-protocol-over-connector.patch b/i2c/w1-userspace-communication-protocol-over-connector.patch
new file mode 100644
index 0000000000000..08afc9518e743
--- /dev/null
+++ b/i2c/w1-userspace-communication-protocol-over-connector.patch
@@ -0,0 +1,1045 @@
+From johnpol@2ka.mipt.ru Thu Mar 23 08:00:09 2006
+Cc: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+Subject: [PATCH 3/5] w1: Userspace communication protocol over connector.
+Date: Thu, 23 Mar 2006 19:11:58 +0300
+Message-Id: <11431303182850@2ka.mipt.ru>
+To: GregKH <greg@kroah.com>
+From: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+
+
+There are three types of messages between w1 core and userspace:
+1. Events. They are generated each time new master or slave device found
+ either due to automatic or requested search.
+2. Userspace commands. Includes read/write and search/alarm search comamnds.
+3. Replies to userspace commands.
+
+
+From: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ Documentation/w1/w1.netlink | 98 ++++++++++++++++++
+ drivers/w1/Makefile | 2
+ drivers/w1/slaves/w1_ds2433.c | 1
+ drivers/w1/slaves/w1_smem.c | 1
+ drivers/w1/slaves/w1_therm.c | 1
+ drivers/w1/w1.c | 141 ++++++++++++++++++--------
+ drivers/w1/w1.h | 38 +++----
+ drivers/w1/w1_family.h | 1
+ drivers/w1/w1_int.c | 27 ++---
+ drivers/w1/w1_io.c | 18 ---
+ drivers/w1/w1_netlink.c | 221 +++++++++++++++++++++++++++++++++++-------
+ drivers/w1/w1_netlink.h | 38 +++++--
+ 12 files changed, 450 insertions(+), 137 deletions(-)
+
+--- /dev/null
++++ gregkh-2.6/Documentation/w1/w1.netlink
+@@ -0,0 +1,98 @@
++Userspace communication protocol over connector [1].
++
++
++Message types.
++=============
++
++There are three types of messages between w1 core and userspace:
++1. Events. They are generated each time new master or slave device found
++ either due to automatic or requested search.
++2. Userspace commands. Includes read/write and search/alarm search comamnds.
++3. Replies to userspace commands.
++
++
++Protocol.
++========
++
++[struct cn_msg] - connector header. It's length field is equal to size of the attached data.
++[struct w1_netlink_msg] - w1 netlink header.
++ __u8 type - message type.
++ W1_SLAVE_ADD/W1_SLAVE_REMOVE - slave add/remove events.
++ W1_MASTER_ADD/W1_MASTER_REMOVE - master add/remove events.
++ W1_MASTER_CMD - userspace command for bus master device (search/alarm search).
++ W1_SLAVE_CMD - userspace command for slave device (read/write/ search/alarm search
++ for bus master device where given slave device found).
++ __u8 res - reserved
++ __u16 len - size of attached to this header data.
++ union {
++ __u8 id; - slave unique device id
++ struct w1_mst {
++ __u32 id; - master's id.
++ __u32 res; - reserved
++ } mst;
++ } id;
++
++[strucrt w1_netlink_cmd] - command for gived master or slave device.
++ __u8 cmd - command opcode.
++ W1_CMD_READ - read command.
++ W1_CMD_WRITE - write command.
++ W1_CMD_SEARCH - search command.
++ W1_CMD_ALARM_SEARCH - alarm search command.
++ __u8 res - reserved
++ __u16 len - length of data for this command.
++ For read command data must be allocated like for write command.
++ __u8 data[0] - data for this command.
++
++
++Each connector message can include one or more w1_netlink_msg with zero of more attached w1_netlink_cmd messages.
++
++For event messages there are no w1_netlink_cmd embedded structures, only connector header
++and w1_netlink_msg strucutre with "len" field being zero and filled type (one of event types)
++and id - either 8 bytes of slave unique id in host order, or master's id, which is assigned
++to bus master device when it is added to w1 core.
++
++Currently replies to userspace commands are only generated for read command request.
++One reply is generated exactly for one w1_netlink_cmd read request.
++Replies are not combined when sent - i.e. typical reply messages looks like the following:
++[cn_msg][w1_netlink_msg][w1_netlink_cmd]
++cn_msg.len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd) + cmd->len;
++w1_netlink_msg.len = sizeof(struct w1_netlink_cmd) + cmd->len;
++w1_netlink_cmd.len = cmd->len;
++
++
++Operation steps in w1 core when new command is received.
++=======================================================
++
++When new message (w1_netlink_msg) is received w1 core detects if it is master of slave request,
++according to w1_netlink_msg.type field.
++Then master or slave device is searched for.
++When found, master device (requested or those one on where slave device is found) is locked.
++If slave command is requested, then reset/select procedure is started to select given device.
++
++Then all requested in w1_netlink_msg operations are performed one by one.
++If command requires reply (like read command) it is sent on command completion.
++
++When all commands (w1_netlink_cmd) are processed muster device is unlocked
++and next w1_netlink_msg header processing started.
++
++
++Connector [1] specific documentation.
++====================================
++
++Each connector message includes two u32 fields as "address".
++w1 uses CN_W1_IDX and CN_W1_VAL defined in include/linux/connector.h header.
++Each message also includes sequence and acknowledge numbers.
++Sequence number for event messages is appropriate bus master sequence number increased with
++each event message sent "through" this master.
++Sequence number for userspace requests is set by userspace application.
++Sequence number for reply is the same as was in request, and
++acknowledge number is set to seq+1.
++
++
++Additional documantion, source code examples.
++============================================
++
++1. Documentation/connector
++2. http://tservice.net.ru/~s0mbre/archive/w1
++This archive includes userspace application w1d.c which
++uses read/write/search commands for all master/slave devices found on the bus.
+--- gregkh-2.6.orig/drivers/w1/Makefile
++++ gregkh-2.6/drivers/w1/Makefile
+@@ -2,7 +2,7 @@
+ # Makefile for the Dallas's 1-wire bus.
+ #
+
+-ifneq ($(CONFIG_NET), y)
++ifeq ($(CONFIG_CONNECTOR), n)
+ EXTRA_CFLAGS += -DNETLINK_DISABLED
+ endif
+
+--- gregkh-2.6.orig/drivers/w1/slaves/w1_ds2433.c
++++ gregkh-2.6/drivers/w1/slaves/w1_ds2433.c
+@@ -22,7 +22,6 @@
+ #endif
+
+ #include "../w1.h"
+-#include "../w1_io.h"
+ #include "../w1_int.h"
+ #include "../w1_family.h"
+
+--- gregkh-2.6.orig/drivers/w1/slaves/w1_smem.c
++++ gregkh-2.6/drivers/w1/slaves/w1_smem.c
+@@ -28,7 +28,6 @@
+ #include <linux/types.h>
+
+ #include "../w1.h"
+-#include "../w1_io.h"
+ #include "../w1_int.h"
+ #include "../w1_family.h"
+
+--- gregkh-2.6.orig/drivers/w1/slaves/w1_therm.c
++++ gregkh-2.6/drivers/w1/slaves/w1_therm.c
+@@ -29,7 +29,6 @@
+ #include <linux/delay.h>
+
+ #include "../w1.h"
+-#include "../w1_io.h"
+ #include "../w1_int.h"
+ #include "../w1_family.h"
+
+--- gregkh-2.6.orig/drivers/w1/w1.c
++++ gregkh-2.6/drivers/w1/w1.c
+@@ -35,7 +35,6 @@
+ #include <asm/atomic.h>
+
+ #include "w1.h"
+-#include "w1_io.h"
+ #include "w1_log.h"
+ #include "w1_int.h"
+ #include "w1_family.h"
+@@ -55,7 +54,7 @@ module_param_named(control_timeout, w1_c
+ module_param_named(max_slave_count, w1_max_slave_count, int, 0);
+ module_param_named(slave_ttl, w1_max_slave_ttl, int, 0);
+
+-DEFINE_SPINLOCK(w1_mlock);
++DECLARE_MUTEX(w1_mlock);
+ LIST_HEAD(w1_masters);
+
+ static struct task_struct *w1_control_thread;
+@@ -75,8 +74,6 @@ static void w1_master_release(struct dev
+ struct w1_master *md = dev_to_w1_master(dev);
+
+ dev_dbg(dev, "%s: Releasing %s.\n", __func__, md->name);
+-
+- dev_fini_netlink(md);
+ memset(md, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master));
+ kfree(md);
+ }
+@@ -85,10 +82,10 @@ static void w1_slave_release(struct devi
+ {
+ struct w1_slave *sl = dev_to_w1_slave(dev);
+
+- dev_dbg(dev, "%s: Releasing %s.\n", __func__, sl->name);
++ printk("%s: Releasing %s.\n", __func__, sl->name);
+
+ while (atomic_read(&sl->refcnt)) {
+- dev_dbg(dev, "Waiting for %s to become free: refcnt=%d.\n",
++ printk("Waiting for %s to become free: refcnt=%d.\n",
+ sl->name, atomic_read(&sl->refcnt));
+ if (msleep_interruptible(1000))
+ flush_signals(current);
+@@ -111,7 +108,6 @@ static ssize_t w1_slave_read_id(struct k
+ {
+ struct w1_slave *sl = kobj_to_w1_slave(kobj);
+
+- atomic_inc(&sl->refcnt);
+ if (off > 8) {
+ count = 0;
+ } else {
+@@ -120,7 +116,6 @@ static ssize_t w1_slave_read_id(struct k
+
+ memcpy(buf, (u8 *)&sl->reg_num, count);
+ }
+- atomic_dec(&sl->refcnt);
+
+ return count;
+ }
+@@ -230,12 +225,11 @@ struct device w1_master_device = {
+ .release = &w1_master_release
+ };
+
+-static struct device_driver w1_slave_driver = {
++struct device_driver w1_slave_driver = {
+ .name = "w1_slave_driver",
+ .bus = &w1_bus_type,
+ };
+
+-#if 0
+ struct device w1_slave_device = {
+ .parent = NULL,
+ .bus = &w1_bus_type,
+@@ -243,7 +237,6 @@ struct device w1_slave_device = {
+ .driver = &w1_slave_driver,
+ .release = &w1_slave_release
+ };
+-#endif /* 0 */
+
+ static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+@@ -423,7 +416,7 @@ int w1_create_master_attributes(struct w
+ return sysfs_create_group(&master->dev.kobj, &w1_master_defattr_group);
+ }
+
+-static void w1_destroy_master_attributes(struct w1_master *master)
++void w1_destroy_master_attributes(struct w1_master *master)
+ {
+ sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group);
+ }
+@@ -454,14 +447,11 @@ static int w1_uevent(struct device *dev,
+ if (dev->driver != &w1_slave_driver || !sl)
+ return 0;
+
+- err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size,
+- &cur_len, "W1_FID=%02X", sl->reg_num.family);
++ err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_FID=%02X", sl->reg_num.family);
+ if (err)
+ return err;
+
+- err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size,
+- &cur_len, "W1_SLAVE_ID=%024LX",
+- (unsigned long long)sl->reg_num.id);
++ err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_SLAVE_ID=%024LX", (u64)sl->reg_num.id);
+ if (err)
+ return err;
+
+@@ -563,6 +553,7 @@ static int w1_attach_slave_device(struct
+ sl->master = dev;
+ set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
+
++ memset(&msg, 0, sizeof(msg));
+ memcpy(&sl->reg_num, rn, sizeof(sl->reg_num));
+ atomic_set(&sl->refcnt, 0);
+ init_completion(&sl->released);
+@@ -593,7 +584,7 @@ static int w1_attach_slave_device(struct
+ sl->ttl = dev->slave_ttl;
+ dev->slave_count++;
+
+- memcpy(&msg.id.id, rn, sizeof(msg.id.id));
++ memcpy(msg.id.id, rn, sizeof(msg.id));
+ msg.type = W1_SLAVE_ADD;
+ w1_netlink_send(dev, &msg);
+
+@@ -611,7 +602,8 @@ static void w1_slave_detach(struct w1_sl
+ if (sl->family->fops && sl->family->fops->remove_slave)
+ sl->family->fops->remove_slave(sl);
+
+- memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id));
++ memset(&msg, 0, sizeof(msg));
++ memcpy(msg.id.id, &sl->reg_num, sizeof(msg.id));
+ msg.type = W1_SLAVE_REMOVE;
+ w1_netlink_send(sl->master, &msg);
+
+@@ -628,7 +620,7 @@ static struct w1_master *w1_search_maste
+ struct w1_master *dev;
+ int found = 0;
+
+- spin_lock_bh(&w1_mlock);
++ down(&w1_mlock);
+ list_for_each_entry(dev, &w1_masters, w1_master_entry) {
+ if (dev->bus_master->data == data) {
+ found = 1;
+@@ -636,22 +628,69 @@ static struct w1_master *w1_search_maste
+ break;
+ }
+ }
+- spin_unlock_bh(&w1_mlock);
++ up(&w1_mlock);
++
++ return (found)?dev:NULL;
++}
++
++struct w1_master *w1_search_master_id(u32 id)
++{
++ struct w1_master *dev;
++ int found = 0;
++
++ down(&w1_mlock);
++ list_for_each_entry(dev, &w1_masters, w1_master_entry) {
++ if (dev->id == id) {
++ found = 1;
++ atomic_inc(&dev->refcnt);
++ break;
++ }
++ }
++ up(&w1_mlock);
+
+ return (found)?dev:NULL;
+ }
+
++struct w1_slave *w1_search_slave(struct w1_reg_num *id)
++{
++ struct w1_master *dev;
++ struct w1_slave *sl = NULL;
++ int found = 0;
++
++ down(&w1_mlock);
++ list_for_each_entry(dev, &w1_masters, w1_master_entry) {
++ down(&dev->mutex);
++ list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
++ if (sl->reg_num.family == id->family &&
++ sl->reg_num.id == id->id &&
++ sl->reg_num.crc == id->crc) {
++ found = 1;
++ atomic_inc(&dev->refcnt);
++ atomic_inc(&sl->refcnt);
++ break;
++ }
++ }
++ up(&dev->mutex);
++
++ if (found)
++ break;
++ }
++ up(&w1_mlock);
++
++ return (found)?sl:NULL;
++}
++
+ void w1_reconnect_slaves(struct w1_family *f)
+ {
+ struct w1_master *dev;
+
+- spin_lock_bh(&w1_mlock);
++ down(&w1_mlock);
+ list_for_each_entry(dev, &w1_masters, w1_master_entry) {
+ dev_dbg(&dev->dev, "Reconnecting slaves in %s into new family %02x.\n",
+ dev->name, f->fid);
+ set_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
+ }
+- spin_unlock_bh(&w1_mlock);
++ up(&w1_mlock);
+ }
+
+ static void w1_slave_found(void *data, u64 rn)
+@@ -713,7 +752,7 @@ static void w1_slave_found(void *data, u
+ * @dev The master device to search
+ * @cb Function to call when a device is found
+ */
+-void w1_search(struct w1_master *dev, w1_slave_found_callback cb)
++void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb)
+ {
+ u64 last_rn, rn, tmp64;
+ int i, slave_count = 0;
+@@ -744,7 +783,7 @@ void w1_search(struct w1_master *dev, w1
+ }
+
+ /* Start the search */
+- w1_write_8(dev, W1_SEARCH);
++ w1_write_8(dev, search_type);
+ for (i = 0; i < 64; ++i) {
+ /* Determine the direction/search bit */
+ if (i == desc_bit)
+@@ -806,9 +845,9 @@ static int w1_control(void *data)
+ if (kthread_should_stop() || test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
+ set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
+
+- spin_lock(&w1_mlock);
++ down(&w1_mlock);
+ list_del(&dev->w1_master_entry);
+- spin_unlock(&w1_mlock);
++ up(&w1_mlock);
+
+ down(&dev->mutex);
+ list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
+@@ -843,10 +882,31 @@ static int w1_control(void *data)
+ return 0;
+ }
+
++void w1_search_process(struct w1_master *dev, u8 search_type)
++{
++ struct w1_slave *sl, *sln;
++
++ list_for_each_entry(sl, &dev->slist, w1_slave_entry)
++ clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
++
++ w1_search_devices(dev, search_type, w1_slave_found);
++
++ list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
++ if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) {
++ w1_slave_detach(sl);
++
++ dev->slave_count--;
++ } else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags))
++ sl->ttl = dev->slave_ttl;
++ }
++
++ if (dev->search_count > 0)
++ dev->search_count--;
++}
++
+ int w1_process(void *data)
+ {
+ struct w1_master *dev = (struct w1_master *) data;
+- struct w1_slave *sl, *sln;
+
+ while (!kthread_should_stop() && !test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
+ try_to_freeze();
+@@ -864,28 +924,13 @@ int w1_process(void *data)
+ if (down_interruptible(&dev->mutex))
+ continue;
+
+- list_for_each_entry(sl, &dev->slist, w1_slave_entry)
+- clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
+-
+- w1_search_devices(dev, w1_slave_found);
+-
+- list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
+- if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) {
+- w1_slave_detach(sl);
+-
+- dev->slave_count--;
+- } else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags))
+- sl->ttl = dev->slave_ttl;
+- }
+-
+- if (dev->search_count > 0)
+- dev->search_count--;
+-
++ w1_search_process(dev, W1_SEARCH);
++
+ up(&dev->mutex);
+ }
+
+ atomic_dec(&dev->refcnt);
+-
++
+ return 0;
+ }
+
+@@ -895,6 +940,8 @@ static int w1_init(void)
+
+ printk(KERN_INFO "Driver for 1-wire Dallas network protocol.\n");
+
++ w1_init_netlink();
++
+ retval = bus_register(&w1_bus_type);
+ if (retval) {
+ printk(KERN_ERR "Failed to register bus. err=%d.\n", retval);
+@@ -946,6 +993,8 @@ static void w1_fini(void)
+
+ list_for_each_entry(dev, &w1_masters, w1_master_entry)
+ __w1_remove_master_device(dev);
++
++ w1_fini_netlink();
+
+ kthread_stop(w1_control_thread);
+
+--- gregkh-2.6.orig/drivers/w1/w1.h
++++ gregkh-2.6/drivers/w1/w1.h
+@@ -42,8 +42,6 @@ struct w1_reg_num
+ #include <linux/completion.h>
+ #include <linux/device.h>
+
+-#include <net/sock.h>
+-
+ #include <asm/semaphore.h>
+
+ #include "w1_family.h"
+@@ -52,7 +50,7 @@ struct w1_reg_num
+ #define W1_SLAVE_DATA_SIZE 128
+
+ #define W1_SEARCH 0xF0
+-#define W1_CONDITIONAL_SEARCH 0xEC
++#define W1_ALARM_SEARCH 0xEC
+ #define W1_CONVERT_TEMP 0x44
+ #define W1_SKIP_ROM 0xCC
+ #define W1_READ_SCRATCHPAD 0xBE
+@@ -145,8 +143,8 @@ struct w1_bus_master
+ */
+ u8 (*reset_bus)(void *);
+
+- /** Really nice hardware can handles the ROM searches */
+- void (*search)(void *, w1_slave_found_callback);
++ /** Really nice hardware can handles the different types of ROM search */
++ void (*search)(void *, u8, w1_slave_found_callback);
+ };
+
+ #define W1_MASTER_NEED_EXIT 0
+@@ -180,12 +178,26 @@ struct w1_master
+
+ struct w1_bus_master *bus_master;
+
+- u32 seq, groups;
+- struct sock *nls;
++ u32 seq;
+ };
+
+ int w1_create_master_attributes(struct w1_master *);
+-void w1_search(struct w1_master *dev, w1_slave_found_callback cb);
++void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb);
++void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb);
++struct w1_slave *w1_search_slave(struct w1_reg_num *id);
++void w1_search_process(struct w1_master *dev, u8 search_type);
++struct w1_master *w1_search_master_id(u32 id);
++
++void w1_delay(unsigned long);
++u8 w1_touch_bit(struct w1_master *, int);
++u8 w1_triplet(struct w1_master *dev, int bdir);
++void w1_write_8(struct w1_master *, u8);
++u8 w1_read_8(struct w1_master *);
++int w1_reset_bus(struct w1_master *);
++u8 w1_calc_crc8(u8 *, int);
++void w1_write_block(struct w1_master *, const u8 *, int);
++u8 w1_read_block(struct w1_master *, u8 *, int);
++int w1_reset_select_slave(struct w1_slave *sl);
+
+ static inline struct w1_slave* dev_to_w1_slave(struct device *dev)
+ {
+@@ -202,16 +214,6 @@ static inline struct w1_master* dev_to_w
+ return container_of(dev, struct w1_master, dev);
+ }
+
+-extern int w1_max_slave_count;
+-extern int w1_max_slave_ttl;
+-extern spinlock_t w1_mlock;
+-extern struct list_head w1_masters;
+-extern struct device_driver w1_master_driver;
+-extern struct device w1_master_device;
+-
+-int w1_process(void *data);
+-void w1_reconnect_slaves(struct w1_family *f);
+-
+ #endif /* __KERNEL__ */
+
+ #endif /* __W1_H */
+--- gregkh-2.6.orig/drivers/w1/w1_family.h
++++ gregkh-2.6/drivers/w1/w1_family.h
+@@ -64,5 +64,6 @@ void __w1_family_put(struct w1_family *)
+ struct w1_family * w1_family_registered(u8);
+ void w1_unregister_family(struct w1_family *);
+ int w1_register_family(struct w1_family *);
++void w1_reconnect_slaves(struct w1_family *f);
+
+ #endif /* __W1_FAMILY_H */
+--- gregkh-2.6.orig/drivers/w1/w1_int.c
++++ gregkh-2.6/drivers/w1/w1_int.c
+@@ -27,10 +27,19 @@
+ #include "w1.h"
+ #include "w1_log.h"
+ #include "w1_netlink.h"
+-#include "w1_int.h"
+
+ static u32 w1_ids = 1;
+
++extern struct device_driver w1_master_driver;
++extern struct bus_type w1_bus_type;
++extern struct device w1_master_device;
++extern int w1_max_slave_count;
++extern int w1_max_slave_ttl;
++extern struct list_head w1_masters;
++extern struct semaphore w1_mlock;
++
++extern int w1_process(void *);
++
+ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
+ struct device_driver *driver,
+ struct device *device)
+@@ -74,16 +83,11 @@ static struct w1_master * w1_alloc_dev(u
+
+ dev->driver = driver;
+
+- dev->groups = 1;
+ dev->seq = 1;
+- dev_init_netlink(dev);
+
+ err = device_register(&dev->dev);
+ if (err) {
+ printk(KERN_ERR "Failed to register master device. err=%d\n", err);
+-
+- dev_fini_netlink(dev);
+-
+ memset(dev, 0, sizeof(struct w1_master));
+ kfree(dev);
+ dev = NULL;
+@@ -92,7 +96,7 @@ static struct w1_master * w1_alloc_dev(u
+ return dev;
+ }
+
+-static void w1_free_dev(struct w1_master *dev)
++void w1_free_dev(struct w1_master *dev)
+ {
+ device_unregister(&dev->dev);
+ }
+@@ -131,12 +135,12 @@ int w1_add_master_device(struct w1_bus_m
+
+ dev->initialized = 1;
+
+- spin_lock(&w1_mlock);
++ down(&w1_mlock);
+ list_add(&dev->w1_master_entry, &w1_masters);
+- spin_unlock(&w1_mlock);
++ up(&w1_mlock);
+
++ memset(&msg, 0, sizeof(msg));
+ msg.id.mst.id = dev->id;
+- msg.id.mst.pid = dev->thread->pid;
+ msg.type = W1_MASTER_ADD;
+ w1_netlink_send(dev, &msg);
+
+@@ -153,7 +157,6 @@ err_out_free_dev:
+ void __w1_remove_master_device(struct w1_master *dev)
+ {
+ struct w1_netlink_msg msg;
+- pid_t pid = dev->thread->pid;
+
+ set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
+ kthread_stop(dev->thread);
+@@ -166,8 +169,8 @@ void __w1_remove_master_device(struct w1
+ flush_signals(current);
+ }
+
++ memset(&msg, 0, sizeof(msg));
+ msg.id.mst.id = dev->id;
+- msg.id.mst.pid = pid;
+ msg.type = W1_MASTER_REMOVE;
+ w1_netlink_send(dev, &msg);
+
+--- gregkh-2.6.orig/drivers/w1/w1_io.c
++++ gregkh-2.6/drivers/w1/w1_io.c
+@@ -26,7 +26,6 @@
+
+ #include "w1.h"
+ #include "w1_log.h"
+-#include "w1_io.h"
+
+ static int w1_delay_parm = 1;
+ module_param_named(delay_coef, w1_delay_parm, int, 0);
+@@ -268,13 +267,13 @@ u8 w1_calc_crc8(u8 * data, int len)
+ return crc;
+ }
+
+-void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb)
++void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb)
+ {
+ dev->attempts++;
+ if (dev->bus_master->search)
+- dev->bus_master->search(dev->bus_master->data, cb);
++ dev->bus_master->search(dev->bus_master->data, search_type, cb);
+ else
+- w1_search(dev, cb);
++ w1_search(dev, search_type, cb);
+ }
+
+ /**
+@@ -300,13 +299,4 @@ int w1_reset_select_slave(struct w1_slav
+ return 0;
+ }
+
+-EXPORT_SYMBOL(w1_touch_bit);
+-EXPORT_SYMBOL(w1_write_8);
+-EXPORT_SYMBOL(w1_read_8);
+-EXPORT_SYMBOL(w1_reset_bus);
+-EXPORT_SYMBOL(w1_calc_crc8);
+-EXPORT_SYMBOL(w1_delay);
+-EXPORT_SYMBOL(w1_read_block);
+-EXPORT_SYMBOL(w1_write_block);
+-EXPORT_SYMBOL(w1_search_devices);
+-EXPORT_SYMBOL(w1_reset_select_slave);
++EXPORT_SYMBOL_GPL(w1_calc_crc8);
+--- gregkh-2.6.orig/drivers/w1/w1_netlink.c
++++ gregkh-2.6/drivers/w1/w1_netlink.c
+@@ -21,6 +21,7 @@
+
+ #include <linux/skbuff.h>
+ #include <linux/netlink.h>
++#include <linux/connector.h>
+
+ #include "w1.h"
+ #include "w1_log.h"
+@@ -29,50 +30,204 @@
+ #ifndef NETLINK_DISABLED
+ void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
+ {
+- unsigned int size;
+- struct sk_buff *skb;
+- struct w1_netlink_msg *data;
+- struct nlmsghdr *nlh;
+-
+- if (!dev->nls)
+- return;
+-
+- size = NLMSG_SPACE(sizeof(struct w1_netlink_msg));
+-
+- skb = alloc_skb(size, GFP_ATOMIC);
+- if (!skb) {
+- dev_err(&dev->dev, "skb_alloc() failed.\n");
+- return;
+- }
++ char buf[sizeof(struct cn_msg) + sizeof(struct w1_netlink_msg)];
++ struct cn_msg *m = (struct cn_msg *)buf;
++ struct w1_netlink_msg *w = (struct w1_netlink_msg *)(m+1);
++
++ memset(buf, 0, sizeof(buf));
+
+- nlh = NLMSG_PUT(skb, 0, dev->seq++, NLMSG_DONE, size - sizeof(*nlh));
++ m->id.idx = CN_W1_IDX;
++ m->id.val = CN_W1_VAL;
+
+- data = (struct w1_netlink_msg *)NLMSG_DATA(nlh);
++ m->seq = dev->seq++;
++ m->len = sizeof(struct w1_netlink_msg);
+
+- memcpy(data, msg, sizeof(struct w1_netlink_msg));
++ memcpy(w, msg, sizeof(struct w1_netlink_msg));
++
++ cn_netlink_send(m, 0, GFP_KERNEL);
++}
+
+- NETLINK_CB(skb).dst_group = dev->groups;
+- netlink_broadcast(dev->nls, skb, 0, dev->groups, GFP_ATOMIC);
++static int w1_process_command_master(struct w1_master *dev, struct cn_msg *msg,
++ struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd)
++{
++ dev_dbg(&dev->dev, "%s: %s: cmd=%02x, len=%u.\n",
++ __func__, dev->name, cmd->cmd, cmd->len);
+
+-nlmsg_failure:
+- return;
++ if (cmd->cmd != W1_CMD_SEARCH && cmd->cmd != W1_CMD_ALARM_SEARCH)
++ return -EINVAL;
++
++ w1_search_process(dev, (cmd->cmd == W1_CMD_ALARM_SEARCH)?W1_ALARM_SEARCH:W1_SEARCH);
++ return 0;
+ }
+
+-int dev_init_netlink(struct w1_master *dev)
++static int w1_send_read_reply(struct w1_slave *sl, struct cn_msg *msg,
++ struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd)
+ {
+- dev->nls = netlink_kernel_create(NETLINK_W1, 1, NULL, THIS_MODULE);
+- if (!dev->nls) {
+- printk(KERN_ERR "Failed to create new netlink socket(%u) for w1 master %s.\n",
+- NETLINK_W1, dev->dev.bus_id);
++ void *data;
++ struct w1_netlink_msg *h;
++ struct w1_netlink_cmd *c;
++ struct cn_msg *cm;
++ int err;
++
++ data = kzalloc(sizeof(struct cn_msg) +
++ sizeof(struct w1_netlink_msg) +
++ sizeof(struct w1_netlink_cmd) +
++ cmd->len, GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
++
++ cm = (struct cn_msg *)(data);
++ h = (struct w1_netlink_msg *)(cm + 1);
++ c = (struct w1_netlink_cmd *)(h + 1);
++
++ memcpy(cm, msg, sizeof(struct cn_msg));
++ memcpy(h, hdr, sizeof(struct w1_netlink_msg));
++ memcpy(c, cmd, sizeof(struct w1_netlink_cmd));
++
++ cm->ack = msg->seq+1;
++ cm->len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd) + cmd->len;
++
++ h->len = sizeof(struct w1_netlink_cmd) + cmd->len;
++
++ memcpy(c->data, cmd->data, c->len);
++
++ err = cn_netlink_send(cm, 0, GFP_KERNEL);
++
++ kfree(data);
++
++ return err;
++}
++
++static int w1_process_command_slave(struct w1_slave *sl, struct cn_msg *msg,
++ struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd)
++{
++ int err = 0;
++
++ dev_dbg(&sl->master->dev, "%s: %02x.%012llx.%02x: cmd=%02x, len=%u.\n",
++ __func__, sl->reg_num.family, (unsigned long long)sl->reg_num.id, sl->reg_num.crc,
++ cmd->cmd, cmd->len);
++
++ switch (cmd->cmd) {
++ case W1_CMD_READ:
++ w1_read_block(sl->master, cmd->data, cmd->len);
++ w1_send_read_reply(sl, msg, hdr, cmd);
++ break;
++ case W1_CMD_WRITE:
++ w1_write_block(sl->master, cmd->data, cmd->len);
++ break;
++ case W1_CMD_SEARCH:
++ case W1_CMD_ALARM_SEARCH:
++ w1_search_process(sl->master,
++ (cmd->cmd == W1_CMD_ALARM_SEARCH)?W1_ALARM_SEARCH:W1_SEARCH);
++ break;
++ default:
++ err = -1;
++ break;
+ }
++
++ return err;
++}
+
+- return 0;
++static void w1_cn_callback(void *data)
++{
++ struct cn_msg *msg = data;
++ struct w1_netlink_msg *m = (struct w1_netlink_msg *)(msg + 1);
++ struct w1_netlink_cmd *cmd;
++ struct w1_slave *sl;
++ struct w1_master *dev;
++ int err = 0;
++
++ while (msg->len && !err) {
++ struct w1_reg_num id;
++ u16 mlen = m->len;
++ u8 *cmd_data = m->data;
++
++ dev = NULL;
++ sl = NULL;
++
++ memcpy(&id, m->id.id, sizeof(id));
++#if 0
++ printk("%s: %02x.%012llx.%02x: type=%02x, len=%u.\n",
++ __func__, id.family, (unsigned long long)id.id, id.crc, m->type, m->len);
++#endif
++ if (m->len + sizeof(struct w1_netlink_msg) > msg->len) {
++ err = -E2BIG;
++ break;
++ }
++
++ if (!mlen)
++ goto out_cont;
++
++ if (m->type == W1_MASTER_CMD) {
++ dev = w1_search_master_id(m->id.mst.id);
++ } else if (m->type == W1_SLAVE_CMD) {
++ sl = w1_search_slave(&id);
++ if (sl)
++ dev = sl->master;
++ }
++
++ if (!dev) {
++ err = -ENODEV;
++ goto out_cont;
++ }
++
++ down(&dev->mutex);
++
++ if (sl && w1_reset_select_slave(sl)) {
++ err = -ENODEV;
++ goto out_up;
++ }
++
++ while (mlen) {
++ cmd = (struct w1_netlink_cmd *)cmd_data;
++
++ if (cmd->len + sizeof(struct w1_netlink_cmd) > mlen) {
++ err = -E2BIG;
++ break;
++ }
++
++ if (sl)
++ w1_process_command_slave(sl, msg, m, cmd);
++ else
++ w1_process_command_master(dev, msg, m, cmd);
++
++ cmd_data += cmd->len + sizeof(struct w1_netlink_cmd);
++ mlen -= cmd->len + sizeof(struct w1_netlink_cmd);
++ }
++out_up:
++ atomic_dec(&dev->refcnt);
++ if (sl)
++ atomic_dec(&sl->refcnt);
++ up(&dev->mutex);
++out_cont:
++ msg->len -= sizeof(struct w1_netlink_msg) + m->len;
++ m = (struct w1_netlink_msg *)(((u8 *)m) + sizeof(struct w1_netlink_msg) + m->len);
++
++ /*
++ * Let's allow requests for nonexisting devices.
++ */
++ if (err == -ENODEV)
++ err = 0;
++ }
++#if 0
++ if (err) {
++ printk("%s: malformed message. Dropping.\n", __func__);
++ }
++#endif
++}
++
++int w1_init_netlink(void)
++{
++ struct cb_id w1_id = {.idx = CN_W1_IDX, .val = CN_W1_VAL};
++
++ return cn_add_callback(&w1_id, "w1", &w1_cn_callback);
+ }
+
+-void dev_fini_netlink(struct w1_master *dev)
++void w1_fini_netlink(void)
+ {
+- if (dev->nls && dev->nls->sk_socket)
+- sock_release(dev->nls->sk_socket);
++ struct cb_id w1_id = {.idx = CN_W1_IDX, .val = CN_W1_VAL};
++
++ cn_del_callback(&w1_id);
+ }
+ #else
+ #warning Netlink support is disabled. Please compile with NET support enabled.
+@@ -81,12 +236,12 @@ void w1_netlink_send(struct w1_master *d
+ {
+ }
+
+-int dev_init_netlink(struct w1_master *dev)
++int w1_init_netlink(void)
+ {
+ return 0;
+ }
+
+-void dev_fini_netlink(struct w1_master *dev)
++void w1_fini_netlink(void)
+ {
+ }
+ #endif
+--- gregkh-2.6.orig/drivers/w1/w1_netlink.h
++++ gregkh-2.6/drivers/w1/w1_netlink.h
+@@ -23,37 +23,55 @@
+ #define __W1_NETLINK_H
+
+ #include <asm/types.h>
++#include <linux/connector.h>
+
+ #include "w1.h"
+
++#define CN_W1_IDX 3
++#define CN_W1_VAL 1
++
+ enum w1_netlink_message_types {
+ W1_SLAVE_ADD = 0,
+ W1_SLAVE_REMOVE,
+ W1_MASTER_ADD,
+ W1_MASTER_REMOVE,
++ W1_MASTER_CMD,
++ W1_SLAVE_CMD,
+ };
+
+ struct w1_netlink_msg
+ {
+ __u8 type;
+- __u8 reserved[3];
+- union
+- {
+- struct w1_reg_num id;
+- __u64 w1_id;
+- struct
+- {
++ __u8 reserved;
++ __u16 len;
++ union {
++ __u8 id[8];
++ struct w1_mst {
+ __u32 id;
+- __u32 pid;
++ __u32 res;
+ } mst;
+ } id;
++ __u8 data[0];
++};
++
++#define W1_CMD_READ 0x0
++#define W1_CMD_WRITE 0x1
++#define W1_CMD_SEARCH 0x2
++#define W1_CMD_ALARM_SEARCH 0x3
++
++struct w1_netlink_cmd
++{
++ __u8 cmd;
++ __u8 res;
++ __u16 len;
++ __u8 data[0];
+ };
+
+ #ifdef __KERNEL__
+
+ void w1_netlink_send(struct w1_master *, struct w1_netlink_msg *);
+-int dev_init_netlink(struct w1_master *dev);
+-void dev_fini_netlink(struct w1_master *dev);
++int w1_init_netlink(void);
++void w1_fini_netlink(void);
+
+ #endif /* __KERNEL__ */
+ #endif /* __W1_NETLINK_H */