aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/w1/w1_netlink.c
diff options
context:
space:
mode:
authorEvgeniy Polyakov <zbr@ioremap.net>2009-01-07 21:08:59 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-08 11:31:13 -0500
commit610705e780395ef30a1b8e53de150c37381ca31f (patch)
treed847963358b5bc568e265b3807ef4b3de13ca7ef /drivers/w1/w1_netlink.c
parenta5fd9139f74c722a190b3bd69bbd611a8d91b388 (diff)
w1: add list masters w1 command
This patch series introduces and extends several userspace commands used with netlink protocol. Touch block command allows to write data and return sampled data to the userspace. Extended search and alarm seach commands to return list of slave devices found during given search. List masters command allows to send all registered master IDs to the userspace. Great thanks to Paul Alfille (owfs) who tested this implementation and wrote w1-to-network daemon http://sourceforge.net/projects/w1repeater/ and Frederik Deweerdt and Randy Dunlap for review. This patch: Returns list of registered bus master devices. Signed-off-by: Evgeniy Polyakov <zbr@ioremap.net> Cc: Paul Alfille <paul.alfille@gmail.com> Cc: Frederik Deweerdt <frederik.deweerdt@xprog.eu> Cc: Randy Dunlap <randy.dunlap@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/w1/w1_netlink.c')
-rw-r--r--drivers/w1/w1_netlink.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c
index 65c5ebd0787e..2e07b59b9859 100644
--- a/drivers/w1/w1_netlink.c
+++ b/drivers/w1/w1_netlink.c
@@ -128,6 +128,59 @@ static int w1_process_command_slave(struct w1_slave *sl, struct cn_msg *msg,
128 return err; 128 return err;
129} 129}
130 130
131static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mcmd)
132{
133 struct w1_master *m;
134 struct cn_msg *cn;
135 struct w1_netlink_msg *w;
136 u32 *id;
137
138 if (mcmd->type != W1_LIST_MASTERS) {
139 printk(KERN_NOTICE "%s: msg: %x.%x, wrong type: %u, len: %u.\n",
140 __func__, msg->id.idx, msg->id.val, mcmd->type, mcmd->len);
141 return -EPROTO;
142 }
143
144 cn = kmalloc(PAGE_SIZE, GFP_KERNEL);
145 if (!cn)
146 return -ENOMEM;
147
148 cn->id.idx = CN_W1_IDX;
149 cn->id.val = CN_W1_VAL;
150
151 cn->seq = msg->seq;
152 cn->ack = 1;
153 cn->len = sizeof(struct w1_netlink_msg);
154 w = (struct w1_netlink_msg *)(cn + 1);
155
156 w->type = W1_LIST_MASTERS;
157 w->reserved = 0;
158 w->len = 0;
159 id = (u32 *)(w + 1);
160
161 mutex_lock(&w1_mlock);
162 list_for_each_entry(m, &w1_masters, w1_master_entry) {
163 if (cn->len + sizeof(*id) > PAGE_SIZE - sizeof(struct cn_msg)) {
164 cn_netlink_send(cn, 0, GFP_KERNEL);
165 cn->ack++;
166 cn->len = sizeof(struct w1_netlink_msg);
167 w->len = 0;
168 id = (u32 *)(w + 1);
169 }
170
171 *id = m->id;
172 w->len += sizeof(*id);
173 cn->len += sizeof(*id);
174 id++;
175 }
176 cn->ack = 0;
177 cn_netlink_send(cn, 0, GFP_KERNEL);
178 mutex_unlock(&w1_mlock);
179
180 kfree(cn);
181 return 0;
182}
183
131static void w1_cn_callback(void *data) 184static void w1_cn_callback(void *data)
132{ 185{
133 struct cn_msg *msg = data; 186 struct cn_msg *msg = data;
@@ -164,6 +217,9 @@ static void w1_cn_callback(void *data)
164 sl = w1_search_slave(&id); 217 sl = w1_search_slave(&id);
165 if (sl) 218 if (sl)
166 dev = sl->master; 219 dev = sl->master;
220 } else {
221 err = w1_process_command_root(msg, m);
222 goto out_cont;
167 } 223 }
168 224
169 if (!dev) { 225 if (!dev) {