Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/w1-2.6
authorLinus Torvalds <torvalds@g5.osdl.org>
Thu, 8 Sep 2005 22:55:53 +0000 (15:55 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Thu, 8 Sep 2005 22:55:53 +0000 (15:55 -0700)
21 files changed:
drivers/w1/Kconfig
drivers/w1/Makefile
drivers/w1/ds_w1_bridge.c
drivers/w1/dscore.c
drivers/w1/dscore.h
drivers/w1/w1.c
drivers/w1/w1.h
drivers/w1/w1_ds2433.c [new file with mode: 0644]
drivers/w1/w1_family.c
drivers/w1/w1_family.h
drivers/w1/w1_int.c
drivers/w1/w1_io.c
drivers/w1/w1_io.h
drivers/w1/w1_netlink.c
drivers/w1/w1_netlink.h
drivers/w1/w1_smem.c
drivers/w1/w1_therm.c
include/linux/crc16.h [new file with mode: 0644]
lib/Kconfig
lib/Makefile
lib/crc16.c [new file with mode: 0644]

index 711b90903e7b64277b76b8654e331deb304d270e..9a1e00dd3e02a45363911ce7ee04e3a680b87796 100644 (file)
@@ -54,4 +54,20 @@ config W1_SMEM
          Say Y here if you want to connect 1-wire
          simple 64bit memory rom(ds2401/ds2411/ds1990*) to you wire.
 
+config W1_DS2433
+       tristate "4kb EEPROM family support (DS2433)"
+       depends on W1
+       help
+         Say Y here if you want to use a 1-wire
+         4kb EEPROM family device (DS2433).
+
+config W1_DS2433_CRC
+       bool "Protect DS2433 data with a CRC16"
+       depends on W1_DS2433
+       select CRC16
+       help
+         Say Y here to protect DS2433 data with a CRC16.
+         Each block has 30 bytes of data and a two byte CRC16.
+         Full block writes are only allowed if the CRC is valid.
+
 endmenu
index 80725c348e704fe185d441aa6c6747747b6e3250..01fb54391470e78cc60959028528d3a7ac2b2971 100644 (file)
@@ -6,6 +6,10 @@ ifneq ($(CONFIG_NET), y)
 EXTRA_CFLAGS   += -DNETLINK_DISABLED
 endif
 
+ifeq ($(CONFIG_W1_DS2433_CRC), y)
+EXTRA_CFLAGS   += -DCONFIG_W1_F23_CRC
+endif
+
 obj-$(CONFIG_W1)       += wire.o
 wire-objs              := w1.o w1_int.o w1_family.o w1_netlink.o w1_io.o
 
@@ -13,8 +17,9 @@ obj-$(CONFIG_W1_MATROX)               += matrox_w1.o
 obj-$(CONFIG_W1_THERM)         += w1_therm.o
 obj-$(CONFIG_W1_SMEM)          += w1_smem.o
 
-obj-$(CONFIG_W1_DS9490)                += ds9490r.o 
+obj-$(CONFIG_W1_DS9490)                += ds9490r.o
 ds9490r-objs    := dscore.o
 
 obj-$(CONFIG_W1_DS9490_BRIDGE) += ds_w1_bridge.o
 
+obj-$(CONFIG_W1_DS2433)                += w1_ds2433.o
index 7bddd8ac7d7f7a615c3fe5e71b1078e244875719..a79d16d5666ff557dadc3b2e7bb895641e6b0fe1 100644 (file)
@@ -1,8 +1,8 @@
 /*
- *     ds_w1_bridge.c
+ *     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
@@ -25,7 +25,7 @@
 #include "../w1/w1.h"
 #include "../w1/w1_int.h"
 #include "dscore.h"
-       
+
 static struct ds_device *ds_dev;
 static struct w1_bus_master *ds_bus_master;
 
@@ -120,7 +120,7 @@ static u8 ds9490r_reset(unsigned long data)
 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");
@@ -136,14 +136,14 @@ static int __devinit ds_w1_init(void)
 
        memset(ds_bus_master, 0, sizeof(*ds_bus_master));
 
-       ds_bus_master->data             = (unsigned long)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->data             = (unsigned long)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);
index eee6644d33d6e60ee89e5eb0cffe8e84ae6c9d38..15fb250451e59a0628029819dfebbfc62d7fede9 100644 (file)
@@ -1,8 +1,8 @@
 /*
- *     dscore.c
+ *     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
@@ -32,19 +32,16 @@ static struct usb_device_id ds_id_table [] = {
 };
 MODULE_DEVICE_TABLE(usb, ds_id_table);
 
-int ds_probe(struct usb_interface *, const struct usb_device_id *);
-void ds_disconnect(struct usb_interface *);
+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);
-int ds_start_pulse(struct ds_device *, int);
-int ds_set_speed(struct ds_device *, int);
+static int ds_start_pulse(struct ds_device *, int);
 int ds_reset(struct ds_device *, struct ds_status *);
-int ds_detect(struct ds_device *, struct ds_status *);
-int ds_stop_pulse(struct ds_device *, int);
 struct ds_device * ds_get_device(void);
 void ds_put_device(struct ds_device *);
 
@@ -79,11 +76,11 @@ void ds_put_device(struct ds_device *dev)
 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]), 
+
+       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", 
+               printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n",
                                value, index, err);
                return err;
        }
@@ -94,11 +91,11 @@ static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)
 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]), 
+
+       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", 
+               printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n",
                                value, index, err);
                return err;
        }
@@ -109,11 +106,11 @@ static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
 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]), 
+
+       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", 
+               printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n",
                                value, index, err);
                return err;
        }
@@ -126,19 +123,20 @@ static inline void ds_dump_status(unsigned char *buf, unsigned char *str, int of
        printk("%45s: %8x\n", str, buf[off]);
 }
 
-int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, unsigned char *buf, int size)
+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));
 
@@ -149,13 +147,13 @@ 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]);
@@ -199,7 +197,7 @@ static int ds_recv_status(struct ds_device *dev, struct ds_status *st)
                        return err;
        }
 #endif
-       
+
        return err;
 }
 
@@ -207,9 +205,9 @@ 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]), 
+       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]);
@@ -234,7 +232,7 @@ static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
 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) {
@@ -245,12 +243,14 @@ static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
        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)
@@ -275,7 +275,7 @@ int ds_stop_pulse(struct ds_device *dev, int limit)
 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;
@@ -283,11 +283,11 @@ int ds_detect(struct ds_device *dev, struct ds_status *st)
        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;
@@ -297,7 +297,9 @@ int ds_detect(struct ds_device *dev, struct ds_status *st)
        return err;
 }
 
-int ds_wait_status(struct ds_device *dev, struct ds_status *st)
+#endif  /*  0  */
+
+static int ds_wait_status(struct ds_device *dev, struct ds_status *st)
 {
        u8 buf[0x20];
        int err, count = 0;
@@ -305,7 +307,7 @@ int ds_wait_status(struct ds_device *dev, struct ds_status *st)
        do {
                err = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
 #if 0
-               if (err >= 0) { 
+               if (err >= 0) {
                        int i;
                        printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err);
                        for (i=0; i<err; ++i)
@@ -319,10 +321,8 @@ int ds_wait_status(struct ds_device *dev, struct ds_status *st)
        if (((err > 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) {
                ds_recv_status(dev, st);
                return -1;
-       }
-       else {
+       } else
                return 0;
-       }
 }
 
 int ds_reset(struct ds_device *dev, struct ds_status *st)
@@ -345,6 +345,7 @@ int ds_reset(struct ds_device *dev, struct ds_status *st)
        return 0;
 }
 
+#if 0
 int ds_set_speed(struct ds_device *dev, int speed)
 {
        int err;
@@ -356,20 +357,21 @@ int ds_set_speed(struct ds_device *dev, int speed)
                speed = SPEED_FLEXIBLE;
 
        speed &= 0xff;
-       
+
        err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed);
        if (err)
                return err;
 
        return err;
 }
+#endif  /*  0  */
 
-int ds_start_pulse(struct ds_device *dev, int delay)
+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)
@@ -390,7 +392,7 @@ int ds_start_pulse(struct ds_device *dev, int delay)
        mdelay(delay);
 
        ds_wait_status(dev, &st);
-       
+
        return err;
 }
 
@@ -400,7 +402,7 @@ int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit)
        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;
@@ -430,7 +432,7 @@ 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;
@@ -445,7 +447,7 @@ 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;
@@ -453,11 +455,11 @@ int ds_write_byte(struct ds_device *dev, u8 byte)
        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);
@@ -470,11 +472,11 @@ int ds_read_bit(struct ds_device *dev, u8 *bit)
        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;
@@ -492,7 +494,7 @@ int ds_read_byte(struct ds_device *dev, u8 *byte)
                return err;
 
        ds_wait_status(dev, &st);
-       
+
        err = ds_recv_data(dev, byte, sizeof(*byte));
        if (err < 0)
                return err;
@@ -509,17 +511,17 @@ int ds_read_block(struct ds_device *dev, u8 *buf, int len)
                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);
 
@@ -530,11 +532,11 @@ 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);
@@ -548,10 +550,12 @@ int ds_write_block(struct ds_device *dev, u8 *buf, int len)
                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;
@@ -559,11 +563,11 @@ int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int condi
        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;
@@ -589,7 +593,7 @@ int ds_match_access(struct ds_device *dev, u64 init)
        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);
@@ -609,11 +613,11 @@ int ds_set_path(struct ds_device *dev, u64 init)
 
        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);
@@ -625,7 +629,10 @@ int ds_set_path(struct ds_device *dev, u64 init)
        return 0;
 }
 
-int ds_probe(struct usb_interface *intf, const struct usb_device_id *udev_id)
+#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;
@@ -653,7 +660,7 @@ int ds_probe(struct usb_interface *intf, const struct usb_device_id *udev_id)
                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);
@@ -662,37 +669,37 @@ int ds_probe(struct usb_interface *intf, const struct usb_device_id *udev_id)
 
        atomic_set(&ds_dev->refcnt, 0);
        memset(ds_dev->ep, 0, sizeof(ds_dev->ep));
-       
+
        /*
-        * This loop doesn'd show control 0 endpoint, 
+        * 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");       
+
+               printk("Resetting...\n");
                ds_reset(ds_dev, &st);
                printk("Setting path for %llx.\n", init);
                err = ds_set_path(ds_dev, init);
@@ -707,12 +714,12 @@ int ds_probe(struct usb_interface *intf, const struct usb_device_id *udev_id)
                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
@@ -720,10 +727,10 @@ int ds_probe(struct usb_interface *intf, const struct usb_device_id *udev_id)
        return 0;
 }
 
-void ds_disconnect(struct usb_interface *intf)
+static void ds_disconnect(struct usb_interface *intf)
 {
        struct ds_device *dev;
-       
+
        dev = usb_get_intfdata(intf);
        usb_set_intfdata(intf, NULL);
 
@@ -740,7 +747,7 @@ void ds_disconnect(struct usb_interface *intf)
        ds_dev = NULL;
 }
 
-int ds_init(void)
+static int ds_init(void)
 {
        int err;
 
@@ -753,7 +760,7 @@ int ds_init(void)
        return 0;
 }
 
-void ds_fini(void)
+static void ds_fini(void)
 {
        usb_deregister(&ds_driver);
 }
@@ -776,8 +783,8 @@ 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 
+ * This functions can be used for EEPROM programming,
+ * when driver will be included into mainline this will
  * require uncommenting.
  */
 #if 0
index 9c767ef4ac2488e9fc1d90d84da357a746057144..6cf5671d6ebea601dbd6d83a172bed0cd4e738a8 100644 (file)
@@ -1,8 +1,8 @@
 /*
- *     dscore.h
+ *     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
 
 struct ds_device
 {
-       struct usb_device       *udev;
+       struct usb_device       *udev;
        struct usb_interface    *intf;
 
        int                     ep[NUM_EP];
@@ -156,11 +156,7 @@ 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_start_pulse(struct ds_device *, int);
-int ds_set_speed(struct ds_device *, int);
 int ds_reset(struct ds_device *, struct ds_status *);
-int ds_detect(struct ds_device *, struct ds_status *);
-int ds_stop_pulse(struct ds_device *, int);
 struct ds_device * ds_get_device(void);
 void ds_put_device(struct ds_device *);
 int ds_write_block(struct ds_device *, u8 *, int);
index 0bbf029b1ef1658f99b537fa690a10186275b486..1b6b74c116a911c3f34c34ad86357cfe3a948dc5 100644 (file)
@@ -45,10 +45,12 @@ MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
 MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol.");
 
 static int w1_timeout = 10;
+static int w1_control_timeout = 1;
 int w1_max_slave_count = 10;
 int w1_max_slave_ttl = 10;
 
 module_param_named(timeout, w1_timeout, int, 0);
+module_param_named(control_timeout, w1_control_timeout, int, 0);
 module_param_named(max_slave_count, w1_max_slave_count, int, 0);
 module_param_named(slave_ttl, w1_max_slave_ttl, int, 0);
 
@@ -59,19 +61,6 @@ static pid_t control_thread;
 static int control_needs_exit;
 static DECLARE_COMPLETION(w1_control_complete);
 
-/* stuff for the default family */
-static ssize_t w1_famdefault_read_name(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
-       return(sprintf(buf, "%s\n", sl->name));
-}
-static struct w1_family_ops w1_default_fops = {
-       .rname = &w1_famdefault_read_name,
-};
-static struct w1_family w1_default_family = {
-       .fops = &w1_default_fops,
-};
-
 static int w1_master_match(struct device *dev, struct device_driver *drv)
 {
        return 1;
@@ -82,73 +71,116 @@ static int w1_master_probe(struct device *dev)
        return -ENODEV;
 }
 
-static int w1_master_remove(struct device *dev)
-{
-       return 0;
-}
-
 static void w1_master_release(struct device *dev)
 {
-       struct w1_master *md = container_of(dev, struct w1_master, dev);
+       struct w1_master *md = dev_to_w1_master(dev);
 
-       complete(&md->dev_released);
+       dev_dbg(dev, "%s: Releasing %s.\n", __func__, md->name);
+
+       if (md->nls && md->nls->sk_socket)
+               sock_release(md->nls->sk_socket);
+       memset(md, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master));
+       kfree(md);
 }
 
 static void w1_slave_release(struct device *dev)
 {
-       struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+       struct w1_slave *sl = dev_to_w1_slave(dev);
+
+       dev_dbg(dev, "%s: Releasing %s.\n", __func__, sl->name);
+
+       while (atomic_read(&sl->refcnt)) {
+               dev_dbg(dev, "Waiting for %s to become free: refcnt=%d.\n",
+                               sl->name, atomic_read(&sl->refcnt));
+               if (msleep_interruptible(1000))
+                       flush_signals(current);
+       }
+
+       w1_family_put(sl->family);
+       sl->master->slave_count--;
 
-       complete(&sl->dev_released);
+       complete(&sl->released);
 }
 
-static ssize_t w1_default_read_name(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t w1_slave_read_name(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       return sprintf(buf, "No family registered.\n");
+       struct w1_slave *sl = dev_to_w1_slave(dev);
+
+       return sprintf(buf, "%s\n", sl->name);
 }
 
-static ssize_t w1_default_read_bin(struct kobject *kobj, char *buf, loff_t off,
-                    size_t count)
+static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, size_t count)
 {
-       return sprintf(buf, "No family registered.\n");
+       struct w1_slave *sl = kobj_to_w1_slave(kobj);
+
+       atomic_inc(&sl->refcnt);
+       if (off > 8) {
+               count = 0;
+       } else {
+               if (off + count > 8)
+                       count = 8 - off;
+
+               memcpy(buf, (u8 *)&sl->reg_num, count);
+       }
+       atomic_dec(&sl->refcnt);
+
+       return count;
 }
 
-static struct device_attribute w1_slave_attribute =
-       __ATTR(name, 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 struct device_attribute w1_slave_attr_name =
+       __ATTR(name, S_IRUGO, w1_slave_read_name, NULL);
+
+static struct bin_attribute w1_slave_attr_bin_id = {
+      .attr = {
+              .name = "id",
+              .mode = S_IRUGO,
+              .owner = THIS_MODULE,
+      },
+      .size = 8,
+      .read = w1_slave_read_id,
 };
 
+/* Default family */
+static struct w1_family w1_default_family;
+
+static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size);
 
 static struct bus_type w1_bus_type = {
        .name = "w1",
        .match = w1_master_match,
+       .hotplug = w1_hotplug,
 };
 
-struct device_driver w1_driver = {
-       .name = "w1_driver",
+struct device_driver w1_master_driver = {
+       .name = "w1_master_driver",
        .bus = &w1_bus_type,
        .probe = w1_master_probe,
-       .remove = w1_master_remove,
 };
 
-struct device w1_device = {
+struct device w1_master_device = {
        .parent = NULL,
        .bus = &w1_bus_type,
        .bus_id = "w1 bus master",
-       .driver = &w1_driver,
+       .driver = &w1_master_driver,
        .release = &w1_master_release
 };
 
+struct device_driver w1_slave_driver = {
+       .name = "w1_slave_driver",
+       .bus = &w1_bus_type,
+};
+
+struct device w1_slave_device = {
+       .parent = NULL,
+       .bus = &w1_bus_type,
+       .bus_id = "w1 bus slave",
+       .driver = &w1_slave_driver,
+       .release = &w1_slave_release
+};
+
 static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct w1_master *md = container_of(dev, struct w1_master, dev);
+       struct w1_master *md = dev_to_w1_master(dev);
        ssize_t count;
 
        if (down_interruptible (&md->mutex))
@@ -165,7 +197,7 @@ static ssize_t w1_master_attribute_store_search(struct device * dev,
                                                struct device_attribute *attr,
                                                const char * buf, size_t count)
 {
-       struct w1_master *md = container_of(dev, struct w1_master, dev);
+       struct w1_master *md = dev_to_w1_master(dev);
 
        if (down_interruptible (&md->mutex))
                return -EBUSY;
@@ -181,7 +213,7 @@ static ssize_t w1_master_attribute_show_search(struct device *dev,
                                               struct device_attribute *attr,
                                               char *buf)
 {
-       struct w1_master *md = container_of(dev, struct w1_master, dev);
+       struct w1_master *md = dev_to_w1_master(dev);
        ssize_t count;
 
        if (down_interruptible (&md->mutex))
@@ -196,7 +228,7 @@ static ssize_t w1_master_attribute_show_search(struct device *dev,
 
 static ssize_t w1_master_attribute_show_pointer(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct w1_master *md = container_of(dev, struct w1_master, dev);
+       struct w1_master *md = dev_to_w1_master(dev);
        ssize_t count;
 
        if (down_interruptible(&md->mutex))
@@ -217,7 +249,7 @@ static ssize_t w1_master_attribute_show_timeout(struct device *dev, struct devic
 
 static ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct w1_master *md = container_of(dev, struct w1_master, dev);
+       struct w1_master *md = dev_to_w1_master(dev);
        ssize_t count;
 
        if (down_interruptible(&md->mutex))
@@ -231,7 +263,7 @@ static ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, stru
 
 static ssize_t w1_master_attribute_show_attempts(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct w1_master *md = container_of(dev, struct w1_master, dev);
+       struct w1_master *md = dev_to_w1_master(dev);
        ssize_t count;
 
        if (down_interruptible(&md->mutex))
@@ -245,7 +277,7 @@ static ssize_t w1_master_attribute_show_attempts(struct device *dev, struct devi
 
 static ssize_t w1_master_attribute_show_slave_count(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct w1_master *md = container_of(dev, struct w1_master, dev);
+       struct w1_master *md = dev_to_w1_master(dev);
        ssize_t count;
 
        if (down_interruptible(&md->mutex))
@@ -259,7 +291,7 @@ static ssize_t w1_master_attribute_show_slave_count(struct device *dev, struct d
 
 static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct w1_master *md = container_of(dev, struct w1_master, dev);
+       struct w1_master *md = dev_to_w1_master(dev);
        int c = PAGE_SIZE;
 
        if (down_interruptible(&md->mutex))
@@ -329,12 +361,55 @@ void w1_destroy_master_attributes(struct w1_master *master)
        sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group);
 }
 
+#ifdef CONFIG_HOTPLUG
+static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+{
+       struct w1_master *md = NULL;
+       struct w1_slave *sl = NULL;
+       char *event_owner, *name;
+       int err, cur_index=0, cur_len=0;
+
+       if (dev->driver == &w1_master_driver) {
+               md = container_of(dev, struct w1_master, dev);
+               event_owner = "master";
+               name = md->name;
+       } else if (dev->driver == &w1_slave_driver) {
+               sl = container_of(dev, struct w1_slave, dev);
+               event_owner = "slave";
+               name = sl->name;
+       } else {
+               dev_dbg(dev, "Unknown hotplug event.\n");
+               return -EINVAL;
+       }
+
+       dev_dbg(dev, "Hotplug event for %s %s, bus_id=%s.\n", event_owner, name, dev->bus_id);
+
+       if (dev->driver != &w1_slave_driver || !sl)
+               return 0;
+
+       err = add_hotplug_env_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_FID=%02X", sl->reg_num.family);
+       if (err)
+               return err;
+
+       err = add_hotplug_env_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_SLAVE_ID=%024LX", (u64)sl->reg_num.id);
+       if (err)
+               return err;
+
+       return 0;
+};
+#else
+static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+{
+       return 0;
+}
+#endif
+
 static int __w1_attach_slave_device(struct w1_slave *sl)
 {
        int err;
 
        sl->dev.parent = &sl->master->dev;
-       sl->dev.driver = sl->master->driver;
+       sl->dev.driver = &w1_slave_driver;
        sl->dev.bus = &w1_bus_type;
        sl->dev.release = &w1_slave_release;
 
@@ -347,8 +422,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
                 (unsigned int) sl->reg_num.family,
                 (unsigned long long) sl->reg_num.id);
 
-       dev_dbg(&sl->dev, "%s: registering %s.\n", __func__,
-               &sl->dev.bus_id[0]);
+       dev_dbg(&sl->dev, "%s: registering %s as %p.\n", __func__, &sl->dev.bus_id[0]);
 
        err = device_register(&sl->dev);
        if (err < 0) {
@@ -358,36 +432,44 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
                return err;
        }
 
-       memcpy(&sl->attr_bin, &w1_slave_bin_attribute, sizeof(sl->attr_bin));
-       memcpy(&sl->attr_name, &w1_slave_attribute, sizeof(sl->attr_name));
-
-       sl->attr_bin.read = sl->family->fops->rbin;
-       sl->attr_name.show = sl->family->fops->rname;
+       /* Create "name" entry */
+       err = device_create_file(&sl->dev, &w1_slave_attr_name);
+       if (err < 0) {
+               dev_err(&sl->dev,
+                       "sysfs file creation for [%s] failed. err=%d\n",
+                       sl->dev.bus_id, err);
+               goto out_unreg;
+       }
 
-       err = device_create_file(&sl->dev, &sl->attr_name);
+       /* Create "id" entry */
+       err = sysfs_create_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id);
        if (err < 0) {
                dev_err(&sl->dev,
                        "sysfs file creation for [%s] failed. err=%d\n",
                        sl->dev.bus_id, err);
-               device_unregister(&sl->dev);
-               return err;
+               goto out_rem1;
        }
 
-       if ( sl->attr_bin.read ) {
-               err = sysfs_create_bin_file(&sl->dev.kobj, &sl->attr_bin);
-               if (err < 0) {
-                       dev_err(&sl->dev,
-                               "sysfs file creation for [%s] failed. err=%d\n",
-                               sl->dev.bus_id, err);
-                       device_remove_file(&sl->dev, &sl->attr_name);
-                       device_unregister(&sl->dev);
-                       return err;
-               }
+       /* if the family driver needs to initialize something... */
+       if (sl->family->fops && sl->family->fops->add_slave &&
+           ((err = sl->family->fops->add_slave(sl)) < 0)) {
+               dev_err(&sl->dev,
+                       "sysfs file creation for [%s] failed. err=%d\n",
+                       sl->dev.bus_id, err);
+               goto out_rem2;
        }
 
        list_add_tail(&sl->w1_slave_entry, &sl->master->slist);
 
        return 0;
+
+out_rem2:
+       sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id);
+out_rem1:
+       device_remove_file(&sl->dev, &w1_slave_attr_name);
+out_unreg:
+       device_unregister(&sl->dev);
+       return err;
 }
 
 static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
@@ -413,7 +495,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
 
        memcpy(&sl->reg_num, rn, sizeof(sl->reg_num));
        atomic_set(&sl->refcnt, 0);
-       init_completion(&sl->dev_released);
+       init_completion(&sl->released);
 
        spin_lock(&w1_flock);
        f = w1_family_registered(rn->family);
@@ -452,28 +534,23 @@ static void w1_slave_detach(struct w1_slave *sl)
 {
        struct w1_netlink_msg msg;
 
-       dev_info(&sl->dev, "%s: detaching %s.\n", __func__, sl->name);
-
-       while (atomic_read(&sl->refcnt)) {
-               printk(KERN_INFO "Waiting for %s to become free: refcnt=%d.\n",
-                               sl->name, atomic_read(&sl->refcnt));
+       dev_dbg(&sl->dev, "%s: detaching %s [%p].\n", __func__, sl->name, sl);
 
-               if (msleep_interruptible(1000))
-                       flush_signals(current);
-       }
-
-       if ( sl->attr_bin.read ) {
-               sysfs_remove_bin_file (&sl->dev.kobj, &sl->attr_bin);
-       }
-       device_remove_file(&sl->dev, &sl->attr_name);
-       device_unregister(&sl->dev);
-       w1_family_put(sl->family);
+       list_del(&sl->w1_slave_entry);
 
-       sl->master->slave_count--;
+       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));
        msg.type = W1_SLAVE_REMOVE;
        w1_netlink_send(sl->master, &msg);
+
+       sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id);
+       device_remove_file(&sl->dev, &w1_slave_attr_name);
+       device_unregister(&sl->dev);
+
+       wait_for_completion(&sl->released);
+       kfree(sl);
 }
 
 static struct w1_master *w1_search_master(unsigned long data)
@@ -500,14 +577,13 @@ void w1_reconnect_slaves(struct w1_family *f)
 
        spin_lock_bh(&w1_mlock);
        list_for_each_entry(dev, &w1_masters, w1_master_entry) {
-               dev_info(&dev->dev, "Reconnecting slaves in %s into new family %02x.\n",
+               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);
 }
 
-
 static void w1_slave_found(unsigned long data, u64 rn)
 {
        int slave_count;
@@ -646,7 +722,7 @@ static int w1_control(void *data)
                have_to_wait = 0;
 
                try_to_freeze();
-               msleep_interruptible(w1_timeout * 1000);
+               msleep_interruptible(w1_control_timeout * 1000);
 
                if (signal_pending(current))
                        flush_signals(current);
@@ -679,33 +755,30 @@ static int w1_control(void *data)
                                list_del(&dev->w1_master_entry);
                                spin_unlock_bh(&w1_mlock);
 
+                               down(&dev->mutex);
                                list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
-                                       list_del(&sl->w1_slave_entry);
-
                                        w1_slave_detach(sl);
-                                       kfree(sl);
                                }
                                w1_destroy_master_attributes(dev);
+                               up(&dev->mutex);
                                atomic_dec(&dev->refcnt);
                                continue;
                        }
 
                        if (test_bit(W1_MASTER_NEED_RECONNECT, &dev->flags)) {
-                               dev_info(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name);
+                               dev_dbg(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name);
                                down(&dev->mutex);
-                               list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
+                               list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
                                        if (sl->family->fid == W1_FAMILY_DEFAULT) {
                                                struct w1_reg_num rn;
-                                               list_del(&sl->w1_slave_entry);
-                                               w1_slave_detach(sl);
 
                                                memcpy(&rn, &sl->reg_num, sizeof(rn));
-
-                                               kfree(sl);
+                                               w1_slave_detach(sl);
 
                                                w1_attach_slave_device(dev, &rn);
                                        }
                                }
+                               dev_dbg(&dev->dev, "Reconnecting slaves in device %s has been finished.\n", dev->name);
                                clear_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
                                up(&dev->mutex);
                        }
@@ -749,10 +822,7 @@ int w1_process(void *data)
 
                list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
                        if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) {
-                               list_del (&sl->w1_slave_entry);
-
-                               w1_slave_detach (sl);
-                               kfree (sl);
+                               w1_slave_detach(sl);
 
                                dev->slave_count--;
                        } else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags))
@@ -783,7 +853,7 @@ static int w1_init(void)
                goto err_out_exit_init;
        }
 
-       retval = driver_register(&w1_driver);
+       retval = driver_register(&w1_master_driver);
        if (retval) {
                printk(KERN_ERR
                        "Failed to register master driver. err=%d.\n",
@@ -791,18 +861,29 @@ static int w1_init(void)
                goto err_out_bus_unregister;
        }
 
+       retval = driver_register(&w1_slave_driver);
+       if (retval) {
+               printk(KERN_ERR
+                       "Failed to register master driver. err=%d.\n",
+                       retval);
+               goto err_out_master_unregister;
+       }
+
        control_thread = kernel_thread(&w1_control, NULL, 0);
        if (control_thread < 0) {
                printk(KERN_ERR "Failed to create control thread. err=%d\n",
                        control_thread);
                retval = control_thread;
-               goto err_out_driver_unregister;
+               goto err_out_slave_unregister;
        }
 
        return 0;
 
-err_out_driver_unregister:
-       driver_unregister(&w1_driver);
+err_out_slave_unregister:
+       driver_unregister(&w1_slave_driver);
+
+err_out_master_unregister:
+       driver_unregister(&w1_master_driver);
 
 err_out_bus_unregister:
        bus_unregister(&w1_bus_type);
@@ -821,7 +902,8 @@ static void w1_fini(void)
        control_needs_exit = 1;
        wait_for_completion(&w1_control_complete);
 
-       driver_unregister(&w1_driver);
+       driver_unregister(&w1_slave_driver);
+       driver_unregister(&w1_master_driver);
        bus_unregister(&w1_bus_type);
 }
 
index 4f0a986e33e3f6332a688c35c1c2923ac1530ccd..d8900780c3bf1fbcfbf1933a3d42b1267c1b02e0 100644 (file)
@@ -75,11 +75,9 @@ struct w1_slave
 
        struct w1_master        *master;
        struct w1_family        *family;
+       void                    *family_data;
        struct device           dev;
-       struct completion       dev_released;
-
-       struct bin_attribute    attr_bin;
-       struct device_attribute attr_name;
+       struct completion       released;
 };
 
 typedef void (* w1_slave_found_callback)(unsigned long, u64);
@@ -179,7 +177,6 @@ struct w1_master
 
        struct device_driver    *driver;
        struct device           dev;
-       struct completion       dev_released;
        struct completion       dev_exited;
 
        struct w1_bus_master    *bus_master;
@@ -191,6 +188,21 @@ struct w1_master
 int w1_create_master_attributes(struct w1_master *);
 void w1_search(struct w1_master *dev, w1_slave_found_callback cb);
 
+static inline struct w1_slave* dev_to_w1_slave(struct device *dev)
+{
+       return container_of(dev, struct w1_slave, dev);
+}
+
+static inline struct w1_slave* kobj_to_w1_slave(struct kobject *kobj)
+{
+       return dev_to_w1_slave(container_of(kobj, struct device, kobj));
+}
+
+static inline struct w1_master* dev_to_w1_master(struct device *dev)
+{
+       return container_of(dev, struct w1_master, dev);
+}
+
 #endif /* __KERNEL__ */
 
 #endif /* __W1_H */
diff --git a/drivers/w1/w1_ds2433.c b/drivers/w1/w1_ds2433.c
new file mode 100644 (file)
index 0000000..b7c24b3
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ *     w1_ds2433.c - w1 family 23 (DS2433) driver
+ *
+ * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#ifdef CONFIG_W1_F23_CRC
+#include <linux/crc16.h>
+#endif
+
+#include "w1.h"
+#include "w1_io.h"
+#include "w1_int.h"
+#include "w1_family.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
+MODULE_DESCRIPTION("w1 family 23 driver for DS2433, 4kb EEPROM");
+
+#define W1_EEPROM_SIZE         512
+#define W1_PAGE_COUNT          16
+#define W1_PAGE_SIZE           32
+#define W1_PAGE_BITS           5
+#define W1_PAGE_MASK           0x1F
+
+#define W1_F23_TIME            300
+
+#define W1_F23_READ_EEPROM     0xF0
+#define W1_F23_WRITE_SCRATCH   0x0F
+#define W1_F23_READ_SCRATCH    0xAA
+#define W1_F23_COPY_SCRATCH    0x55
+
+struct w1_f23_data {
+       u8      memory[W1_EEPROM_SIZE];
+       u32     validcrc;
+};
+
+/**
+ * Check the file size bounds and adjusts count as needed.
+ * This would not be needed if the file size didn't reset to 0 after a write.
+ */
+static inline size_t w1_f23_fix_count(loff_t off, size_t count, size_t size)
+{
+       if (off > size)
+               return 0;
+
+       if ((off + count) > size)
+               return (size - off);
+
+       return count;
+}
+
+#ifdef CONFIG_W1_F23_CRC
+static int w1_f23_refresh_block(struct w1_slave *sl, struct w1_f23_data *data,
+                               int block)
+{
+       u8      wrbuf[3];
+       int     off = block * W1_PAGE_SIZE;
+
+       if (data->validcrc & (1 << block))
+               return 0;
+
+       if (w1_reset_select_slave(sl)) {
+               data->validcrc = 0;
+               return -EIO;
+       }
+
+       wrbuf[0] = W1_F23_READ_EEPROM;
+       wrbuf[1] = off & 0xff;
+       wrbuf[2] = off >> 8;
+       w1_write_block(sl->master, wrbuf, 3);
+       w1_read_block(sl->master, &data->memory[off], W1_PAGE_SIZE);
+
+       /* cache the block if the CRC is valid */
+       if (crc16(CRC16_INIT, &data->memory[off], W1_PAGE_SIZE) == CRC16_VALID)
+               data->validcrc |= (1 << block);
+
+       return 0;
+}
+#endif /* CONFIG_W1_F23_CRC */
+
+static ssize_t w1_f23_read_bin(struct kobject *kobj, char *buf, loff_t off,
+                              size_t count)
+{
+       struct w1_slave *sl = kobj_to_w1_slave(kobj);
+#ifdef CONFIG_W1_F23_CRC
+       struct w1_f23_data *data = sl->family_data;
+       int i, min_page, max_page;
+#else
+       u8 wrbuf[3];
+#endif
+
+       if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0)
+               return 0;
+
+       atomic_inc(&sl->refcnt);
+       if (down_interruptible(&sl->master->mutex)) {
+               count = 0;
+               goto out_dec;
+       }
+
+#ifdef CONFIG_W1_F23_CRC
+
+       min_page = (off >> W1_PAGE_BITS);
+       max_page = (off + count - 1) >> W1_PAGE_BITS;
+       for (i = min_page; i <= max_page; i++) {
+               if (w1_f23_refresh_block(sl, data, i)) {
+                       count = -EIO;
+                       goto out_up;
+               }
+       }
+       memcpy(buf, &data->memory[off], count);
+
+#else  /* CONFIG_W1_F23_CRC */
+
+       /* read directly from the EEPROM */
+       if (w1_reset_select_slave(sl)) {
+               count = -EIO;
+               goto out_up;
+       }
+
+       wrbuf[0] = W1_F23_READ_EEPROM;
+       wrbuf[1] = off & 0xff;
+       wrbuf[2] = off >> 8;
+       w1_write_block(sl->master, wrbuf, 3);
+       w1_read_block(sl->master, buf, count);
+
+#endif /* CONFIG_W1_F23_CRC */
+
+out_up:
+       up(&sl->master->mutex);
+out_dec:
+       atomic_dec(&sl->refcnt);
+
+       return count;
+}
+
+/**
+ * Writes to the scratchpad and reads it back for verification.
+ * Then copies the scratchpad to EEPROM.
+ * The data must be on one page.
+ * The master must be locked.
+ *
+ * @param sl   The slave structure
+ * @param addr Address for the write
+ * @param len   length must be <= (W1_PAGE_SIZE - (addr & W1_PAGE_MASK))
+ * @param data The data to write
+ * @return     0=Success -1=failure
+ */
+static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data)
+{
+       u8 wrbuf[4];
+       u8 rdbuf[W1_PAGE_SIZE + 3];
+       u8 es = (addr + len - 1) & 0x1f;
+
+       /* Write the data to the scratchpad */
+       if (w1_reset_select_slave(sl))
+               return -1;
+
+       wrbuf[0] = W1_F23_WRITE_SCRATCH;
+       wrbuf[1] = addr & 0xff;
+       wrbuf[2] = addr >> 8;
+
+       w1_write_block(sl->master, wrbuf, 3);
+       w1_write_block(sl->master, data, len);
+
+       /* Read the scratchpad and verify */
+       if (w1_reset_select_slave(sl))
+               return -1;
+
+       w1_write_8(sl->master, W1_F23_READ_SCRATCH);
+       w1_read_block(sl->master, rdbuf, len + 3);
+
+       /* Compare what was read against the data written */
+       if ((rdbuf[0] != wrbuf[1]) || (rdbuf[1] != wrbuf[2]) ||
+           (rdbuf[2] != es) || (memcmp(data, &rdbuf[3], len) != 0))
+               return -1;
+
+       /* Copy the scratchpad to EEPROM */
+       if (w1_reset_select_slave(sl))
+               return -1;
+
+       wrbuf[0] = W1_F23_COPY_SCRATCH;
+       wrbuf[3] = es;
+       w1_write_block(sl->master, wrbuf, 4);
+
+       /* Sleep for 5 ms to wait for the write to complete */
+       msleep(5);
+
+       /* Reset the bus to wake up the EEPROM (this may not be needed) */
+       w1_reset_bus(sl->master);
+
+       return 0;
+}
+
+static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off,
+                               size_t count)
+{
+       struct w1_slave *sl = kobj_to_w1_slave(kobj);
+       int addr, len, idx;
+
+       if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0)
+               return 0;
+
+#ifdef CONFIG_W1_F23_CRC
+       /* can only write full blocks in cached mode */
+       if ((off & W1_PAGE_MASK) || (count & W1_PAGE_MASK)) {
+               dev_err(&sl->dev, "invalid offset/count off=%d cnt=%d\n",
+                       (int)off, count);
+               return -EINVAL;
+       }
+
+       /* make sure the block CRCs are valid */
+       for (idx = 0; idx < count; idx += W1_PAGE_SIZE) {
+               if (crc16(CRC16_INIT, &buf[idx], W1_PAGE_SIZE) != CRC16_VALID) {
+                       dev_err(&sl->dev, "bad CRC at offset %d\n", (int)off);
+                       return -EINVAL;
+               }
+       }
+#endif /* CONFIG_W1_F23_CRC */
+
+       atomic_inc(&sl->refcnt);
+       if (down_interruptible(&sl->master->mutex)) {
+               count = 0;
+               goto out_dec;
+       }
+
+       /* Can only write data to one page at a time */
+       idx = 0;
+       while (idx < count) {
+               addr = off + idx;
+               len = W1_PAGE_SIZE - (addr & W1_PAGE_MASK);
+               if (len > (count - idx))
+                       len = count - idx;
+
+               if (w1_f23_write(sl, addr, len, &buf[idx]) < 0) {
+                       count = -EIO;
+                       goto out_up;
+               }
+               idx += len;
+       }
+
+out_up:
+       up(&sl->master->mutex);
+out_dec:
+       atomic_dec(&sl->refcnt);
+
+       return count;
+}
+
+static struct bin_attribute w1_f23_bin_attr = {
+       .attr = {
+               .name = "eeprom",
+               .mode = S_IRUGO | S_IWUSR,
+               .owner = THIS_MODULE,
+       },
+       .size = W1_EEPROM_SIZE,
+       .read = w1_f23_read_bin,
+       .write = w1_f23_write_bin,
+};
+
+static int w1_f23_add_slave(struct w1_slave *sl)
+{
+       int err;
+#ifdef CONFIG_W1_F23_CRC
+       struct w1_f23_data *data;
+
+       data = kmalloc(sizeof(struct w1_f23_data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+       memset(data, 0, sizeof(struct w1_f23_data));
+       sl->family_data = data;
+
+#endif /* CONFIG_W1_F23_CRC */
+
+       err = sysfs_create_bin_file(&sl->dev.kobj, &w1_f23_bin_attr);
+
+#ifdef CONFIG_W1_F23_CRC
+       if (err)
+               kfree(data);
+#endif /* CONFIG_W1_F23_CRC */
+
+       return err;
+}
+
+static void w1_f23_remove_slave(struct w1_slave *sl)
+{
+#ifdef CONFIG_W1_F23_CRC
+       if (sl->family_data) {
+               kfree(sl->family_data);
+               sl->family_data = NULL;
+       }
+#endif /* CONFIG_W1_F23_CRC */
+       sysfs_remove_bin_file(&sl->dev.kobj, &w1_f23_bin_attr);
+}
+
+static struct w1_family_ops w1_f23_fops = {
+       .add_slave      = w1_f23_add_slave,
+       .remove_slave   = w1_f23_remove_slave,
+};
+
+static struct w1_family w1_family_23 = {
+       .fid = W1_EEPROM_DS2433,
+       .fops = &w1_f23_fops,
+};
+
+static int __init w1_f23_init(void)
+{
+       return w1_register_family(&w1_family_23);
+}
+
+static void __exit w1_f23_fini(void)
+{
+       w1_unregister_family(&w1_family_23);
+}
+
+module_init(w1_f23_init);
+module_exit(w1_f23_fini);
index 02eee57d3c0cd2c46e394faf1617251944778e42..88c517a4c178fa7ed9f884aed5dd55d465c401e3 100644 (file)
@@ -29,23 +29,12 @@ DEFINE_SPINLOCK(w1_flock);
 static LIST_HEAD(w1_families);
 extern void w1_reconnect_slaves(struct w1_family *f);
 
-static int w1_check_family(struct w1_family *f)
-{
-       if (!f->fops->rname || !f->fops->rbin)
-               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);
index b26da01bbc384c3b8b8fd627735e63e4d9cba96b..2ca0489c716a1f8083125cfecf3d3c0bfc31945c 100644 (file)
 #define W1_FAMILY_SMEM_81      0x81
 #define W1_THERM_DS18S20       0x10
 #define W1_THERM_DS1822        0x22
+#define W1_EEPROM_DS2433       0x23
 #define W1_THERM_DS18B20       0x28
 
 #define MAXNAMELEN             32
 
+struct w1_slave;
+
 struct w1_family_ops
 {
-       ssize_t (* rname)(struct device *, struct device_attribute *, char *);
-       ssize_t (* rbin)(struct kobject *, char *, loff_t, size_t);
+       int  (* add_slave)(struct w1_slave *);
+       void (* remove_slave)(struct w1_slave *);
 };
 
 struct w1_family
index 498ad505fa5f94360309063f7a72ec715ef75dd2..c3f67eafc7ec85f35a8bf696f6f9fe941d9d178d 100644 (file)
@@ -29,9 +29,9 @@
 
 static u32 w1_ids = 1;
 
-extern struct device_driver w1_driver;
+extern struct device_driver w1_master_driver;
 extern struct bus_type w1_bus_type;
-extern struct device w1_device;
+extern struct device w1_master_device;
 extern int w1_max_slave_count;
 extern int w1_max_slave_ttl;
 extern struct list_head w1_masters;
@@ -76,7 +76,6 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
        INIT_LIST_HEAD(&dev->slist);
        init_MUTEX(&dev->mutex);
 
-       init_completion(&dev->dev_released);
        init_completion(&dev->dev_exited);
 
        memcpy(&dev->dev, device, sizeof(struct device));
@@ -88,17 +87,14 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
 
        dev->groups = 1;
        dev->seq = 1;
-       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_NFLOG, dev->dev.bus_id);
-       }
+       dev_init_netlink(dev);
 
        err = device_register(&dev->dev);
        if (err) {
                printk(KERN_ERR "Failed to register master device. err=%d\n", err);
-               if (dev->nls && dev->nls->sk_socket)
-                       sock_release(dev->nls->sk_socket);
+
+               dev_fini_netlink(dev);
+
                memset(dev, 0, sizeof(struct w1_master));
                kfree(dev);
                dev = NULL;
@@ -107,13 +103,9 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
        return dev;
 }
 
-static void w1_free_dev(struct w1_master *dev)
+void w1_free_dev(struct w1_master *dev)
 {
        device_unregister(&dev->dev);
-       if (dev->nls && dev->nls->sk_socket)
-               sock_release(dev->nls->sk_socket);
-       memset(dev, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master));
-       kfree(dev);
 }
 
 int w1_add_master_device(struct w1_bus_master *master)
@@ -129,7 +121,7 @@ int w1_add_master_device(struct w1_bus_master *master)
                return(-EINVAL);
         }
 
-       dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_driver, &w1_device);
+       dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_master_driver, &w1_master_device);
        if (!dev)
                return -ENOMEM;
 
@@ -188,7 +180,7 @@ void __w1_remove_master_device(struct w1_master *dev)
                         __func__, dev->kpid);
 
        while (atomic_read(&dev->refcnt)) {
-               printk(KERN_INFO "Waiting for %s to become free: refcnt=%d.\n",
+               dev_dbg(&dev->dev, "Waiting for %s to become free: refcnt=%d.\n",
                                dev->name, atomic_read(&dev->refcnt));
 
                if (msleep_interruptible(1000))
index 00f032220173863c3603dbc0d5f66ca005f9adb0..e2a043354ddfa3040fdc10c17350efb4c8fc653d 100644 (file)
@@ -277,6 +277,29 @@ void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb)
                w1_search(dev, cb);
 }
 
+/**
+ * Resets the bus and then selects the slave by sending either a skip rom
+ * or a rom match.
+ * The w1 master lock must be held.
+ *
+ * @param sl   the slave to select
+ * @return     0=success, anything else=error
+ */
+int w1_reset_select_slave(struct w1_slave *sl)
+{
+       if (w1_reset_bus(sl->master))
+               return -1;
+
+       if (sl->master->slave_count == 1)
+               w1_write_8(sl->master, W1_SKIP_ROM);
+       else {
+               u8 match[9] = {W1_MATCH_ROM, };
+               memcpy(&match[1], (u8 *)&sl->reg_num, 8);
+               w1_write_block(sl->master, match, 9);
+       }
+       return 0;
+}
+
 EXPORT_SYMBOL(w1_touch_bit);
 EXPORT_SYMBOL(w1_write_8);
 EXPORT_SYMBOL(w1_read_8);
@@ -286,3 +309,4 @@ 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);
index af5829778aaa1fe9c72148386c97555066d39ed5..232860184a29ed62ae4a6166441b2c182cbabd97 100644 (file)
@@ -34,5 +34,6 @@ 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);
 void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb);
+int w1_reset_select_slave(struct w1_slave *sl);
 
 #endif /* __W1_IO_H */
index e7b774423dd65c56fce07dc13ca0017e713fb6f3..328645da79727f8eee095bce9c7d4d7047841d55 100644 (file)
@@ -57,10 +57,36 @@ void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
 nlmsg_failure:
        return;
 }
+
+int dev_init_netlink(struct w1_master *dev)
+{
+       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);
+       }
+
+       return 0;
+}
+
+void dev_fini_netlink(struct w1_master *dev)
+{
+       if (dev->nls && dev->nls->sk_socket)
+               sock_release(dev->nls->sk_socket);
+}
 #else
 #warning Netlink support is disabled. Please compile with NET support enabled.
 
 void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
 {
 }
+
+int dev_init_netlink(struct w1_master *dev)
+{
+       return 0;
+}
+
+void dev_fini_netlink(struct w1_master *dev)
+{
+}
 #endif
index 8615756946dfa988891d81ecc6be5b94d8ee496a..eb0c8b3152c8868059bcc01a3c8bb872fe3b15b3 100644 (file)
@@ -52,6 +52,8 @@ struct w1_netlink_msg
 #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);
 
 #endif /* __KERNEL__ */
 #endif /* __W1_NETLINK_H */
index 70d2d469963cfe8e57be5b242c31ae1bec525a69..e3209d0aca9b6f0832f296a7a0dde6c45175ff0b 100644 (file)
@@ -36,61 +36,12 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
 MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family.");
 
-static ssize_t w1_smem_read_name(struct device *, struct device_attribute *attr, char *);
-static ssize_t w1_smem_read_bin(struct kobject *, char *, loff_t, size_t);
-
-static struct w1_family_ops w1_smem_fops = {
-       .rname = &w1_smem_read_name,
-       .rbin = &w1_smem_read_bin,
-};
-
-static ssize_t w1_smem_read_name(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
-
-       return sprintf(buf, "%s\n", sl->name);
-}
-
-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;
-
-       atomic_inc(&sl->refcnt);
-       if (down_interruptible(&sl->master->mutex)) {
-               count = 0;
-               goto out_dec;
-       }
-
-       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 < 8; ++i)
-               count += sprintf(buf + count, "%02x ", ((u8 *)&sl->reg_num)[i]);
-       count += sprintf(buf + count, "\n");
-
-out:
-       up(&sl->master->mutex);
-out_dec:
-       atomic_dec(&sl->refcnt);
-
-       return count;
-}
-
 static struct w1_family w1_smem_family_01 = {
        .fid = W1_FAMILY_SMEM_01,
-       .fops = &w1_smem_fops,
 };
 
 static struct w1_family w1_smem_family_81 = {
        .fid = W1_FAMILY_SMEM_81,
-       .fops = &w1_smem_fops,
 };
 
 static int __init w1_smem_init(void)
index 165526c9360ad5a99a642e5e91c92ac762b24b0c..4577df3cfc4839e8537ed22618f02381a1b1b079 100644 (file)
@@ -42,12 +42,31 @@ static u8 bad_roms[][9] = {
                                {}
                        };
 
-static ssize_t w1_therm_read_name(struct device *, struct device_attribute *attr, char *);
 static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t);
 
+static struct bin_attribute w1_therm_bin_attr = {
+       .attr = {
+               .name = "w1_slave",
+               .mode = S_IRUGO,
+               .owner = THIS_MODULE,
+       },
+       .size = W1_SLAVE_DATA_SIZE,
+       .read = w1_therm_read_bin,
+};
+
+static int w1_therm_add_slave(struct w1_slave *sl)
+{
+       return sysfs_create_bin_file(&sl->dev.kobj, &w1_therm_bin_attr);
+}
+
+static void w1_therm_remove_slave(struct w1_slave *sl)
+{
+       sysfs_remove_bin_file(&sl->dev.kobj, &w1_therm_bin_attr);
+}
+
 static struct w1_family_ops w1_therm_fops = {
-       .rname = &w1_therm_read_name,
-       .rbin = &w1_therm_read_bin,
+       .add_slave      = w1_therm_add_slave,
+       .remove_slave   = w1_therm_remove_slave,
 };
 
 static struct w1_family w1_therm_family_DS18S20 = {
@@ -59,6 +78,7 @@ static struct w1_family w1_therm_family_DS18B20 = {
        .fid = W1_THERM_DS18B20,
        .fops = &w1_therm_fops,
 };
+
 static struct w1_family w1_therm_family_DS1822 = {
        .fid = W1_THERM_DS1822,
        .fops = &w1_therm_fops,
@@ -90,13 +110,6 @@ static struct w1_therm_family_converter w1_therm_families[] = {
        },
 };
 
-static ssize_t w1_therm_read_name(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
-
-       return sprintf(buf, "%s\n", sl->name);
-}
-
 static inline int w1_DS18B20_convert_temp(u8 rom[9])
 {
        int t = (rom[1] << 8) | rom[0];
@@ -148,8 +161,7 @@ static int w1_therm_check_rom(u8 rom[9])
 
 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_slave *sl = kobj_to_w1_slave(kobj);
        struct w1_master *dev = sl->master;
        u8 rom[9], crc, verdict;
        int i, max_trying = 10;
@@ -178,15 +190,10 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
        crc = 0;
 
        while (max_trying--) {
-               if (!w1_reset_bus (dev)) {
+               if (!w1_reset_select_slave(sl)) {
                        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) {
@@ -195,8 +202,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
                                        flush_signals(current);
                        }
 
-                       if (!w1_reset_bus (dev)) {
-                               w1_write_block(dev, match, 9);
+                       if (!w1_reset_select_slave(sl)) {
 
                                w1_write_8(dev, W1_READ_SCRATCHPAD);
                                if ((count = w1_read_block(dev, rom, 9)) != 9) {
@@ -207,7 +213,6 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
 
                                if (rom[8] == crc && rom[0])
                                        verdict = 1;
-
                        }
                }
 
diff --git a/include/linux/crc16.h b/include/linux/crc16.h
new file mode 100644 (file)
index 0000000..bdedf82
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ *     crc16.h - CRC-16 routine
+ *
+ * Implements the standard CRC-16, as used with 1-wire devices:
+ *   Width 16
+ *   Poly  0x8005 (x^16 + x^15 + x^2 + 1)
+ *   Init  0
+ *
+ * For 1-wire devices, the CRC is stored inverted, LSB-first
+ *
+ * Example buffer with the CRC attached:
+ *   31 32 33 34 35 36 37 38 39 C2 44
+ *
+ * The CRC over a buffer with the CRC attached is 0xB001.
+ * So, if (crc16(0, buf, size) == 0xB001) then the buffer is valid.
+ *
+ * Refer to "Application Note 937: Book of iButton Standards" for details.
+ * http://www.maxim-ic.com/appnotes.cfm/appnote_number/937
+ *
+ * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#ifndef __CRC16_H
+#define __CRC16_H
+
+#include <linux/types.h>
+
+#define CRC16_INIT             0
+#define CRC16_VALID            0xb001
+
+extern u16 const crc16_table[256];
+
+extern u16 crc16(u16 crc, const u8 *buffer, size_t len);
+
+static inline u16 crc16_byte(u16 crc, const u8 data)
+{
+       return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff];
+}
+
+#endif /* __CRC16_H */
+
index e43197efeb9c559a459cf199a9908a876eb3a976..3de93357f5ab1e05c370164e5e390eb7d0595f9f 100644 (file)
@@ -12,6 +12,14 @@ config CRC_CCITT
          the kernel tree does. Such modules that use library CRC-CCITT
          functions require M here.
 
+config CRC16
+       tristate "CRC16 functions"
+       help
+         This option is provided for the case where no in-kernel-tree
+         modules require CRC16 functions, but a module built outside
+         the kernel tree does. Such modules that use library CRC16
+         functions require M here.
+
 config CRC32
        tristate "CRC32 functions"
        default y
index 3e2bd0df23bb4c76d745bdee5b71b97a57dd4c8f..d9c38ba05e7bc2fcb3cbbca915bf43c51bd580fd 100644 (file)
@@ -23,11 +23,12 @@ lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
 obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
 obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
 
-ifneq ($(CONFIG_HAVE_DEC_LOCK),y) 
+ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
   lib-y += dec_and_lock.o
 endif
 
 obj-$(CONFIG_CRC_CCITT)        += crc-ccitt.o
+obj-$(CONFIG_CRC16)    += crc16.o
 obj-$(CONFIG_CRC32)    += crc32.o
 obj-$(CONFIG_LIBCRC32C)        += libcrc32c.o
 obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
diff --git a/lib/crc16.c b/lib/crc16.c
new file mode 100644 (file)
index 0000000..011fe57
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *      crc16.c
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/crc16.h>
+
+/** CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */
+u16 const crc16_table[256] = {
+       0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
+       0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
+       0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
+       0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
+       0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
+       0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
+       0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
+       0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
+       0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
+       0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
+       0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
+       0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
+       0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
+       0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
+       0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
+       0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
+       0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
+       0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
+       0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
+       0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
+       0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
+       0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
+       0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
+       0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
+       0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
+       0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
+       0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
+       0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
+       0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
+       0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
+       0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
+       0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
+};
+EXPORT_SYMBOL(crc16_table);
+
+/**
+ * Compute the CRC-16 for the data buffer
+ *
+ * @param crc     previous CRC value
+ * @param buffer  data pointer
+ * @param len     number of bytes in the buffer
+ * @return        the updated CRC value
+ */
+u16 crc16(u16 crc, u8 const *buffer, size_t len)
+{
+       while (len--)
+               crc = crc16_byte(crc, *buffer++);
+       return crc;
+}
+EXPORT_SYMBOL(crc16);
+
+MODULE_DESCRIPTION("CRC16 calculations");
+MODULE_LICENSE("GPL");
+