Commit | Line | Data |
---|---|---|
94859308 SA |
1 | /* |
2 | * w1_ds2406.c - w1 family 12 (DS2406) driver | |
3 | * based on w1_ds2413.c by Mariusz Bialonczyk <manio@skyboo.net> | |
4 | * | |
5 | * Copyright (c) 2014 Scott Alfter <scott@alfter.us> | |
6 | * | |
7 | * This source code is licensed under the GNU General Public License, | |
8 | * Version 2. See the file COPYING for more details. | |
9 | */ | |
10 | ||
11 | #include <linux/kernel.h> | |
12 | #include <linux/module.h> | |
13 | #include <linux/moduleparam.h> | |
14 | #include <linux/device.h> | |
15 | #include <linux/types.h> | |
16 | #include <linux/delay.h> | |
17 | #include <linux/slab.h> | |
18 | #include <linux/crc16.h> | |
19 | ||
20 | #include "../w1.h" | |
21 | #include "../w1_int.h" | |
22 | #include "../w1_family.h" | |
23 | ||
24 | MODULE_LICENSE("GPL"); | |
25 | MODULE_AUTHOR("Scott Alfter <scott@alfter.us>"); | |
26 | MODULE_DESCRIPTION("w1 family 12 driver for DS2406 2 Pin IO"); | |
27 | ||
28 | #define W1_F12_FUNC_READ_STATUS 0xAA | |
29 | #define W1_F12_FUNC_WRITE_STATUS 0x55 | |
30 | ||
31 | static ssize_t w1_f12_read_state( | |
32 | struct file *filp, struct kobject *kobj, | |
33 | struct bin_attribute *bin_attr, | |
34 | char *buf, loff_t off, size_t count) | |
35 | { | |
36 | u8 w1_buf[6]={W1_F12_FUNC_READ_STATUS, 7, 0, 0, 0, 0}; | |
37 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | |
38 | u16 crc=0; | |
39 | int i; | |
40 | ssize_t rtnval=1; | |
41 | ||
42 | if (off != 0) | |
43 | return 0; | |
44 | if (!buf) | |
45 | return -EINVAL; | |
46 | ||
47 | mutex_lock(&sl->master->bus_mutex); | |
48 | ||
49 | if (w1_reset_select_slave(sl)) { | |
50 | mutex_unlock(&sl->master->bus_mutex); | |
51 | return -EIO; | |
52 | } | |
53 | ||
54 | w1_write_block(sl->master, w1_buf, 3); | |
55 | w1_read_block(sl->master, w1_buf+3, 3); | |
56 | for (i=0; i<6; i++) | |
57 | crc=crc16_byte(crc, w1_buf[i]); | |
58 | if (crc==0xb001) /* good read? */ | |
59 | *buf=((w1_buf[3]>>5)&3)|0x30; | |
60 | else | |
61 | rtnval=-EIO; | |
62 | ||
63 | mutex_unlock(&sl->master->bus_mutex); | |
64 | ||
65 | return rtnval; | |
66 | } | |
67 | ||
68 | static ssize_t w1_f12_write_output( | |
69 | struct file *filp, struct kobject *kobj, | |
70 | struct bin_attribute *bin_attr, | |
71 | char *buf, loff_t off, size_t count) | |
72 | { | |
73 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | |
74 | u8 w1_buf[6]={W1_F12_FUNC_WRITE_STATUS, 7, 0, 0, 0, 0}; | |
75 | u16 crc=0; | |
76 | int i; | |
77 | ssize_t rtnval=1; | |
78 | ||
79 | if (count != 1 || off != 0) | |
80 | return -EFAULT; | |
81 | ||
82 | mutex_lock(&sl->master->bus_mutex); | |
83 | ||
84 | if (w1_reset_select_slave(sl)) { | |
85 | mutex_unlock(&sl->master->bus_mutex); | |
86 | return -EIO; | |
87 | } | |
88 | ||
89 | w1_buf[3] = (((*buf)&3)<<5)|0x1F; | |
90 | w1_write_block(sl->master, w1_buf, 4); | |
91 | w1_read_block(sl->master, w1_buf+4, 2); | |
92 | for (i=0; i<6; i++) | |
93 | crc=crc16_byte(crc, w1_buf[i]); | |
94 | if (crc==0xb001) /* good read? */ | |
95 | w1_write_8(sl->master, 0xFF); | |
96 | else | |
97 | rtnval=-EIO; | |
98 | ||
99 | mutex_unlock(&sl->master->bus_mutex); | |
100 | return rtnval; | |
101 | } | |
102 | ||
103 | #define NB_SYSFS_BIN_FILES 2 | |
104 | static struct bin_attribute w1_f12_sysfs_bin_files[NB_SYSFS_BIN_FILES] = { | |
105 | { | |
106 | .attr = { | |
107 | .name = "state", | |
108 | .mode = S_IRUGO, | |
109 | }, | |
110 | .size = 1, | |
111 | .read = w1_f12_read_state, | |
112 | }, | |
113 | { | |
114 | .attr = { | |
115 | .name = "output", | |
116 | .mode = S_IRUGO | S_IWUSR | S_IWGRP, | |
117 | }, | |
118 | .size = 1, | |
119 | .write = w1_f12_write_output, | |
120 | } | |
121 | }; | |
122 | ||
123 | static int w1_f12_add_slave(struct w1_slave *sl) | |
124 | { | |
125 | int err = 0; | |
126 | int i; | |
127 | ||
128 | for (i = 0; i < NB_SYSFS_BIN_FILES && !err; ++i) | |
129 | err = sysfs_create_bin_file( | |
130 | &sl->dev.kobj, | |
131 | &(w1_f12_sysfs_bin_files[i])); | |
132 | if (err) | |
133 | while (--i >= 0) | |
134 | sysfs_remove_bin_file(&sl->dev.kobj, | |
135 | &(w1_f12_sysfs_bin_files[i])); | |
136 | return err; | |
137 | } | |
138 | ||
139 | static void w1_f12_remove_slave(struct w1_slave *sl) | |
140 | { | |
141 | int i; | |
142 | for (i = NB_SYSFS_BIN_FILES - 1; i >= 0; --i) | |
143 | sysfs_remove_bin_file(&sl->dev.kobj, | |
144 | &(w1_f12_sysfs_bin_files[i])); | |
145 | } | |
146 | ||
147 | static struct w1_family_ops w1_f12_fops = { | |
148 | .add_slave = w1_f12_add_slave, | |
149 | .remove_slave = w1_f12_remove_slave, | |
150 | }; | |
151 | ||
152 | static struct w1_family w1_family_12 = { | |
153 | .fid = W1_FAMILY_DS2406, | |
154 | .fops = &w1_f12_fops, | |
155 | }; | |
939fc832 | 156 | module_w1_family(w1_family_12); |