4 * Copyright (c) 2010 Mika Laitio <lamikr@pilppa.org>
6 * This driver will read and write the value of 4 counters to w1_slave file in
8 * Inspired by the w1_therm and w1_ds2431 drivers.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the therms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include <linux/kernel.h>
26 #include <linux/module.h>
27 #include <linux/moduleparam.h>
28 #include <linux/device.h>
29 #include <linux/types.h>
30 #include <linux/delay.h>
31 #include <linux/crc16.h>
34 #include "../w1_int.h"
35 #include "../w1_family.h"
37 #define CRC16_VALID 0xb001
40 #define COUNTER_COUNT 4
41 #define READ_BYTE_COUNT 42
43 static ssize_t
w1_counter_read(struct device
*device
,
44 struct device_attribute
*attr
, char *buf
);
46 static struct device_attribute w1_counter_attr
=
47 __ATTR(w1_slave
, S_IRUGO
, w1_counter_read
, NULL
);
49 static ssize_t
w1_counter_read(struct device
*device
,
50 struct device_attribute
*attr
, char *out_buf
)
52 struct w1_slave
*sl
= dev_to_w1_slave(device
);
53 struct w1_master
*dev
= sl
->master
;
54 u8 rbuf
[COUNTER_COUNT
* READ_BYTE_COUNT
];
65 rom_addr
= (12 << 5) + 31;
67 wrbuf
[1] = rom_addr
& 0xFF;
68 wrbuf
[2] = rom_addr
>> 8;
69 mutex_lock(&dev
->mutex
);
70 if (!w1_reset_select_slave(sl
)) {
71 w1_write_block(dev
, wrbuf
, 3);
73 for (p
= 0; p
< 4; p
++) {
75 * 1 byte for first bytes in ram page read
77 * 4 bytes for zero bits
79 * 31 remaining bytes from the ram page
81 read_byte_count
+= w1_read_block(dev
,
82 rbuf
+ (p
* READ_BYTE_COUNT
), READ_BYTE_COUNT
);
83 for (ii
= 0; ii
< READ_BYTE_COUNT
; ++ii
)
84 c
-= snprintf(out_buf
+ PAGE_SIZE
- c
,
86 rbuf
[(p
* READ_BYTE_COUNT
) + ii
]);
87 if (read_byte_count
!= (p
+ 1) * READ_BYTE_COUNT
) {
89 "w1_counter_read() returned %u bytes "
90 "instead of %d bytes wanted.\n",
93 c
-= snprintf(out_buf
+ PAGE_SIZE
- c
,
97 crc
= crc16(CRC16_INIT
, wrbuf
, 3);
98 crc
= crc16(crc
, rbuf
, 11);
101 * DS2423 calculates crc from all bytes
102 * read after the previous crc bytes.
104 crc
= crc16(CRC16_INIT
,
106 ((p
- 1) * READ_BYTE_COUNT
),
109 if (crc
== CRC16_VALID
) {
111 for (ii
= 4; ii
> 0; ii
--) {
114 READ_BYTE_COUNT
) + ii
];
116 c
-= snprintf(out_buf
+ PAGE_SIZE
- c
,
117 c
, "crc=YES c=%d\n", result
);
119 c
-= snprintf(out_buf
+ PAGE_SIZE
- c
,
125 c
-= snprintf(out_buf
+ PAGE_SIZE
- c
, c
, "Connection error");
127 mutex_unlock(&dev
->mutex
);
128 return PAGE_SIZE
- c
;
131 static int w1_f1d_add_slave(struct w1_slave
*sl
)
133 return device_create_file(&sl
->dev
, &w1_counter_attr
);
136 static void w1_f1d_remove_slave(struct w1_slave
*sl
)
138 device_remove_file(&sl
->dev
, &w1_counter_attr
);
141 static struct w1_family_ops w1_f1d_fops
= {
142 .add_slave
= w1_f1d_add_slave
,
143 .remove_slave
= w1_f1d_remove_slave
,
146 static struct w1_family w1_family_1d
= {
147 .fid
= W1_COUNTER_DS2423
,
148 .fops
= &w1_f1d_fops
,
151 static int __init
w1_f1d_init(void)
153 return w1_register_family(&w1_family_1d
);
156 static void __exit
w1_f1d_exit(void)
158 w1_unregister_family(&w1_family_1d
);
161 module_init(w1_f1d_init
);
162 module_exit(w1_f1d_exit
);
164 MODULE_LICENSE("GPL");
165 MODULE_AUTHOR("Mika Laitio <lamikr@pilppa.org>");
166 MODULE_DESCRIPTION("w1 family 1d driver for DS2423, 4 counters and 4kb ram");