502ce284261d29520ba9eff3e4d77ef30b5a372c
[bertos.git] / dt / dnotifier.c
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2005 Develer S.r.l. (http://www.develer.com/)
30  * -->
31  *
32  * \version $Id$
33  *
34  * \brief Notifier obj (implementation).
35  *
36  * \version $Id$
37  * \author Bernardo Innocenti <bernie@develer.com>
38  * \author Francesco Sacchi <batt@develer.com>
39  */
40
41 /*#*
42  *#* $Log$
43  *#* Revision 1.2  2006/07/19 12:56:26  bernie
44  *#* Convert to new Doxygen style.
45  *#*
46  *#* Revision 1.1  2005/11/04 18:26:38  bernie
47  *#* Import into DevLib.
48  *#*
49  *#* Revision 1.5  2005/06/09 13:49:22  batt
50  *#* Reformat; correct some comments.
51  *#*
52  *#* Revision 1.4  2005/06/09 13:23:58  batt
53  *#* Add some comments.
54  *#*
55  *#* Revision 1.3  2005/06/08 17:32:33  batt
56  *#* Switch to new messaging system.
57  *#*
58  *#* Revision 1.2  2005/06/06 11:04:12  batt
59  *#* Add some comments.
60  *#*
61  *#* Revision 1.1  2005/05/26 08:32:53  batt
62  *#* Add new Develer widget system :)
63  *#*
64  *#*/
65
66 #include <cfg/debug.h>
67
68 #include <dt/dtag.h>
69 #include <dt/dnotifier.h>
70 #include <mware/list.h>
71
72 /**
73  * Default update used to notify target: notify all trasparently all
74  * targets in the list.
75  */
76 static void notifier_update(DNotifier *n, dtag_t tag, dval_t val)
77 {
78         dnotify_targets(n, tag, val);
79 }
80
81 /**
82  * Init.
83  */
84 void notifier_init(DNotifier *n)
85 {
86         // Init instance
87         n->update = notifier_update;
88         LIST_INIT(&n->targets);
89 }
90
91 /**
92  * Search in the map a tag and a val corresponding to the ones supplied.
93  * If a match is found change them to the corresponding ones in the map.
94  * If map is NULL the filter is trasparent and all messages sent to filter
95  * will be forwarded to its target.
96  */
97 void filter_update(DFilter *f, dtag_t tag, dval_t val)
98 {
99
100         const DFilterMap *map = f->map;
101
102         if (map)
103         {
104                 while (map->src.tag != TAG_END)
105                 {
106                         if ((map->src.tag == tag) && (map->src.val == val))
107                         {
108                                 tag = map->dst.tag;
109                                 val = map->dst.val;
110                                 break;
111                         }
112                         /* TAG_ANY matches anything */
113                         if (map->src.tag == TAG_ANY)
114                                 break;
115                         map++;
116                 }
117
118                 if (map->src.tag != TAG_END)
119                         dnotify(f->target, tag, val);
120         }
121         else
122                 dnotify(f->target, tag, val);
123 }
124
125
126 /**
127  * Search in the table a tag corresponding to the one supplied and a val
128  * that has at least the mask map supplied bits to one.
129  * If a match is found change them to the corresponding ones in the map.
130  * If map is NULL the filter is trasparent and all messages sent to filter
131  * will be forwarded to its target.
132  */
133 void filter_mask_update(DFilter *f, dtag_t tag, dval_t val)
134 {
135
136         const DFilterMap *map = f->map;
137         dfilter_mask_t mask;
138
139         if (map)
140         {
141                 while (map->src.tag != TAG_END)
142                 {
143                         mask = (dfilter_mask_t) map->src.val;
144                         if ((map->src.tag == tag) && ((mask & (dfilter_mask_t)val) == mask))
145                         {
146                                 tag = map->dst.tag;
147                                 val = map->dst.val;
148                                 break;
149                         }
150                         /* TAG_ANY matches anything */
151                         if (map->src.tag == TAG_ANY)
152                                 break;
153                         map++;
154                 }
155
156
157                 if (map->src.tag != TAG_END)
158                         dnotify(f->target, tag, val);
159         }
160         else
161                 dnotify(f->target, tag, val);
162 }
163
164
165 #define FILTER_MAGIC_ACTIVE 0xAA
166 /**
167  * Init filter.
168  * If \a masked is true, all the fields value in \a map must be interpreted as a mask of bits.
169  */
170 void filter_init(DFilter *f, const DFilterMap *map, bool masked, DNotifier *source, DNotifier *target)
171 {
172         // Init instance
173         if (masked)
174                 f->update = (update_filter_ptr)filter_mask_update;
175         else
176                 f->update = (update_filter_ptr)filter_update;
177
178         /* set filter map and target */
179         f->map = map;
180         f->target = target;
181
182         /* these ensure that the filter is not inserted in more than one list */
183         ASSERT(f->magic != FILTER_MAGIC_ACTIVE);
184         DB(f->magic = FILTER_MAGIC_ACTIVE;)
185
186         /* Add the filter to source filter list */
187         ADDTAIL(&source->targets, &f->link);
188 }