diff options
author | Evgeniy Polyakov <zbr@ioremap.net> | 2009-01-07 21:09:01 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-08 11:31:13 -0500 |
commit | 3b8384070ea1dc358f6da6233b3b6c0926ae1bf4 (patch) | |
tree | 00535e5b18029c95f59efb68612ff2e57bb7ac82 /drivers/w1/w1_netlink.c | |
parent | 9be62e0b2fadaf5ffeb32fd1b910ef1fe6bd43db (diff) |
w1: list slaves commands
Initiates search (or alarm search) and returns all found devices to
userspace. Found devices are not added into the system (i.e. they are
not attached to family devices or bus masters), it will be done via (if
was not done yet) usual timed searching.
Signed-off-by: Evgeniy Polyakov <zbr@ioremap.net>
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.c | 102 |
1 files changed, 85 insertions, 17 deletions
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c index cae556c8577b..8a7021577f32 100644 --- a/drivers/w1/w1_netlink.c +++ b/drivers/w1/w1_netlink.c | |||
@@ -47,19 +47,97 @@ void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg) | |||
47 | cn_netlink_send(m, 0, GFP_KERNEL); | 47 | cn_netlink_send(m, 0, GFP_KERNEL); |
48 | } | 48 | } |
49 | 49 | ||
50 | static int w1_process_command_master(struct w1_master *dev, struct cn_msg *msg, | 50 | static void w1_send_slave(struct w1_master *dev, u64 rn) |
51 | struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd) | 51 | { |
52 | struct cn_msg *msg = dev->priv; | ||
53 | struct w1_netlink_msg *hdr = (struct w1_netlink_msg *)(msg + 1); | ||
54 | struct w1_netlink_cmd *cmd = (struct w1_netlink_cmd *)(hdr + 1); | ||
55 | int avail; | ||
56 | |||
57 | avail = dev->priv_size - cmd->len; | ||
58 | |||
59 | if (avail > 8) { | ||
60 | u64 *data = (void *)(cmd + 1) + cmd->len; | ||
61 | |||
62 | *data = rn; | ||
63 | cmd->len += 8; | ||
64 | hdr->len += 8; | ||
65 | msg->len += 8; | ||
66 | return; | ||
67 | } | ||
68 | |||
69 | msg->ack++; | ||
70 | cn_netlink_send(msg, 0, GFP_KERNEL); | ||
71 | |||
72 | msg->len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd); | ||
73 | hdr->len = sizeof(struct w1_netlink_cmd); | ||
74 | cmd->len = 0; | ||
75 | } | ||
76 | |||
77 | static int w1_process_search_command(struct w1_master *dev, struct cn_msg *msg, | ||
78 | unsigned int avail) | ||
52 | { | 79 | { |
53 | dev_dbg(&dev->dev, "%s: %s: cmd=%02x, len=%u.\n", | 80 | struct w1_netlink_msg *hdr = (struct w1_netlink_msg *)(msg + 1); |
54 | __func__, dev->name, cmd->cmd, cmd->len); | 81 | struct w1_netlink_cmd *cmd = (struct w1_netlink_cmd *)(hdr + 1); |
82 | int search_type = (cmd->cmd == W1_CMD_ALARM_SEARCH)?W1_ALARM_SEARCH:W1_SEARCH; | ||
55 | 83 | ||
56 | if (cmd->cmd != W1_CMD_SEARCH && cmd->cmd != W1_CMD_ALARM_SEARCH) | 84 | dev->priv = msg; |
57 | return -EINVAL; | 85 | dev->priv_size = avail; |
86 | |||
87 | w1_search_devices(dev, search_type, w1_send_slave); | ||
88 | |||
89 | msg->ack = 0; | ||
90 | cn_netlink_send(msg, 0, GFP_KERNEL); | ||
91 | |||
92 | dev->priv = NULL; | ||
93 | dev->priv_size = 0; | ||
58 | 94 | ||
59 | w1_search_process(dev, (cmd->cmd == W1_CMD_ALARM_SEARCH)?W1_ALARM_SEARCH:W1_SEARCH); | ||
60 | return 0; | 95 | return 0; |
61 | } | 96 | } |
62 | 97 | ||
98 | static int w1_process_command_master(struct w1_master *dev, struct cn_msg *req_msg, | ||
99 | struct w1_netlink_msg *req_hdr, struct w1_netlink_cmd *req_cmd) | ||
100 | { | ||
101 | int err = -EINVAL; | ||
102 | struct cn_msg *msg; | ||
103 | struct w1_netlink_msg *hdr; | ||
104 | struct w1_netlink_cmd *cmd; | ||
105 | |||
106 | msg = kzalloc(PAGE_SIZE, GFP_KERNEL); | ||
107 | if (!msg) | ||
108 | return -ENOMEM; | ||
109 | |||
110 | msg->id = req_msg->id; | ||
111 | msg->seq = req_msg->seq; | ||
112 | msg->ack = 0; | ||
113 | msg->len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd); | ||
114 | |||
115 | hdr = (struct w1_netlink_msg *)(msg + 1); | ||
116 | cmd = (struct w1_netlink_cmd *)(hdr + 1); | ||
117 | |||
118 | hdr->type = W1_MASTER_CMD; | ||
119 | hdr->id = req_hdr->id; | ||
120 | hdr->len = sizeof(struct w1_netlink_cmd); | ||
121 | |||
122 | cmd->cmd = req_cmd->cmd; | ||
123 | cmd->len = 0; | ||
124 | |||
125 | switch (cmd->cmd) { | ||
126 | case W1_CMD_SEARCH: | ||
127 | case W1_CMD_ALARM_SEARCH: | ||
128 | err = w1_process_search_command(dev, msg, | ||
129 | PAGE_SIZE - msg->len - sizeof(struct cn_msg)); | ||
130 | break; | ||
131 | default: | ||
132 | cmd->res = EINVAL; | ||
133 | cn_netlink_send(msg, 0, GFP_KERNEL); | ||
134 | break; | ||
135 | } | ||
136 | |||
137 | kfree(msg); | ||
138 | return err; | ||
139 | } | ||
140 | |||
63 | static int w1_send_read_reply(struct w1_slave *sl, struct cn_msg *msg, | 141 | static int w1_send_read_reply(struct w1_slave *sl, struct cn_msg *msg, |
64 | struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd) | 142 | struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd) |
65 | { | 143 | { |
@@ -119,11 +197,6 @@ static int w1_process_command_slave(struct w1_slave *sl, struct cn_msg *msg, | |||
119 | case W1_CMD_WRITE: | 197 | case W1_CMD_WRITE: |
120 | w1_write_block(sl->master, cmd->data, cmd->len); | 198 | w1_write_block(sl->master, cmd->data, cmd->len); |
121 | break; | 199 | break; |
122 | case W1_CMD_SEARCH: | ||
123 | case W1_CMD_ALARM_SEARCH: | ||
124 | w1_search_process(sl->master, | ||
125 | (cmd->cmd == W1_CMD_ALARM_SEARCH)?W1_ALARM_SEARCH:W1_SEARCH); | ||
126 | break; | ||
127 | default: | 200 | default: |
128 | err = -1; | 201 | err = -1; |
129 | break; | 202 | break; |
@@ -270,11 +343,6 @@ out_cont: | |||
270 | if (err == -ENODEV) | 343 | if (err == -ENODEV) |
271 | err = 0; | 344 | err = 0; |
272 | } | 345 | } |
273 | #if 0 | ||
274 | if (err) { | ||
275 | printk("%s: malformed message. Dropping.\n", __func__); | ||
276 | } | ||
277 | #endif | ||
278 | } | 346 | } |
279 | 347 | ||
280 | int w1_init_netlink(void) | 348 | int w1_init_netlink(void) |