aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeniy Polyakov <johnpol@2ka.mipt.ru>2006-03-23 11:11:58 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-06-22 14:22:50 -0400
commit12003375acd879e498c6c511faf27531296f9640 (patch)
treef69001169d28c6e56e1a12e04420683620e31d79
parent81f6075ebcf3b0800321b7d81e4845d6ad9566d8 (diff)
[PATCH] w1: Userspace communication protocol over connector.
There are three types of messages between w1 core and userspace: 1. Events. They are generated each time new master or slave device found either due to automatic or requested search. 2. Userspace commands. Includes read/write and search/alarm search comamnds. 3. Replies to userspace commands. From: Evgeniy Polyakov <johnpol@2ka.mipt.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--Documentation/w1/w1.netlink98
-rw-r--r--drivers/w1/Makefile2
-rw-r--r--drivers/w1/slaves/w1_ds2433.c1
-rw-r--r--drivers/w1/slaves/w1_smem.c1
-rw-r--r--drivers/w1/slaves/w1_therm.c1
-rw-r--r--drivers/w1/w1.c137
-rw-r--r--drivers/w1/w1.h38
-rw-r--r--drivers/w1/w1_family.h1
-rw-r--r--drivers/w1/w1_int.c27
-rw-r--r--drivers/w1/w1_io.c18
-rw-r--r--drivers/w1/w1_netlink.c215
-rw-r--r--drivers/w1/w1_netlink.h38
12 files changed, 445 insertions, 132 deletions
diff --git a/Documentation/w1/w1.netlink b/Documentation/w1/w1.netlink
new file mode 100644
index 000000000000..3640c7c87d45
--- /dev/null
+++ b/Documentation/w1/w1.netlink
@@ -0,0 +1,98 @@
1Userspace communication protocol over connector [1].
2
3
4Message types.
5=============
6
7There are three types of messages between w1 core and userspace:
81. Events. They are generated each time new master or slave device found
9 either due to automatic or requested search.
102. Userspace commands. Includes read/write and search/alarm search comamnds.
113. Replies to userspace commands.
12
13
14Protocol.
15========
16
17[struct cn_msg] - connector header. It's length field is equal to size of the attached data.
18[struct w1_netlink_msg] - w1 netlink header.
19 __u8 type - message type.
20 W1_SLAVE_ADD/W1_SLAVE_REMOVE - slave add/remove events.
21 W1_MASTER_ADD/W1_MASTER_REMOVE - master add/remove events.
22 W1_MASTER_CMD - userspace command for bus master device (search/alarm search).
23 W1_SLAVE_CMD - userspace command for slave device (read/write/ search/alarm search
24 for bus master device where given slave device found).
25 __u8 res - reserved
26 __u16 len - size of attached to this header data.
27 union {
28 __u8 id; - slave unique device id
29 struct w1_mst {
30 __u32 id; - master's id.
31 __u32 res; - reserved
32 } mst;
33 } id;
34
35[strucrt w1_netlink_cmd] - command for gived master or slave device.
36 __u8 cmd - command opcode.
37 W1_CMD_READ - read command.
38 W1_CMD_WRITE - write command.
39 W1_CMD_SEARCH - search command.
40 W1_CMD_ALARM_SEARCH - alarm search command.
41 __u8 res - reserved
42 __u16 len - length of data for this command.
43 For read command data must be allocated like for write command.
44 __u8 data[0] - data for this command.
45
46
47Each connector message can include one or more w1_netlink_msg with zero of more attached w1_netlink_cmd messages.
48
49For event messages there are no w1_netlink_cmd embedded structures, only connector header
50and w1_netlink_msg strucutre with "len" field being zero and filled type (one of event types)
51and id - either 8 bytes of slave unique id in host order, or master's id, which is assigned
52to bus master device when it is added to w1 core.
53
54Currently replies to userspace commands are only generated for read command request.
55One reply is generated exactly for one w1_netlink_cmd read request.
56Replies are not combined when sent - i.e. typical reply messages looks like the following:
57[cn_msg][w1_netlink_msg][w1_netlink_cmd]
58cn_msg.len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd) + cmd->len;
59w1_netlink_msg.len = sizeof(struct w1_netlink_cmd) + cmd->len;
60w1_netlink_cmd.len = cmd->len;
61
62
63Operation steps in w1 core when new command is received.
64=======================================================
65
66When new message (w1_netlink_msg) is received w1 core detects if it is master of slave request,
67according to w1_netlink_msg.type field.
68Then master or slave device is searched for.
69When found, master device (requested or those one on where slave device is found) is locked.
70If slave command is requested, then reset/select procedure is started to select given device.
71
72Then all requested in w1_netlink_msg operations are performed one by one.
73If command requires reply (like read command) it is sent on command completion.
74
75When all commands (w1_netlink_cmd) are processed muster device is unlocked
76and next w1_netlink_msg header processing started.
77
78
79Connector [1] specific documentation.
80====================================
81
82Each connector message includes two u32 fields as "address".
83w1 uses CN_W1_IDX and CN_W1_VAL defined in include/linux/connector.h header.
84Each message also includes sequence and acknowledge numbers.
85Sequence number for event messages is appropriate bus master sequence number increased with
86each event message sent "through" this master.
87Sequence number for userspace requests is set by userspace application.
88Sequence number for reply is the same as was in request, and
89acknowledge number is set to seq+1.
90
91
92Additional documantion, source code examples.
93============================================
94
951. Documentation/connector
962. http://tservice.net.ru/~s0mbre/archive/w1
97This archive includes userspace application w1d.c which
98uses read/write/search commands for all master/slave devices found on the bus.
diff --git a/drivers/w1/Makefile b/drivers/w1/Makefile
index 0c2aa22d8c04..f0465c20a675 100644
--- a/drivers/w1/Makefile
+++ b/drivers/w1/Makefile
@@ -2,7 +2,7 @@
2# Makefile for the Dallas's 1-wire bus. 2# Makefile for the Dallas's 1-wire bus.
3# 3#
4 4
5ifneq ($(CONFIG_NET), y) 5ifeq ($(CONFIG_CONNECTOR), n)
6EXTRA_CFLAGS += -DNETLINK_DISABLED 6EXTRA_CFLAGS += -DNETLINK_DISABLED
7endif 7endif
8 8
diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c
index fb118be789ea..ddd01e6fc2c9 100644
--- a/drivers/w1/slaves/w1_ds2433.c
+++ b/drivers/w1/slaves/w1_ds2433.c
@@ -22,7 +22,6 @@
22#endif 22#endif
23 23
24#include "../w1.h" 24#include "../w1.h"
25#include "../w1_io.h"
26#include "../w1_int.h" 25#include "../w1_int.h"
27#include "../w1_family.h" 26#include "../w1_family.h"
28 27
diff --git a/drivers/w1/slaves/w1_smem.c b/drivers/w1/slaves/w1_smem.c
index c6d3be54f94c..cc8c02e92593 100644
--- a/drivers/w1/slaves/w1_smem.c
+++ b/drivers/w1/slaves/w1_smem.c
@@ -28,7 +28,6 @@
28#include <linux/types.h> 28#include <linux/types.h>
29 29
30#include "../w1.h" 30#include "../w1.h"
31#include "../w1_io.h"
32#include "../w1_int.h" 31#include "../w1_int.h"
33#include "../w1_family.h" 32#include "../w1_family.h"
34 33
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index 536d16d78de7..44afdffe3c8b 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -29,7 +29,6 @@
29#include <linux/delay.h> 29#include <linux/delay.h>
30 30
31#include "../w1.h" 31#include "../w1.h"
32#include "../w1_io.h"
33#include "../w1_int.h" 32#include "../w1_int.h"
34#include "../w1_family.h" 33#include "../w1_family.h"
35 34
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index c9486c168505..32d8de881f11 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -35,7 +35,6 @@
35#include <asm/atomic.h> 35#include <asm/atomic.h>
36 36
37#include "w1.h" 37#include "w1.h"
38#include "w1_io.h"
39#include "w1_log.h" 38#include "w1_log.h"
40#include "w1_int.h" 39#include "w1_int.h"
41#include "w1_family.h" 40#include "w1_family.h"
@@ -55,7 +54,7 @@ module_param_named(control_timeout, w1_control_timeout, int, 0);
55module_param_named(max_slave_count, w1_max_slave_count, int, 0); 54module_param_named(max_slave_count, w1_max_slave_count, int, 0);
56module_param_named(slave_ttl, w1_max_slave_ttl, int, 0); 55module_param_named(slave_ttl, w1_max_slave_ttl, int, 0);
57 56
58DEFINE_SPINLOCK(w1_mlock); 57DECLARE_MUTEX(w1_mlock);
59LIST_HEAD(w1_masters); 58LIST_HEAD(w1_masters);
60 59
61static struct task_struct *w1_control_thread; 60static struct task_struct *w1_control_thread;
@@ -75,8 +74,6 @@ static void w1_master_release(struct device *dev)
75 struct w1_master *md = dev_to_w1_master(dev); 74 struct w1_master *md = dev_to_w1_master(dev);
76 75
77 dev_dbg(dev, "%s: Releasing %s.\n", __func__, md->name); 76 dev_dbg(dev, "%s: Releasing %s.\n", __func__, md->name);
78
79 dev_fini_netlink(md);
80 memset(md, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master)); 77 memset(md, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master));
81 kfree(md); 78 kfree(md);
82} 79}
@@ -85,10 +82,10 @@ static void w1_slave_release(struct device *dev)
85{ 82{
86 struct w1_slave *sl = dev_to_w1_slave(dev); 83 struct w1_slave *sl = dev_to_w1_slave(dev);
87 84
88 dev_dbg(dev, "%s: Releasing %s.\n", __func__, sl->name); 85 printk("%s: Releasing %s.\n", __func__, sl->name);
89 86
90 while (atomic_read(&sl->refcnt)) { 87 while (atomic_read(&sl->refcnt)) {
91 dev_dbg(dev, "Waiting for %s to become free: refcnt=%d.\n", 88 printk("Waiting for %s to become free: refcnt=%d.\n",
92 sl->name, atomic_read(&sl->refcnt)); 89 sl->name, atomic_read(&sl->refcnt));
93 if (msleep_interruptible(1000)) 90 if (msleep_interruptible(1000))
94 flush_signals(current); 91 flush_signals(current);
@@ -111,7 +108,6 @@ static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, siz
111{ 108{
112 struct w1_slave *sl = kobj_to_w1_slave(kobj); 109 struct w1_slave *sl = kobj_to_w1_slave(kobj);
113 110
114 atomic_inc(&sl->refcnt);
115 if (off > 8) { 111 if (off > 8) {
116 count = 0; 112 count = 0;
117 } else { 113 } else {
@@ -120,7 +116,6 @@ static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, siz
120 116
121 memcpy(buf, (u8 *)&sl->reg_num, count); 117 memcpy(buf, (u8 *)&sl->reg_num, count);
122 } 118 }
123 atomic_dec(&sl->refcnt);
124 119
125 return count; 120 return count;
126} 121}
@@ -230,12 +225,11 @@ struct device w1_master_device = {
230 .release = &w1_master_release 225 .release = &w1_master_release
231}; 226};
232 227
233static struct device_driver w1_slave_driver = { 228struct device_driver w1_slave_driver = {
234 .name = "w1_slave_driver", 229 .name = "w1_slave_driver",
235 .bus = &w1_bus_type, 230 .bus = &w1_bus_type,
236}; 231};
237 232
238#if 0
239struct device w1_slave_device = { 233struct device w1_slave_device = {
240 .parent = NULL, 234 .parent = NULL,
241 .bus = &w1_bus_type, 235 .bus = &w1_bus_type,
@@ -243,7 +237,6 @@ struct device w1_slave_device = {
243 .driver = &w1_slave_driver, 237 .driver = &w1_slave_driver,
244 .release = &w1_slave_release 238 .release = &w1_slave_release
245}; 239};
246#endif /* 0 */
247 240
248static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf) 241static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf)
249{ 242{
@@ -423,7 +416,7 @@ int w1_create_master_attributes(struct w1_master *master)
423 return sysfs_create_group(&master->dev.kobj, &w1_master_defattr_group); 416 return sysfs_create_group(&master->dev.kobj, &w1_master_defattr_group);
424} 417}
425 418
426static void w1_destroy_master_attributes(struct w1_master *master) 419void w1_destroy_master_attributes(struct w1_master *master)
427{ 420{
428 sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group); 421 sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group);
429} 422}
@@ -454,14 +447,11 @@ static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer
454 if (dev->driver != &w1_slave_driver || !sl) 447 if (dev->driver != &w1_slave_driver || !sl)
455 return 0; 448 return 0;
456 449
457 err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, 450 err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_FID=%02X", sl->reg_num.family);
458 &cur_len, "W1_FID=%02X", sl->reg_num.family);
459 if (err) 451 if (err)
460 return err; 452 return err;
461 453
462 err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, 454 err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_SLAVE_ID=%024LX", (u64)sl->reg_num.id);
463 &cur_len, "W1_SLAVE_ID=%024LX",
464 (unsigned long long)sl->reg_num.id);
465 if (err) 455 if (err)
466 return err; 456 return err;
467 457
@@ -563,6 +553,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
563 sl->master = dev; 553 sl->master = dev;
564 set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags); 554 set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
565 555
556 memset(&msg, 0, sizeof(msg));
566 memcpy(&sl->reg_num, rn, sizeof(sl->reg_num)); 557 memcpy(&sl->reg_num, rn, sizeof(sl->reg_num));
567 atomic_set(&sl->refcnt, 0); 558 atomic_set(&sl->refcnt, 0);
568 init_completion(&sl->released); 559 init_completion(&sl->released);
@@ -593,7 +584,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
593 sl->ttl = dev->slave_ttl; 584 sl->ttl = dev->slave_ttl;
594 dev->slave_count++; 585 dev->slave_count++;
595 586
596 memcpy(&msg.id.id, rn, sizeof(msg.id.id)); 587 memcpy(msg.id.id, rn, sizeof(msg.id));
597 msg.type = W1_SLAVE_ADD; 588 msg.type = W1_SLAVE_ADD;
598 w1_netlink_send(dev, &msg); 589 w1_netlink_send(dev, &msg);
599 590
@@ -611,7 +602,8 @@ static void w1_slave_detach(struct w1_slave *sl)
611 if (sl->family->fops && sl->family->fops->remove_slave) 602 if (sl->family->fops && sl->family->fops->remove_slave)
612 sl->family->fops->remove_slave(sl); 603 sl->family->fops->remove_slave(sl);
613 604
614 memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id)); 605 memset(&msg, 0, sizeof(msg));
606 memcpy(msg.id.id, &sl->reg_num, sizeof(msg.id));
615 msg.type = W1_SLAVE_REMOVE; 607 msg.type = W1_SLAVE_REMOVE;
616 w1_netlink_send(sl->master, &msg); 608 w1_netlink_send(sl->master, &msg);
617 609
@@ -628,7 +620,7 @@ static struct w1_master *w1_search_master(void *data)
628 struct w1_master *dev; 620 struct w1_master *dev;
629 int found = 0; 621 int found = 0;
630 622
631 spin_lock_bh(&w1_mlock); 623 down(&w1_mlock);
632 list_for_each_entry(dev, &w1_masters, w1_master_entry) { 624 list_for_each_entry(dev, &w1_masters, w1_master_entry) {
633 if (dev->bus_master->data == data) { 625 if (dev->bus_master->data == data) {
634 found = 1; 626 found = 1;
@@ -636,22 +628,69 @@ static struct w1_master *w1_search_master(void *data)
636 break; 628 break;
637 } 629 }
638 } 630 }
639 spin_unlock_bh(&w1_mlock); 631 up(&w1_mlock);
640 632
641 return (found)?dev:NULL; 633 return (found)?dev:NULL;
642} 634}
643 635
636struct w1_master *w1_search_master_id(u32 id)
637{
638 struct w1_master *dev;
639 int found = 0;
640
641 down(&w1_mlock);
642 list_for_each_entry(dev, &w1_masters, w1_master_entry) {
643 if (dev->id == id) {
644 found = 1;
645 atomic_inc(&dev->refcnt);
646 break;
647 }
648 }
649 up(&w1_mlock);
650
651 return (found)?dev:NULL;
652}
653
654struct w1_slave *w1_search_slave(struct w1_reg_num *id)
655{
656 struct w1_master *dev;
657 struct w1_slave *sl = NULL;
658 int found = 0;
659
660 down(&w1_mlock);
661 list_for_each_entry(dev, &w1_masters, w1_master_entry) {
662 down(&dev->mutex);
663 list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
664 if (sl->reg_num.family == id->family &&
665 sl->reg_num.id == id->id &&
666 sl->reg_num.crc == id->crc) {
667 found = 1;
668 atomic_inc(&dev->refcnt);
669 atomic_inc(&sl->refcnt);
670 break;
671 }
672 }
673 up(&dev->mutex);
674
675 if (found)
676 break;
677 }
678 up(&w1_mlock);
679
680 return (found)?sl:NULL;
681}
682
644void w1_reconnect_slaves(struct w1_family *f) 683void w1_reconnect_slaves(struct w1_family *f)
645{ 684{
646 struct w1_master *dev; 685 struct w1_master *dev;
647 686
648 spin_lock_bh(&w1_mlock); 687 down(&w1_mlock);
649 list_for_each_entry(dev, &w1_masters, w1_master_entry) { 688 list_for_each_entry(dev, &w1_masters, w1_master_entry) {
650 dev_dbg(&dev->dev, "Reconnecting slaves in %s into new family %02x.\n", 689 dev_dbg(&dev->dev, "Reconnecting slaves in %s into new family %02x.\n",
651 dev->name, f->fid); 690 dev->name, f->fid);
652 set_bit(W1_MASTER_NEED_RECONNECT, &dev->flags); 691 set_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
653 } 692 }
654 spin_unlock_bh(&w1_mlock); 693 up(&w1_mlock);
655} 694}
656 695
657static void w1_slave_found(void *data, u64 rn) 696static void w1_slave_found(void *data, u64 rn)
@@ -713,7 +752,7 @@ static void w1_slave_found(void *data, u64 rn)
713 * @dev The master device to search 752 * @dev The master device to search
714 * @cb Function to call when a device is found 753 * @cb Function to call when a device is found
715 */ 754 */
716void w1_search(struct w1_master *dev, w1_slave_found_callback cb) 755void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb)
717{ 756{
718 u64 last_rn, rn, tmp64; 757 u64 last_rn, rn, tmp64;
719 int i, slave_count = 0; 758 int i, slave_count = 0;
@@ -744,7 +783,7 @@ void w1_search(struct w1_master *dev, w1_slave_found_callback cb)
744 } 783 }
745 784
746 /* Start the search */ 785 /* Start the search */
747 w1_write_8(dev, W1_SEARCH); 786 w1_write_8(dev, search_type);
748 for (i = 0; i < 64; ++i) { 787 for (i = 0; i < 64; ++i) {
749 /* Determine the direction/search bit */ 788 /* Determine the direction/search bit */
750 if (i == desc_bit) 789 if (i == desc_bit)
@@ -806,9 +845,9 @@ static int w1_control(void *data)
806 if (kthread_should_stop() || test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) { 845 if (kthread_should_stop() || test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
807 set_bit(W1_MASTER_NEED_EXIT, &dev->flags); 846 set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
808 847
809 spin_lock(&w1_mlock); 848 down(&w1_mlock);
810 list_del(&dev->w1_master_entry); 849 list_del(&dev->w1_master_entry);
811 spin_unlock(&w1_mlock); 850 up(&w1_mlock);
812 851
813 down(&dev->mutex); 852 down(&dev->mutex);
814 list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { 853 list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
@@ -843,10 +882,31 @@ static int w1_control(void *data)
843 return 0; 882 return 0;
844} 883}
845 884
885void w1_search_process(struct w1_master *dev, u8 search_type)
886{
887 struct w1_slave *sl, *sln;
888
889 list_for_each_entry(sl, &dev->slist, w1_slave_entry)
890 clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
891
892 w1_search_devices(dev, search_type, w1_slave_found);
893
894 list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
895 if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) {
896 w1_slave_detach(sl);
897
898 dev->slave_count--;
899 } else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags))
900 sl->ttl = dev->slave_ttl;
901 }
902
903 if (dev->search_count > 0)
904 dev->search_count--;
905}
906
846int w1_process(void *data) 907int w1_process(void *data)
847{ 908{
848 struct w1_master *dev = (struct w1_master *) data; 909 struct w1_master *dev = (struct w1_master *) data;
849 struct w1_slave *sl, *sln;
850 910
851 while (!kthread_should_stop() && !test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) { 911 while (!kthread_should_stop() && !test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
852 try_to_freeze(); 912 try_to_freeze();
@@ -864,22 +924,7 @@ int w1_process(void *data)
864 if (down_interruptible(&dev->mutex)) 924 if (down_interruptible(&dev->mutex))
865 continue; 925 continue;
866 926
867 list_for_each_entry(sl, &dev->slist, w1_slave_entry) 927 w1_search_process(dev, W1_SEARCH);
868 clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
869
870 w1_search_devices(dev, w1_slave_found);
871
872 list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
873 if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) {
874 w1_slave_detach(sl);
875
876 dev->slave_count--;
877 } else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags))
878 sl->ttl = dev->slave_ttl;
879 }
880
881 if (dev->search_count > 0)
882 dev->search_count--;
883 928
884 up(&dev->mutex); 929 up(&dev->mutex);
885 } 930 }
@@ -895,6 +940,8 @@ static int w1_init(void)
895 940
896 printk(KERN_INFO "Driver for 1-wire Dallas network protocol.\n"); 941 printk(KERN_INFO "Driver for 1-wire Dallas network protocol.\n");
897 942
943 w1_init_netlink();
944
898 retval = bus_register(&w1_bus_type); 945 retval = bus_register(&w1_bus_type);
899 if (retval) { 946 if (retval) {
900 printk(KERN_ERR "Failed to register bus. err=%d.\n", retval); 947 printk(KERN_ERR "Failed to register bus. err=%d.\n", retval);
@@ -947,6 +994,8 @@ static void w1_fini(void)
947 list_for_each_entry(dev, &w1_masters, w1_master_entry) 994 list_for_each_entry(dev, &w1_masters, w1_master_entry)
948 __w1_remove_master_device(dev); 995 __w1_remove_master_device(dev);
949 996
997 w1_fini_netlink();
998
950 kthread_stop(w1_control_thread); 999 kthread_stop(w1_control_thread);
951 1000
952 driver_unregister(&w1_slave_driver); 1001 driver_unregister(&w1_slave_driver);
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h
index 02e8caddfb36..e8c96e6e7418 100644
--- a/drivers/w1/w1.h
+++ b/drivers/w1/w1.h
@@ -42,8 +42,6 @@ struct w1_reg_num
42#include <linux/completion.h> 42#include <linux/completion.h>
43#include <linux/device.h> 43#include <linux/device.h>
44 44
45#include <net/sock.h>
46
47#include <asm/semaphore.h> 45#include <asm/semaphore.h>
48 46
49#include "w1_family.h" 47#include "w1_family.h"
@@ -52,7 +50,7 @@ struct w1_reg_num
52#define W1_SLAVE_DATA_SIZE 128 50#define W1_SLAVE_DATA_SIZE 128
53 51
54#define W1_SEARCH 0xF0 52#define W1_SEARCH 0xF0
55#define W1_CONDITIONAL_SEARCH 0xEC 53#define W1_ALARM_SEARCH 0xEC
56#define W1_CONVERT_TEMP 0x44 54#define W1_CONVERT_TEMP 0x44
57#define W1_SKIP_ROM 0xCC 55#define W1_SKIP_ROM 0xCC
58#define W1_READ_SCRATCHPAD 0xBE 56#define W1_READ_SCRATCHPAD 0xBE
@@ -145,8 +143,8 @@ struct w1_bus_master
145 */ 143 */
146 u8 (*reset_bus)(void *); 144 u8 (*reset_bus)(void *);
147 145
148 /** Really nice hardware can handles the ROM searches */ 146 /** Really nice hardware can handles the different types of ROM search */
149 void (*search)(void *, w1_slave_found_callback); 147 void (*search)(void *, u8, w1_slave_found_callback);
150}; 148};
151 149
152#define W1_MASTER_NEED_EXIT 0 150#define W1_MASTER_NEED_EXIT 0
@@ -180,12 +178,26 @@ struct w1_master
180 178
181 struct w1_bus_master *bus_master; 179 struct w1_bus_master *bus_master;
182 180
183 u32 seq, groups; 181 u32 seq;
184 struct sock *nls;
185}; 182};
186 183
187int w1_create_master_attributes(struct w1_master *); 184int w1_create_master_attributes(struct w1_master *);
188void w1_search(struct w1_master *dev, w1_slave_found_callback cb); 185void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb);
186void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb);
187struct w1_slave *w1_search_slave(struct w1_reg_num *id);
188void w1_search_process(struct w1_master *dev, u8 search_type);
189struct w1_master *w1_search_master_id(u32 id);
190
191void w1_delay(unsigned long);
192u8 w1_touch_bit(struct w1_master *, int);
193u8 w1_triplet(struct w1_master *dev, int bdir);
194void w1_write_8(struct w1_master *, u8);
195u8 w1_read_8(struct w1_master *);
196int w1_reset_bus(struct w1_master *);
197u8 w1_calc_crc8(u8 *, int);
198void w1_write_block(struct w1_master *, const u8 *, int);
199u8 w1_read_block(struct w1_master *, u8 *, int);
200int w1_reset_select_slave(struct w1_slave *sl);
189 201
190static inline struct w1_slave* dev_to_w1_slave(struct device *dev) 202static inline struct w1_slave* dev_to_w1_slave(struct device *dev)
191{ 203{
@@ -202,16 +214,6 @@ static inline struct w1_master* dev_to_w1_master(struct device *dev)
202 return container_of(dev, struct w1_master, dev); 214 return container_of(dev, struct w1_master, dev);
203} 215}
204 216
205extern int w1_max_slave_count;
206extern int w1_max_slave_ttl;
207extern spinlock_t w1_mlock;
208extern struct list_head w1_masters;
209extern struct device_driver w1_master_driver;
210extern struct device w1_master_device;
211
212int w1_process(void *data);
213void w1_reconnect_slaves(struct w1_family *f);
214
215#endif /* __KERNEL__ */ 217#endif /* __KERNEL__ */
216 218
217#endif /* __W1_H */ 219#endif /* __W1_H */
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
index 2ca0489c716a..22a9d52c94f3 100644
--- a/drivers/w1/w1_family.h
+++ b/drivers/w1/w1_family.h
@@ -64,5 +64,6 @@ void __w1_family_put(struct w1_family *);
64struct w1_family * w1_family_registered(u8); 64struct w1_family * w1_family_registered(u8);
65void w1_unregister_family(struct w1_family *); 65void w1_unregister_family(struct w1_family *);
66int w1_register_family(struct w1_family *); 66int w1_register_family(struct w1_family *);
67void w1_reconnect_slaves(struct w1_family *f);
67 68
68#endif /* __W1_FAMILY_H */ 69#endif /* __W1_FAMILY_H */
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c
index 68565aacec7b..ae78473d11f9 100644
--- a/drivers/w1/w1_int.c
+++ b/drivers/w1/w1_int.c
@@ -27,10 +27,19 @@
27#include "w1.h" 27#include "w1.h"
28#include "w1_log.h" 28#include "w1_log.h"
29#include "w1_netlink.h" 29#include "w1_netlink.h"
30#include "w1_int.h"
31 30
32static u32 w1_ids = 1; 31static u32 w1_ids = 1;
33 32
33extern struct device_driver w1_master_driver;
34extern struct bus_type w1_bus_type;
35extern struct device w1_master_device;
36extern int w1_max_slave_count;
37extern int w1_max_slave_ttl;
38extern struct list_head w1_masters;
39extern struct semaphore w1_mlock;
40
41extern int w1_process(void *);
42
34static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, 43static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
35 struct device_driver *driver, 44 struct device_driver *driver,
36 struct device *device) 45 struct device *device)
@@ -74,16 +83,11 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
74 83
75 dev->driver = driver; 84 dev->driver = driver;
76 85
77 dev->groups = 1;
78 dev->seq = 1; 86 dev->seq = 1;
79 dev_init_netlink(dev);
80 87
81 err = device_register(&dev->dev); 88 err = device_register(&dev->dev);
82 if (err) { 89 if (err) {
83 printk(KERN_ERR "Failed to register master device. err=%d\n", err); 90 printk(KERN_ERR "Failed to register master device. err=%d\n", err);
84
85 dev_fini_netlink(dev);
86
87 memset(dev, 0, sizeof(struct w1_master)); 91 memset(dev, 0, sizeof(struct w1_master));
88 kfree(dev); 92 kfree(dev);
89 dev = NULL; 93 dev = NULL;
@@ -92,7 +96,7 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
92 return dev; 96 return dev;
93} 97}
94 98
95static void w1_free_dev(struct w1_master *dev) 99void w1_free_dev(struct w1_master *dev)
96{ 100{
97 device_unregister(&dev->dev); 101 device_unregister(&dev->dev);
98} 102}
@@ -131,12 +135,12 @@ int w1_add_master_device(struct w1_bus_master *master)
131 135
132 dev->initialized = 1; 136 dev->initialized = 1;
133 137
134 spin_lock(&w1_mlock); 138 down(&w1_mlock);
135 list_add(&dev->w1_master_entry, &w1_masters); 139 list_add(&dev->w1_master_entry, &w1_masters);
136 spin_unlock(&w1_mlock); 140 up(&w1_mlock);
137 141
142 memset(&msg, 0, sizeof(msg));
138 msg.id.mst.id = dev->id; 143 msg.id.mst.id = dev->id;
139 msg.id.mst.pid = dev->thread->pid;
140 msg.type = W1_MASTER_ADD; 144 msg.type = W1_MASTER_ADD;
141 w1_netlink_send(dev, &msg); 145 w1_netlink_send(dev, &msg);
142 146
@@ -153,7 +157,6 @@ err_out_free_dev:
153void __w1_remove_master_device(struct w1_master *dev) 157void __w1_remove_master_device(struct w1_master *dev)
154{ 158{
155 struct w1_netlink_msg msg; 159 struct w1_netlink_msg msg;
156 pid_t pid = dev->thread->pid;
157 160
158 set_bit(W1_MASTER_NEED_EXIT, &dev->flags); 161 set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
159 kthread_stop(dev->thread); 162 kthread_stop(dev->thread);
@@ -166,8 +169,8 @@ void __w1_remove_master_device(struct w1_master *dev)
166 flush_signals(current); 169 flush_signals(current);
167 } 170 }
168 171
172 memset(&msg, 0, sizeof(msg));
169 msg.id.mst.id = dev->id; 173 msg.id.mst.id = dev->id;
170 msg.id.mst.pid = pid;
171 msg.type = W1_MASTER_REMOVE; 174 msg.type = W1_MASTER_REMOVE;
172 w1_netlink_send(dev, &msg); 175 w1_netlink_send(dev, &msg);
173 176
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c
index f7f7e8bec30e..a6eb9db73591 100644
--- a/drivers/w1/w1_io.c
+++ b/drivers/w1/w1_io.c
@@ -26,7 +26,6 @@
26 26
27#include "w1.h" 27#include "w1.h"
28#include "w1_log.h" 28#include "w1_log.h"
29#include "w1_io.h"
30 29
31static int w1_delay_parm = 1; 30static int w1_delay_parm = 1;
32module_param_named(delay_coef, w1_delay_parm, int, 0); 31module_param_named(delay_coef, w1_delay_parm, int, 0);
@@ -268,13 +267,13 @@ u8 w1_calc_crc8(u8 * data, int len)
268 return crc; 267 return crc;
269} 268}
270 269
271void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb) 270void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb)
272{ 271{
273 dev->attempts++; 272 dev->attempts++;
274 if (dev->bus_master->search) 273 if (dev->bus_master->search)
275 dev->bus_master->search(dev->bus_master->data, cb); 274 dev->bus_master->search(dev->bus_master->data, search_type, cb);
276 else 275 else
277 w1_search(dev, cb); 276 w1_search(dev, search_type, cb);
278} 277}
279 278
280/** 279/**
@@ -300,13 +299,4 @@ int w1_reset_select_slave(struct w1_slave *sl)
300 return 0; 299 return 0;
301} 300}
302 301
303EXPORT_SYMBOL(w1_touch_bit); 302EXPORT_SYMBOL_GPL(w1_calc_crc8);
304EXPORT_SYMBOL(w1_write_8);
305EXPORT_SYMBOL(w1_read_8);
306EXPORT_SYMBOL(w1_reset_bus);
307EXPORT_SYMBOL(w1_calc_crc8);
308EXPORT_SYMBOL(w1_delay);
309EXPORT_SYMBOL(w1_read_block);
310EXPORT_SYMBOL(w1_write_block);
311EXPORT_SYMBOL(w1_search_devices);
312EXPORT_SYMBOL(w1_reset_select_slave);
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c
index 328645da7972..d48f3acdb8a2 100644
--- a/drivers/w1/w1_netlink.c
+++ b/drivers/w1/w1_netlink.c
@@ -21,6 +21,7 @@
21 21
22#include <linux/skbuff.h> 22#include <linux/skbuff.h>
23#include <linux/netlink.h> 23#include <linux/netlink.h>
24#include <linux/connector.h>
24 25
25#include "w1.h" 26#include "w1.h"
26#include "w1_log.h" 27#include "w1_log.h"
@@ -29,50 +30,204 @@
29#ifndef NETLINK_DISABLED 30#ifndef NETLINK_DISABLED
30void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg) 31void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
31{ 32{
32 unsigned int size; 33 char buf[sizeof(struct cn_msg) + sizeof(struct w1_netlink_msg)];
33 struct sk_buff *skb; 34 struct cn_msg *m = (struct cn_msg *)buf;
34 struct w1_netlink_msg *data; 35 struct w1_netlink_msg *w = (struct w1_netlink_msg *)(m+1);
35 struct nlmsghdr *nlh;
36 36
37 if (!dev->nls) 37 memset(buf, 0, sizeof(buf));
38 return;
39 38
40 size = NLMSG_SPACE(sizeof(struct w1_netlink_msg)); 39 m->id.idx = CN_W1_IDX;
40 m->id.val = CN_W1_VAL;
41 41
42 skb = alloc_skb(size, GFP_ATOMIC); 42 m->seq = dev->seq++;
43 if (!skb) { 43 m->len = sizeof(struct w1_netlink_msg);
44 dev_err(&dev->dev, "skb_alloc() failed.\n");
45 return;
46 }
47 44
48 nlh = NLMSG_PUT(skb, 0, dev->seq++, NLMSG_DONE, size - sizeof(*nlh)); 45 memcpy(w, msg, sizeof(struct w1_netlink_msg));
49 46
50 data = (struct w1_netlink_msg *)NLMSG_DATA(nlh); 47 cn_netlink_send(m, 0, GFP_KERNEL);
48}
51 49
52 memcpy(data, msg, sizeof(struct w1_netlink_msg)); 50static int w1_process_command_master(struct w1_master *dev, struct cn_msg *msg,
51 struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd)
52{
53 dev_dbg(&dev->dev, "%s: %s: cmd=%02x, len=%u.\n",
54 __func__, dev->name, cmd->cmd, cmd->len);
53 55
54 NETLINK_CB(skb).dst_group = dev->groups; 56 if (cmd->cmd != W1_CMD_SEARCH && cmd->cmd != W1_CMD_ALARM_SEARCH)
55 netlink_broadcast(dev->nls, skb, 0, dev->groups, GFP_ATOMIC); 57 return -EINVAL;
56 58
57nlmsg_failure: 59 w1_search_process(dev, (cmd->cmd == W1_CMD_ALARM_SEARCH)?W1_ALARM_SEARCH:W1_SEARCH);
58 return; 60 return 0;
59} 61}
60 62
61int dev_init_netlink(struct w1_master *dev) 63static int w1_send_read_reply(struct w1_slave *sl, struct cn_msg *msg,
64 struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd)
62{ 65{
63 dev->nls = netlink_kernel_create(NETLINK_W1, 1, NULL, THIS_MODULE); 66 void *data;
64 if (!dev->nls) { 67 struct w1_netlink_msg *h;
65 printk(KERN_ERR "Failed to create new netlink socket(%u) for w1 master %s.\n", 68 struct w1_netlink_cmd *c;
66 NETLINK_W1, dev->dev.bus_id); 69 struct cn_msg *cm;
70 int err;
71
72 data = kzalloc(sizeof(struct cn_msg) +
73 sizeof(struct w1_netlink_msg) +
74 sizeof(struct w1_netlink_cmd) +
75 cmd->len, GFP_KERNEL);
76 if (!data)
77 return -ENOMEM;
78
79 cm = (struct cn_msg *)(data);
80 h = (struct w1_netlink_msg *)(cm + 1);
81 c = (struct w1_netlink_cmd *)(h + 1);
82
83 memcpy(cm, msg, sizeof(struct cn_msg));
84 memcpy(h, hdr, sizeof(struct w1_netlink_msg));
85 memcpy(c, cmd, sizeof(struct w1_netlink_cmd));
86
87 cm->ack = msg->seq+1;
88 cm->len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd) + cmd->len;
89
90 h->len = sizeof(struct w1_netlink_cmd) + cmd->len;
91
92 memcpy(c->data, cmd->data, c->len);
93
94 err = cn_netlink_send(cm, 0, GFP_KERNEL);
95
96 kfree(data);
97
98 return err;
99}
100
101static int w1_process_command_slave(struct w1_slave *sl, struct cn_msg *msg,
102 struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd)
103{
104 int err = 0;
105
106 dev_dbg(&sl->master->dev, "%s: %02x.%012llx.%02x: cmd=%02x, len=%u.\n",
107 __func__, sl->reg_num.family, (unsigned long long)sl->reg_num.id, sl->reg_num.crc,
108 cmd->cmd, cmd->len);
109
110 switch (cmd->cmd) {
111 case W1_CMD_READ:
112 w1_read_block(sl->master, cmd->data, cmd->len);
113 w1_send_read_reply(sl, msg, hdr, cmd);
114 break;
115 case W1_CMD_WRITE:
116 w1_write_block(sl->master, cmd->data, cmd->len);
117 break;
118 case W1_CMD_SEARCH:
119 case W1_CMD_ALARM_SEARCH:
120 w1_search_process(sl->master,
121 (cmd->cmd == W1_CMD_ALARM_SEARCH)?W1_ALARM_SEARCH:W1_SEARCH);
122 break;
123 default:
124 err = -1;
125 break;
67 } 126 }
68 127
69 return 0; 128 return err;
129}
130
131static void w1_cn_callback(void *data)
132{
133 struct cn_msg *msg = data;
134 struct w1_netlink_msg *m = (struct w1_netlink_msg *)(msg + 1);
135 struct w1_netlink_cmd *cmd;
136 struct w1_slave *sl;
137 struct w1_master *dev;
138 int err = 0;
139
140 while (msg->len && !err) {
141 struct w1_reg_num id;
142 u16 mlen = m->len;
143 u8 *cmd_data = m->data;
144
145 dev = NULL;
146 sl = NULL;
147
148 memcpy(&id, m->id.id, sizeof(id));
149#if 0
150 printk("%s: %02x.%012llx.%02x: type=%02x, len=%u.\n",
151 __func__, id.family, (unsigned long long)id.id, id.crc, m->type, m->len);
152#endif
153 if (m->len + sizeof(struct w1_netlink_msg) > msg->len) {
154 err = -E2BIG;
155 break;
156 }
157
158 if (!mlen)
159 goto out_cont;
160
161 if (m->type == W1_MASTER_CMD) {
162 dev = w1_search_master_id(m->id.mst.id);
163 } else if (m->type == W1_SLAVE_CMD) {
164 sl = w1_search_slave(&id);
165 if (sl)
166 dev = sl->master;
167 }
168
169 if (!dev) {
170 err = -ENODEV;
171 goto out_cont;
172 }
173
174 down(&dev->mutex);
175
176 if (sl && w1_reset_select_slave(sl)) {
177 err = -ENODEV;
178 goto out_up;
179 }
180
181 while (mlen) {
182 cmd = (struct w1_netlink_cmd *)cmd_data;
183
184 if (cmd->len + sizeof(struct w1_netlink_cmd) > mlen) {
185 err = -E2BIG;
186 break;
187 }
188
189 if (sl)
190 w1_process_command_slave(sl, msg, m, cmd);
191 else
192 w1_process_command_master(dev, msg, m, cmd);
193
194 cmd_data += cmd->len + sizeof(struct w1_netlink_cmd);
195 mlen -= cmd->len + sizeof(struct w1_netlink_cmd);
196 }
197out_up:
198 atomic_dec(&dev->refcnt);
199 if (sl)
200 atomic_dec(&sl->refcnt);
201 up(&dev->mutex);
202out_cont:
203 msg->len -= sizeof(struct w1_netlink_msg) + m->len;
204 m = (struct w1_netlink_msg *)(((u8 *)m) + sizeof(struct w1_netlink_msg) + m->len);
205
206 /*
207 * Let's allow requests for nonexisting devices.
208 */
209 if (err == -ENODEV)
210 err = 0;
211 }
212#if 0
213 if (err) {
214 printk("%s: malformed message. Dropping.\n", __func__);
215 }
216#endif
70} 217}
71 218
72void dev_fini_netlink(struct w1_master *dev) 219int w1_init_netlink(void)
73{ 220{
74 if (dev->nls && dev->nls->sk_socket) 221 struct cb_id w1_id = {.idx = CN_W1_IDX, .val = CN_W1_VAL};
75 sock_release(dev->nls->sk_socket); 222
223 return cn_add_callback(&w1_id, "w1", &w1_cn_callback);
224}
225
226void w1_fini_netlink(void)
227{
228 struct cb_id w1_id = {.idx = CN_W1_IDX, .val = CN_W1_VAL};
229
230 cn_del_callback(&w1_id);
76} 231}
77#else 232#else
78#warning Netlink support is disabled. Please compile with NET support enabled. 233#warning Netlink support is disabled. Please compile with NET support enabled.
@@ -81,12 +236,12 @@ void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
81{ 236{
82} 237}
83 238
84int dev_init_netlink(struct w1_master *dev) 239int w1_init_netlink(void)
85{ 240{
86 return 0; 241 return 0;
87} 242}
88 243
89void dev_fini_netlink(struct w1_master *dev) 244void w1_fini_netlink(void)
90{ 245{
91} 246}
92#endif 247#endif
diff --git a/drivers/w1/w1_netlink.h b/drivers/w1/w1_netlink.h
index eb0c8b3152c8..5644221f9a44 100644
--- a/drivers/w1/w1_netlink.h
+++ b/drivers/w1/w1_netlink.h
@@ -23,37 +23,55 @@
23#define __W1_NETLINK_H 23#define __W1_NETLINK_H
24 24
25#include <asm/types.h> 25#include <asm/types.h>
26#include <linux/connector.h>
26 27
27#include "w1.h" 28#include "w1.h"
28 29
30#define CN_W1_IDX 3
31#define CN_W1_VAL 1
32
29enum w1_netlink_message_types { 33enum w1_netlink_message_types {
30 W1_SLAVE_ADD = 0, 34 W1_SLAVE_ADD = 0,
31 W1_SLAVE_REMOVE, 35 W1_SLAVE_REMOVE,
32 W1_MASTER_ADD, 36 W1_MASTER_ADD,
33 W1_MASTER_REMOVE, 37 W1_MASTER_REMOVE,
38 W1_MASTER_CMD,
39 W1_SLAVE_CMD,
34}; 40};
35 41
36struct w1_netlink_msg 42struct w1_netlink_msg
37{ 43{
38 __u8 type; 44 __u8 type;
39 __u8 reserved[3]; 45 __u8 reserved;
40 union 46 __u16 len;
41 { 47 union {
42 struct w1_reg_num id; 48 __u8 id[8];
43 __u64 w1_id; 49 struct w1_mst {
44 struct
45 {
46 __u32 id; 50 __u32 id;
47 __u32 pid; 51 __u32 res;
48 } mst; 52 } mst;
49 } id; 53 } id;
54 __u8 data[0];
55};
56
57#define W1_CMD_READ 0x0
58#define W1_CMD_WRITE 0x1
59#define W1_CMD_SEARCH 0x2
60#define W1_CMD_ALARM_SEARCH 0x3
61
62struct w1_netlink_cmd
63{
64 __u8 cmd;
65 __u8 res;
66 __u16 len;
67 __u8 data[0];
50}; 68};
51 69
52#ifdef __KERNEL__ 70#ifdef __KERNEL__
53 71
54void w1_netlink_send(struct w1_master *, struct w1_netlink_msg *); 72void w1_netlink_send(struct w1_master *, struct w1_netlink_msg *);
55int dev_init_netlink(struct w1_master *dev); 73int w1_init_netlink(void);
56void dev_fini_netlink(struct w1_master *dev); 74void w1_fini_netlink(void);
57 75
58#endif /* __KERNEL__ */ 76#endif /* __KERNEL__ */
59#endif /* __W1_NETLINK_H */ 77#endif /* __W1_NETLINK_H */