diff options
Diffstat (limited to 'drivers/w1')
-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) |