Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/w1-2.6

This commit is contained in:
Linus Torvalds 2005-09-08 15:55:53 -07:00
commit 6d8de3a26b
21 changed files with 871 additions and 313 deletions

View File

@ -54,4 +54,20 @@ config W1_SMEM
Say Y here if you want to connect 1-wire Say Y here if you want to connect 1-wire
simple 64bit memory rom(ds2401/ds2411/ds1990*) to you 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 endmenu

View File

@ -6,6 +6,10 @@ ifneq ($(CONFIG_NET), y)
EXTRA_CFLAGS += -DNETLINK_DISABLED EXTRA_CFLAGS += -DNETLINK_DISABLED
endif endif
ifeq ($(CONFIG_W1_DS2433_CRC), y)
EXTRA_CFLAGS += -DCONFIG_W1_F23_CRC
endif
obj-$(CONFIG_W1) += wire.o obj-$(CONFIG_W1) += wire.o
wire-objs := w1.o w1_int.o w1_family.o w1_netlink.o w1_io.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_THERM) += w1_therm.o
obj-$(CONFIG_W1_SMEM) += w1_smem.o obj-$(CONFIG_W1_SMEM) += w1_smem.o
obj-$(CONFIG_W1_DS9490) += ds9490r.o obj-$(CONFIG_W1_DS9490) += ds9490r.o
ds9490r-objs := dscore.o ds9490r-objs := dscore.o
obj-$(CONFIG_W1_DS9490_BRIDGE) += ds_w1_bridge.o obj-$(CONFIG_W1_DS9490_BRIDGE) += ds_w1_bridge.o
obj-$(CONFIG_W1_DS2433) += w1_ds2433.o

View File

@ -1,8 +1,8 @@
/* /*
* ds_w1_bridge.c * ds_w1_bridge.c
* *
* Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru> * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
* *
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -25,7 +25,7 @@
#include "../w1/w1.h" #include "../w1/w1.h"
#include "../w1/w1_int.h" #include "../w1/w1_int.h"
#include "dscore.h" #include "dscore.h"
static struct ds_device *ds_dev; static struct ds_device *ds_dev;
static struct w1_bus_master *ds_bus_master; 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) static int __devinit ds_w1_init(void)
{ {
int err; int err;
ds_bus_master = kmalloc(sizeof(*ds_bus_master), GFP_KERNEL); ds_bus_master = kmalloc(sizeof(*ds_bus_master), GFP_KERNEL);
if (!ds_bus_master) { if (!ds_bus_master) {
printk(KERN_ERR "Failed to allocate DS9490R USB<->W1 bus_master structure.\n"); 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)); memset(ds_bus_master, 0, sizeof(*ds_bus_master));
ds_bus_master->data = (unsigned long)ds_dev; ds_bus_master->data = (unsigned long)ds_dev;
ds_bus_master->touch_bit = &ds9490r_touch_bit; ds_bus_master->touch_bit = &ds9490r_touch_bit;
ds_bus_master->read_bit = &ds9490r_read_bit; ds_bus_master->read_bit = &ds9490r_read_bit;
ds_bus_master->write_bit = &ds9490r_write_bit; ds_bus_master->write_bit = &ds9490r_write_bit;
ds_bus_master->read_byte = &ds9490r_read_byte; ds_bus_master->read_byte = &ds9490r_read_byte;
ds_bus_master->write_byte = &ds9490r_write_byte; ds_bus_master->write_byte = &ds9490r_write_byte;
ds_bus_master->read_block = &ds9490r_read_block; ds_bus_master->read_block = &ds9490r_read_block;
ds_bus_master->write_block = &ds9490r_write_block; ds_bus_master->write_block = &ds9490r_write_block;
ds_bus_master->reset_bus = &ds9490r_reset; ds_bus_master->reset_bus = &ds9490r_reset;
err = w1_add_master_device(ds_bus_master); err = w1_add_master_device(ds_bus_master);

View File

@ -1,8 +1,8 @@
/* /*
* dscore.c * dscore.c
* *
* Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru> * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
* *
* *
* This program is free software; you can redistribute it and/or modify * 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 * 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); MODULE_DEVICE_TABLE(usb, ds_id_table);
int ds_probe(struct usb_interface *, const struct usb_device_id *); static int ds_probe(struct usb_interface *, const struct usb_device_id *);
void ds_disconnect(struct usb_interface *); static void ds_disconnect(struct usb_interface *);
int ds_touch_bit(struct ds_device *, u8, u8 *); int ds_touch_bit(struct ds_device *, u8, u8 *);
int ds_read_byte(struct ds_device *, u8 *); int ds_read_byte(struct ds_device *, u8 *);
int ds_read_bit(struct ds_device *, u8 *); int ds_read_bit(struct ds_device *, u8 *);
int ds_write_byte(struct ds_device *, u8); int ds_write_byte(struct ds_device *, u8);
int ds_write_bit(struct ds_device *, u8); int ds_write_bit(struct ds_device *, u8);
int ds_start_pulse(struct ds_device *, int); static 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_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); struct ds_device * ds_get_device(void);
void ds_put_device(struct ds_device *); 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) static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)
{ {
int err; 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); CONTROL_CMD, 0x40, value, index, NULL, 0, 1000);
if (err < 0) { 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); value, index, err);
return 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) static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
{ {
int err; 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); MODE_CMD, 0x40, value, index, NULL, 0, 1000);
if (err < 0) { 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); value, index, err);
return 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) static int ds_send_control(struct ds_device *dev, u16 value, u16 index)
{ {
int err; 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); COMM_CMD, 0x40, value, index, NULL, 0, 1000);
if (err < 0) { 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); value, index, err);
return 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]); 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; int count, err;
memset(st, 0, sizeof(st)); memset(st, 0, sizeof(st));
count = 0; count = 0;
err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100); err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100);
if (err < 0) { if (err < 0) {
printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err); printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err);
return err; return err;
} }
if (count >= sizeof(*st)) if (count >= sizeof(*st))
memcpy(st, buf, 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]; unsigned char buf[64];
int count, err = 0, i; int count, err = 0, i;
memcpy(st, buf, sizeof(*st)); memcpy(st, buf, sizeof(*st));
count = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
if (count < 0) if (count < 0)
return err; return err;
printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count); printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count);
for (i=0; i<count; ++i) for (i=0; i<count; ++i)
printk("%02x ", buf[i]); printk("%02x ", buf[i]);
@ -199,7 +197,7 @@ static int ds_recv_status(struct ds_device *dev, struct ds_status *st)
return err; return err;
} }
#endif #endif
return err; return err;
} }
@ -207,9 +205,9 @@ static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
{ {
int count, err; int count, err;
struct ds_status st; struct ds_status st;
count = 0; 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); buf, size, &count, 1000);
if (err < 0) { if (err < 0) {
printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]); 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) static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
{ {
int count, err; int count, err;
count = 0; count = 0;
err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000); err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000);
if (err < 0) { if (err < 0) {
@ -245,12 +243,14 @@ static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
return err; return err;
} }
#if 0
int ds_stop_pulse(struct ds_device *dev, int limit) int ds_stop_pulse(struct ds_device *dev, int limit)
{ {
struct ds_status st; struct ds_status st;
int count = 0, err = 0; int count = 0, err = 0;
u8 buf[0x20]; u8 buf[0x20];
do { do {
err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0); err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0);
if (err) 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 ds_detect(struct ds_device *dev, struct ds_status *st)
{ {
int err; int err;
err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
if (err) if (err)
return 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); err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0);
if (err) if (err)
return err; return err;
err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40); err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40);
if (err) if (err)
return err; return err;
err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG); err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG);
if (err) if (err)
return err; return err;
@ -297,7 +297,9 @@ int ds_detect(struct ds_device *dev, struct ds_status *st)
return err; 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]; u8 buf[0x20];
int err, count = 0; int err, count = 0;
@ -305,7 +307,7 @@ int ds_wait_status(struct ds_device *dev, struct ds_status *st)
do { do {
err = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); err = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
#if 0 #if 0
if (err >= 0) { if (err >= 0) {
int i; int i;
printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err); printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err);
for (i=0; i<err; ++i) 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) { if (((err > 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) {
ds_recv_status(dev, st); ds_recv_status(dev, st);
return -1; return -1;
} } else
else {
return 0; return 0;
}
} }
int ds_reset(struct ds_device *dev, struct ds_status *st) 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; return 0;
} }
#if 0
int ds_set_speed(struct ds_device *dev, int speed) int ds_set_speed(struct ds_device *dev, int speed)
{ {
int err; int err;
@ -356,20 +357,21 @@ int ds_set_speed(struct ds_device *dev, int speed)
speed = SPEED_FLEXIBLE; speed = SPEED_FLEXIBLE;
speed &= 0xff; speed &= 0xff;
err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed); err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed);
if (err) if (err)
return err; return 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; int err;
u8 del = 1 + (u8)(delay >> 4); u8 del = 1 + (u8)(delay >> 4);
struct ds_status st; struct ds_status st;
#if 0 #if 0
err = ds_stop_pulse(dev, 10); err = ds_stop_pulse(dev, 10);
if (err) if (err)
@ -390,7 +392,7 @@ int ds_start_pulse(struct ds_device *dev, int delay)
mdelay(delay); mdelay(delay);
ds_wait_status(dev, &st); ds_wait_status(dev, &st);
return err; return err;
} }
@ -400,7 +402,7 @@ int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit)
struct ds_status st; struct ds_status st;
u16 value = (COMM_BIT_IO | COMM_IM) | ((bit) ? COMM_D : 0); u16 value = (COMM_BIT_IO | COMM_IM) | ((bit) ? COMM_D : 0);
u16 cmd; u16 cmd;
err = ds_send_control(dev, value, 0); err = ds_send_control(dev, value, 0);
if (err) if (err)
return err; return err;
@ -430,7 +432,7 @@ int ds_write_bit(struct ds_device *dev, u8 bit)
{ {
int err; int err;
struct ds_status st; struct ds_status st;
err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit) ? COMM_D : 0, 0); err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit) ? COMM_D : 0, 0);
if (err) if (err)
return err; return err;
@ -445,7 +447,7 @@ int ds_write_byte(struct ds_device *dev, u8 byte)
int err; int err;
struct ds_status st; struct ds_status st;
u8 rbyte; u8 rbyte;
err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte); err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte);
if (err) if (err)
return err; return err;
@ -453,11 +455,11 @@ int ds_write_byte(struct ds_device *dev, u8 byte)
err = ds_wait_status(dev, &st); err = ds_wait_status(dev, &st);
if (err) if (err)
return err; return err;
err = ds_recv_data(dev, &rbyte, sizeof(rbyte)); err = ds_recv_data(dev, &rbyte, sizeof(rbyte));
if (err < 0) if (err < 0)
return err; return err;
ds_start_pulse(dev, PULLUP_PULSE_DURATION); ds_start_pulse(dev, PULLUP_PULSE_DURATION);
return !(byte == rbyte); 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); err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE);
if (err) if (err)
return err; return err;
err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | COMM_SPU | COMM_D, 0); err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | COMM_SPU | COMM_D, 0);
if (err) if (err)
return err; return err;
err = ds_recv_data(dev, bit, sizeof(*bit)); err = ds_recv_data(dev, bit, sizeof(*bit));
if (err < 0) if (err < 0)
return err; return err;
@ -492,7 +494,7 @@ int ds_read_byte(struct ds_device *dev, u8 *byte)
return err; return err;
ds_wait_status(dev, &st); ds_wait_status(dev, &st);
err = ds_recv_data(dev, byte, sizeof(*byte)); err = ds_recv_data(dev, byte, sizeof(*byte));
if (err < 0) if (err < 0)
return err; return err;
@ -509,17 +511,17 @@ int ds_read_block(struct ds_device *dev, u8 *buf, int len)
return -E2BIG; return -E2BIG;
memset(buf, 0xFF, len); memset(buf, 0xFF, len);
err = ds_send_data(dev, buf, len); err = ds_send_data(dev, buf, len);
if (err < 0) if (err < 0)
return err; return err;
err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len); err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
if (err) if (err)
return err; return err;
ds_wait_status(dev, &st); ds_wait_status(dev, &st);
memset(buf, 0x00, len); memset(buf, 0x00, len);
err = ds_recv_data(dev, buf, 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; int err;
struct ds_status st; struct ds_status st;
err = ds_send_data(dev, buf, len); err = ds_send_data(dev, buf, len);
if (err < 0) if (err < 0)
return err; return err;
ds_wait_status(dev, &st); ds_wait_status(dev, &st);
err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len); 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; return err;
ds_start_pulse(dev, PULLUP_PULSE_DURATION); ds_start_pulse(dev, PULLUP_PULSE_DURATION);
return !(err == len); return !(err == len);
} }
#if 0
int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search) int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search)
{ {
int err; 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; struct ds_status st;
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
err = ds_send_data(ds_dev, (unsigned char *)&init, 8); err = ds_send_data(ds_dev, (unsigned char *)&init, 8);
if (err) if (err)
return err; return err;
ds_wait_status(ds_dev, &st); ds_wait_status(ds_dev, &st);
value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS; 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)); err = ds_send_data(dev, (unsigned char *)&init, sizeof(init));
if (err) if (err)
return err; return err;
ds_wait_status(dev, &st); ds_wait_status(dev, &st);
err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055); 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); memcpy(buf, &init, 8);
buf[8] = BRANCH_MAIN; buf[8] = BRANCH_MAIN;
err = ds_send_data(dev, buf, sizeof(buf)); err = ds_send_data(dev, buf, sizeof(buf));
if (err) if (err)
return err; return err;
ds_wait_status(dev, &st); ds_wait_status(dev, &st);
err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0); 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; 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_device *udev = interface_to_usbdev(intf);
struct usb_endpoint_descriptor *endpoint; 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); printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err);
return err; return err;
} }
iface_desc = &intf->altsetting[0]; iface_desc = &intf->altsetting[0];
if (iface_desc->desc.bNumEndpoints != NUM_EP-1) { if (iface_desc->desc.bNumEndpoints != NUM_EP-1) {
printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints); 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); atomic_set(&ds_dev->refcnt, 0);
memset(ds_dev->ep, 0, sizeof(ds_dev->ep)); 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. * so we will fill only 1-3 endpoints entry.
*/ */
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc; endpoint = &iface_desc->endpoint[i].desc;
ds_dev->ep[i+1] = endpoint->bEndpointAddress; ds_dev->ep[i+1] = endpoint->bEndpointAddress;
printk("%d: addr=%x, size=%d, dir=%s, type=%x\n", printk("%d: addr=%x, size=%d, dir=%s, type=%x\n",
i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize), i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize),
(endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT", (endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT",
endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
} }
#if 0 #if 0
{ {
int err, i; int err, i;
u64 buf[3]; u64 buf[3];
u64 init=0xb30000002078ee81ull; u64 init=0xb30000002078ee81ull;
struct ds_status st; struct ds_status st;
ds_reset(ds_dev, &st); ds_reset(ds_dev, &st);
err = ds_search(ds_dev, init, buf, 3, 0); err = ds_search(ds_dev, init, buf, 3, 0);
if (err < 0) if (err < 0)
return err; return err;
for (i=0; i<err; ++i) for (i=0; i<err; ++i)
printk("%d: %llx\n", i, buf[i]); printk("%d: %llx\n", i, buf[i]);
printk("Resetting...\n"); printk("Resetting...\n");
ds_reset(ds_dev, &st); ds_reset(ds_dev, &st);
printk("Setting path for %llx.\n", init); printk("Setting path for %llx.\n", init);
err = ds_set_path(ds_dev, 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); err = ds_search(ds_dev, init, buf, 3, 0);
printk("ds_search() returned %d\n", err); printk("ds_search() returned %d\n", err);
if (err < 0) if (err < 0)
return err; return err;
for (i=0; i<err; ++i) for (i=0; i<err; ++i)
printk("%d: %llx\n", i, buf[i]); printk("%d: %llx\n", i, buf[i]);
return 0; return 0;
} }
#endif #endif
@ -720,10 +727,10 @@ int ds_probe(struct usb_interface *intf, const struct usb_device_id *udev_id)
return 0; return 0;
} }
void ds_disconnect(struct usb_interface *intf) static void ds_disconnect(struct usb_interface *intf)
{ {
struct ds_device *dev; struct ds_device *dev;
dev = usb_get_intfdata(intf); dev = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL); usb_set_intfdata(intf, NULL);
@ -740,7 +747,7 @@ void ds_disconnect(struct usb_interface *intf)
ds_dev = NULL; ds_dev = NULL;
} }
int ds_init(void) static int ds_init(void)
{ {
int err; int err;
@ -753,7 +760,7 @@ int ds_init(void)
return 0; return 0;
} }
void ds_fini(void) static void ds_fini(void)
{ {
usb_deregister(&ds_driver); usb_deregister(&ds_driver);
} }
@ -776,8 +783,8 @@ EXPORT_SYMBOL(ds_get_device);
EXPORT_SYMBOL(ds_put_device); EXPORT_SYMBOL(ds_put_device);
/* /*
* This functions can be used for EEPROM programming, * This functions can be used for EEPROM programming,
* when driver will be included into mainline this will * when driver will be included into mainline this will
* require uncommenting. * require uncommenting.
*/ */
#if 0 #if 0

View File

@ -1,8 +1,8 @@
/* /*
* dscore.h * dscore.h
* *
* Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru> * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
* *
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -122,7 +122,7 @@
struct ds_device struct ds_device
{ {
struct usb_device *udev; struct usb_device *udev;
struct usb_interface *intf; struct usb_interface *intf;
int ep[NUM_EP]; 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_read_bit(struct ds_device *, u8 *);
int ds_write_byte(struct ds_device *, u8); int ds_write_byte(struct ds_device *, u8);
int ds_write_bit(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_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); struct ds_device * ds_get_device(void);
void ds_put_device(struct ds_device *); void ds_put_device(struct ds_device *);
int ds_write_block(struct ds_device *, u8 *, int); int ds_write_block(struct ds_device *, u8 *, int);

View File

@ -45,10 +45,12 @@ MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol."); MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol.");
static int w1_timeout = 10; static int w1_timeout = 10;
static int w1_control_timeout = 1;
int w1_max_slave_count = 10; int w1_max_slave_count = 10;
int w1_max_slave_ttl = 10; int w1_max_slave_ttl = 10;
module_param_named(timeout, w1_timeout, int, 0); 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(max_slave_count, w1_max_slave_count, int, 0);
module_param_named(slave_ttl, w1_max_slave_ttl, 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 int control_needs_exit;
static DECLARE_COMPLETION(w1_control_complete); 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) static int w1_master_match(struct device *dev, struct device_driver *drv)
{ {
return 1; return 1;
@ -82,73 +71,116 @@ static int w1_master_probe(struct device *dev)
return -ENODEV; return -ENODEV;
} }
static int w1_master_remove(struct device *dev)
{
return 0;
}
static void w1_master_release(struct device *dev) 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) 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);
complete(&sl->dev_released); 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->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, static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, size_t count)
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 = static struct device_attribute w1_slave_attr_name =
__ATTR(name, S_IRUGO, w1_default_read_name, NULL); __ATTR(name, S_IRUGO, w1_slave_read_name, NULL);
static struct bin_attribute w1_slave_bin_attribute = { static struct bin_attribute w1_slave_attr_bin_id = {
.attr = { .attr = {
.name = "w1_slave", .name = "id",
.mode = S_IRUGO, .mode = S_IRUGO,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.size = W1_SLAVE_DATA_SIZE, .size = 8,
.read = &w1_default_read_bin, .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 = { static struct bus_type w1_bus_type = {
.name = "w1", .name = "w1",
.match = w1_master_match, .match = w1_master_match,
.hotplug = w1_hotplug,
}; };
struct device_driver w1_driver = { struct device_driver w1_master_driver = {
.name = "w1_driver", .name = "w1_master_driver",
.bus = &w1_bus_type, .bus = &w1_bus_type,
.probe = w1_master_probe, .probe = w1_master_probe,
.remove = w1_master_remove,
}; };
struct device w1_device = { struct device w1_master_device = {
.parent = NULL, .parent = NULL,
.bus = &w1_bus_type, .bus = &w1_bus_type,
.bus_id = "w1 bus master", .bus_id = "w1 bus master",
.driver = &w1_driver, .driver = &w1_master_driver,
.release = &w1_master_release .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) 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; ssize_t count;
if (down_interruptible (&md->mutex)) if (down_interruptible (&md->mutex))
@ -165,7 +197,7 @@ static ssize_t w1_master_attribute_store_search(struct device * dev,
struct device_attribute *attr, struct device_attribute *attr,
const char * buf, size_t count) 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)) if (down_interruptible (&md->mutex))
return -EBUSY; return -EBUSY;
@ -181,7 +213,7 @@ static ssize_t w1_master_attribute_show_search(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) 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; ssize_t count;
if (down_interruptible (&md->mutex)) 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) 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; ssize_t count;
if (down_interruptible(&md->mutex)) 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) 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; ssize_t count;
if (down_interruptible(&md->mutex)) 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) 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; ssize_t count;
if (down_interruptible(&md->mutex)) 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) 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; ssize_t count;
if (down_interruptible(&md->mutex)) 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) 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; int c = PAGE_SIZE;
if (down_interruptible(&md->mutex)) 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); 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) static int __w1_attach_slave_device(struct w1_slave *sl)
{ {
int err; int err;
sl->dev.parent = &sl->master->dev; 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.bus = &w1_bus_type;
sl->dev.release = &w1_slave_release; 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 int) sl->reg_num.family,
(unsigned long long) sl->reg_num.id); (unsigned long long) sl->reg_num.id);
dev_dbg(&sl->dev, "%s: registering %s.\n", __func__, dev_dbg(&sl->dev, "%s: registering %s as %p.\n", __func__, &sl->dev.bus_id[0]);
&sl->dev.bus_id[0]);
err = device_register(&sl->dev); err = device_register(&sl->dev);
if (err < 0) { if (err < 0) {
@ -358,36 +432,44 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
return err; return err;
} }
memcpy(&sl->attr_bin, &w1_slave_bin_attribute, sizeof(sl->attr_bin)); /* Create "name" entry */
memcpy(&sl->attr_name, &w1_slave_attribute, sizeof(sl->attr_name)); err = device_create_file(&sl->dev, &w1_slave_attr_name);
sl->attr_bin.read = sl->family->fops->rbin;
sl->attr_name.show = sl->family->fops->rname;
err = device_create_file(&sl->dev, &sl->attr_name);
if (err < 0) { if (err < 0) {
dev_err(&sl->dev, dev_err(&sl->dev,
"sysfs file creation for [%s] failed. err=%d\n", "sysfs file creation for [%s] failed. err=%d\n",
sl->dev.bus_id, err); sl->dev.bus_id, err);
device_unregister(&sl->dev); goto out_unreg;
return err;
} }
if ( sl->attr_bin.read ) { /* Create "id" entry */
err = sysfs_create_bin_file(&sl->dev.kobj, &sl->attr_bin); err = sysfs_create_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id);
if (err < 0) { if (err < 0) {
dev_err(&sl->dev, dev_err(&sl->dev,
"sysfs file creation for [%s] failed. err=%d\n", "sysfs file creation for [%s] failed. err=%d\n",
sl->dev.bus_id, err); sl->dev.bus_id, err);
device_remove_file(&sl->dev, &sl->attr_name); goto out_rem1;
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); list_add_tail(&sl->w1_slave_entry, &sl->master->slist);
return 0; 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) 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)); memcpy(&sl->reg_num, rn, sizeof(sl->reg_num));
atomic_set(&sl->refcnt, 0); atomic_set(&sl->refcnt, 0);
init_completion(&sl->dev_released); init_completion(&sl->released);
spin_lock(&w1_flock); spin_lock(&w1_flock);
f = w1_family_registered(rn->family); f = w1_family_registered(rn->family);
@ -452,28 +534,23 @@ static void w1_slave_detach(struct w1_slave *sl)
{ {
struct w1_netlink_msg msg; struct w1_netlink_msg msg;
dev_info(&sl->dev, "%s: detaching %s.\n", __func__, sl->name); dev_dbg(&sl->dev, "%s: detaching %s [%p].\n", __func__, sl->name, sl);
while (atomic_read(&sl->refcnt)) { list_del(&sl->w1_slave_entry);
printk(KERN_INFO "Waiting for %s to become free: refcnt=%d.\n",
sl->name, atomic_read(&sl->refcnt));
if (msleep_interruptible(1000)) if (sl->family->fops && sl->family->fops->remove_slave)
flush_signals(current); sl->family->fops->remove_slave(sl);
}
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);
sl->master->slave_count--;
memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id)); memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id));
msg.type = W1_SLAVE_REMOVE; msg.type = W1_SLAVE_REMOVE;
w1_netlink_send(sl->master, &msg); 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) 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); spin_lock_bh(&w1_mlock);
list_for_each_entry(dev, &w1_masters, w1_master_entry) { 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); dev->name, f->fid);
set_bit(W1_MASTER_NEED_RECONNECT, &dev->flags); set_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
} }
spin_unlock_bh(&w1_mlock); spin_unlock_bh(&w1_mlock);
} }
static void w1_slave_found(unsigned long data, u64 rn) static void w1_slave_found(unsigned long data, u64 rn)
{ {
int slave_count; int slave_count;
@ -646,7 +722,7 @@ static int w1_control(void *data)
have_to_wait = 0; have_to_wait = 0;
try_to_freeze(); try_to_freeze();
msleep_interruptible(w1_timeout * 1000); msleep_interruptible(w1_control_timeout * 1000);
if (signal_pending(current)) if (signal_pending(current))
flush_signals(current); flush_signals(current);
@ -679,33 +755,30 @@ static int w1_control(void *data)
list_del(&dev->w1_master_entry); list_del(&dev->w1_master_entry);
spin_unlock_bh(&w1_mlock); spin_unlock_bh(&w1_mlock);
down(&dev->mutex);
list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
list_del(&sl->w1_slave_entry);
w1_slave_detach(sl); w1_slave_detach(sl);
kfree(sl);
} }
w1_destroy_master_attributes(dev); w1_destroy_master_attributes(dev);
up(&dev->mutex);
atomic_dec(&dev->refcnt); atomic_dec(&dev->refcnt);
continue; continue;
} }
if (test_bit(W1_MASTER_NEED_RECONNECT, &dev->flags)) { 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); 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) { if (sl->family->fid == W1_FAMILY_DEFAULT) {
struct w1_reg_num rn; struct w1_reg_num rn;
list_del(&sl->w1_slave_entry);
w1_slave_detach(sl);
memcpy(&rn, &sl->reg_num, sizeof(rn)); memcpy(&rn, &sl->reg_num, sizeof(rn));
w1_slave_detach(sl);
kfree(sl);
w1_attach_slave_device(dev, &rn); 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); clear_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
up(&dev->mutex); up(&dev->mutex);
} }
@ -749,10 +822,7 @@ int w1_process(void *data)
list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) { if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) {
list_del (&sl->w1_slave_entry); w1_slave_detach(sl);
w1_slave_detach (sl);
kfree (sl);
dev->slave_count--; dev->slave_count--;
} else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags)) } 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; goto err_out_exit_init;
} }
retval = driver_register(&w1_driver); retval = driver_register(&w1_master_driver);
if (retval) { if (retval) {
printk(KERN_ERR printk(KERN_ERR
"Failed to register master driver. err=%d.\n", "Failed to register master driver. err=%d.\n",
@ -791,18 +861,29 @@ static int w1_init(void)
goto err_out_bus_unregister; 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); control_thread = kernel_thread(&w1_control, NULL, 0);
if (control_thread < 0) { if (control_thread < 0) {
printk(KERN_ERR "Failed to create control thread. err=%d\n", printk(KERN_ERR "Failed to create control thread. err=%d\n",
control_thread); control_thread);
retval = control_thread; retval = control_thread;
goto err_out_driver_unregister; goto err_out_slave_unregister;
} }
return 0; return 0;
err_out_driver_unregister: err_out_slave_unregister:
driver_unregister(&w1_driver); driver_unregister(&w1_slave_driver);
err_out_master_unregister:
driver_unregister(&w1_master_driver);
err_out_bus_unregister: err_out_bus_unregister:
bus_unregister(&w1_bus_type); bus_unregister(&w1_bus_type);
@ -821,7 +902,8 @@ static void w1_fini(void)
control_needs_exit = 1; control_needs_exit = 1;
wait_for_completion(&w1_control_complete); 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); bus_unregister(&w1_bus_type);
} }

View File

@ -75,11 +75,9 @@ struct w1_slave
struct w1_master *master; struct w1_master *master;
struct w1_family *family; struct w1_family *family;
void *family_data;
struct device dev; struct device dev;
struct completion dev_released; struct completion released;
struct bin_attribute attr_bin;
struct device_attribute attr_name;
}; };
typedef void (* w1_slave_found_callback)(unsigned long, u64); typedef void (* w1_slave_found_callback)(unsigned long, u64);
@ -179,7 +177,6 @@ struct w1_master
struct device_driver *driver; struct device_driver *driver;
struct device dev; struct device dev;
struct completion dev_released;
struct completion dev_exited; struct completion dev_exited;
struct w1_bus_master *bus_master; struct w1_bus_master *bus_master;
@ -191,6 +188,21 @@ struct w1_master
int w1_create_master_attributes(struct w1_master *); 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, 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 /* __KERNEL__ */
#endif /* __W1_H */ #endif /* __W1_H */

327
drivers/w1/w1_ds2433.c Normal file
View File

@ -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);

View File

@ -29,23 +29,12 @@ DEFINE_SPINLOCK(w1_flock);
static LIST_HEAD(w1_families); static LIST_HEAD(w1_families);
extern void w1_reconnect_slaves(struct w1_family *f); 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) int w1_register_family(struct w1_family *newf)
{ {
struct list_head *ent, *n; struct list_head *ent, *n;
struct w1_family *f; struct w1_family *f;
int ret = 0; int ret = 0;
if (w1_check_family(newf))
return -EINVAL;
spin_lock(&w1_flock); spin_lock(&w1_flock);
list_for_each_safe(ent, n, &w1_families) { list_for_each_safe(ent, n, &w1_families) {
f = list_entry(ent, struct w1_family, family_entry); f = list_entry(ent, struct w1_family, family_entry);

View File

@ -31,14 +31,17 @@
#define W1_FAMILY_SMEM_81 0x81 #define W1_FAMILY_SMEM_81 0x81
#define W1_THERM_DS18S20 0x10 #define W1_THERM_DS18S20 0x10
#define W1_THERM_DS1822 0x22 #define W1_THERM_DS1822 0x22
#define W1_EEPROM_DS2433 0x23
#define W1_THERM_DS18B20 0x28 #define W1_THERM_DS18B20 0x28
#define MAXNAMELEN 32 #define MAXNAMELEN 32
struct w1_slave;
struct w1_family_ops struct w1_family_ops
{ {
ssize_t (* rname)(struct device *, struct device_attribute *, char *); int (* add_slave)(struct w1_slave *);
ssize_t (* rbin)(struct kobject *, char *, loff_t, size_t); void (* remove_slave)(struct w1_slave *);
}; };
struct w1_family struct w1_family

View File

@ -29,9 +29,9 @@
static u32 w1_ids = 1; 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 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_count;
extern int w1_max_slave_ttl; extern int w1_max_slave_ttl;
extern struct list_head w1_masters; 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_LIST_HEAD(&dev->slist);
init_MUTEX(&dev->mutex); init_MUTEX(&dev->mutex);
init_completion(&dev->dev_released);
init_completion(&dev->dev_exited); init_completion(&dev->dev_exited);
memcpy(&dev->dev, device, sizeof(struct device)); 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->groups = 1;
dev->seq = 1; dev->seq = 1;
dev->nls = netlink_kernel_create(NETLINK_W1, 1, NULL, THIS_MODULE); dev_init_netlink(dev);
if (!dev->nls) {
printk(KERN_ERR "Failed to create new netlink socket(%u) for w1 master %s.\n",
NETLINK_NFLOG, dev->dev.bus_id);
}
err = device_register(&dev->dev); err = device_register(&dev->dev);
if (err) { if (err) {
printk(KERN_ERR "Failed to register master device. err=%d\n", 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)); memset(dev, 0, sizeof(struct w1_master));
kfree(dev); kfree(dev);
dev = NULL; dev = NULL;
@ -107,13 +103,9 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
return dev; return dev;
} }
static void w1_free_dev(struct w1_master *dev) void w1_free_dev(struct w1_master *dev)
{ {
device_unregister(&dev->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) 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); 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) if (!dev)
return -ENOMEM; return -ENOMEM;
@ -188,7 +180,7 @@ void __w1_remove_master_device(struct w1_master *dev)
__func__, dev->kpid); __func__, dev->kpid);
while (atomic_read(&dev->refcnt)) { 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)); dev->name, atomic_read(&dev->refcnt));
if (msleep_interruptible(1000)) if (msleep_interruptible(1000))

View File

@ -277,6 +277,29 @@ void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb)
w1_search(dev, 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_touch_bit);
EXPORT_SYMBOL(w1_write_8); EXPORT_SYMBOL(w1_write_8);
EXPORT_SYMBOL(w1_read_8); EXPORT_SYMBOL(w1_read_8);
@ -286,3 +309,4 @@ EXPORT_SYMBOL(w1_delay);
EXPORT_SYMBOL(w1_read_block); EXPORT_SYMBOL(w1_read_block);
EXPORT_SYMBOL(w1_write_block); EXPORT_SYMBOL(w1_write_block);
EXPORT_SYMBOL(w1_search_devices); EXPORT_SYMBOL(w1_search_devices);
EXPORT_SYMBOL(w1_reset_select_slave);

View File

@ -34,5 +34,6 @@ u8 w1_calc_crc8(u8 *, int);
void w1_write_block(struct w1_master *, const u8 *, int); void w1_write_block(struct w1_master *, const u8 *, int);
u8 w1_read_block(struct w1_master *, u8 *, int); u8 w1_read_block(struct w1_master *, u8 *, int);
void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb); 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 */ #endif /* __W1_IO_H */

View File

@ -57,10 +57,36 @@ void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
nlmsg_failure: nlmsg_failure:
return; 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 #else
#warning Netlink support is disabled. Please compile with NET support enabled. #warning Netlink support is disabled. Please compile with NET support enabled.
void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg) 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 #endif

View File

@ -52,6 +52,8 @@ struct w1_netlink_msg
#ifdef __KERNEL__ #ifdef __KERNEL__
void w1_netlink_send(struct w1_master *, struct w1_netlink_msg *); 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 /* __KERNEL__ */
#endif /* __W1_NETLINK_H */ #endif /* __W1_NETLINK_H */

View File

@ -36,61 +36,12 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>"); MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family."); 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 = { static struct w1_family w1_smem_family_01 = {
.fid = W1_FAMILY_SMEM_01, .fid = W1_FAMILY_SMEM_01,
.fops = &w1_smem_fops,
}; };
static struct w1_family w1_smem_family_81 = { static struct w1_family w1_smem_family_81 = {
.fid = W1_FAMILY_SMEM_81, .fid = W1_FAMILY_SMEM_81,
.fops = &w1_smem_fops,
}; };
static int __init w1_smem_init(void) static int __init w1_smem_init(void)

View 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 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 = { static struct w1_family_ops w1_therm_fops = {
.rname = &w1_therm_read_name, .add_slave = w1_therm_add_slave,
.rbin = &w1_therm_read_bin, .remove_slave = w1_therm_remove_slave,
}; };
static struct w1_family w1_therm_family_DS18S20 = { static struct w1_family w1_therm_family_DS18S20 = {
@ -59,6 +78,7 @@ static struct w1_family w1_therm_family_DS18B20 = {
.fid = W1_THERM_DS18B20, .fid = W1_THERM_DS18B20,
.fops = &w1_therm_fops, .fops = &w1_therm_fops,
}; };
static struct w1_family w1_therm_family_DS1822 = { static struct w1_family w1_therm_family_DS1822 = {
.fid = W1_THERM_DS1822, .fid = W1_THERM_DS1822,
.fops = &w1_therm_fops, .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]) static inline int w1_DS18B20_convert_temp(u8 rom[9])
{ {
int t = (rom[1] << 8) | rom[0]; 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) 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 *sl = kobj_to_w1_slave(kobj);
struct w1_slave, dev);
struct w1_master *dev = sl->master; struct w1_master *dev = sl->master;
u8 rom[9], crc, verdict; u8 rom[9], crc, verdict;
int i, max_trying = 10; 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; crc = 0;
while (max_trying--) { while (max_trying--) {
if (!w1_reset_bus (dev)) { if (!w1_reset_select_slave(sl)) {
int count = 0; int count = 0;
u8 match[9] = {W1_MATCH_ROM, };
unsigned int tm = 750; 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); w1_write_8(dev, W1_CONVERT_TEMP);
while (tm) { 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); flush_signals(current);
} }
if (!w1_reset_bus (dev)) { if (!w1_reset_select_slave(sl)) {
w1_write_block(dev, match, 9);
w1_write_8(dev, W1_READ_SCRATCHPAD); w1_write_8(dev, W1_READ_SCRATCHPAD);
if ((count = w1_read_block(dev, rom, 9)) != 9) { 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]) if (rom[8] == crc && rom[0])
verdict = 1; verdict = 1;
} }
} }

44
include/linux/crc16.h Normal file
View File

@ -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 */

View File

@ -12,6 +12,14 @@ config CRC_CCITT
the kernel tree does. Such modules that use library CRC-CCITT the kernel tree does. Such modules that use library CRC-CCITT
functions require M here. 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 config CRC32
tristate "CRC32 functions" tristate "CRC32 functions"
default y default y

View File

@ -23,11 +23,12 @@ lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.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 lib-y += dec_and_lock.o
endif endif
obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o
obj-$(CONFIG_CRC16) += crc16.o
obj-$(CONFIG_CRC32) += crc32.o obj-$(CONFIG_CRC32) += crc32.o
obj-$(CONFIG_LIBCRC32C) += libcrc32c.o obj-$(CONFIG_LIBCRC32C) += libcrc32c.o
obj-$(CONFIG_GENERIC_IOMAP) += iomap.o obj-$(CONFIG_GENERIC_IOMAP) += iomap.o

67
lib/crc16.c Normal file
View File

@ -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");