Update preset.
[bertos.git] / bertos / 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  *
33  * \brief Notifier obj (implementation).
34  *
35  * \author Bernie Innocenti <bernie@codewiz.org>
36  * \author Francesco Sacchi <batt@develer.com>
37  */
38
39 #include <cfg/debug.h>
40
41 #include <dt/dtag.h>
42 #include <dt/dnotifier.h>
43 #include <struct/list.h>
44
45 /**
46  * Default update used to notify target: notify all trasparently all
47  * targets in the list.
48  */
49 static void notifier_update(DNotifier *n, dtag_t tag, dval_t val)
50 {
51         dnotify_targets(n, tag, val);
52 }
53
54 /**
55  * Init.
56  */
57 void notifier_init(DNotifier *n)
58 {
59         // Init instance
60         n->update = notifier_update;
61         LIST_INIT(&n->targets);
62 }
63
64 /**
65  * Search in the map a tag and a val corresponding to the ones supplied.
66  * If a match is found change them to the corresponding ones in the map.
67  * If map is NULL the filter is trasparent and all messages sent to filter
68  * will be forwarded to its target.
69  */
70 void filter_update(DFilter *f, dtag_t tag, dval_t val)
71 {
72
73         const DFilterMap *map = f->map;
74
75         if (map)
76         {
77                 while (map->src.tag != TAG_END)
78                 {
79                         if ((map->src.tag == tag) && (map->src.val == val))
80                         {
81                                 tag = map->dst.tag;
82                                 val = map->dst.val;
83                                 break;
84                         }
85                         /* TAG_ANY matches anything */
86                         if (map->src.tag == TAG_ANY)
87                                 break;
88                         map++;
89                 }
90
91                 if (map->src.tag != TAG_END)
92                         dnotify(f->target, tag, val);
93         }
94         else
95                 dnotify(f->target, tag, val);
96 }
97
98
99 /**
100  * Search in the table a tag corresponding to the one supplied and a val
101  * that has at least the mask map supplied bits to one.
102  * If a match is found change them to the corresponding ones in the map.
103  * If map is NULL the filter is trasparent and all messages sent to filter
104  * will be forwarded to its target.
105  */
106 void filter_mask_update(DFilter *f, dtag_t tag, dval_t val)
107 {
108
109         const DFilterMap *map = f->map;
110         dfilter_mask_t mask;
111
112         if (map)
113         {
114                 while (map->src.tag != TAG_END)
115                 {
116                         mask = (dfilter_mask_t) map->src.val;
117                         if ((map->src.tag == tag) && ((mask & (dfilter_mask_t)val) == mask))
118                         {
119                                 tag = map->dst.tag;
120                                 val = map->dst.val;
121                                 break;
122                         }
123                         /* TAG_ANY matches anything */
124                         if (map->src.tag == TAG_ANY)
125                                 break;
126                         map++;
127                 }
128
129
130                 if (map->src.tag != TAG_END)
131                         dnotify(f->target, tag, val);
132         }
133         else
134                 dnotify(f->target, tag, val);
135 }
136
137
138 #define FILTER_MAGIC_ACTIVE 0xAA
139 /**
140  * Init filter.
141  * If \a masked is true, all the fields value in \a map must be interpreted as a mask of bits.
142  */
143 void filter_init(DFilter *f, const DFilterMap *map, bool masked, DNotifier *source, DNotifier *target)
144 {
145         // Init instance
146         if (masked)
147                 f->update = (update_filter_ptr)filter_mask_update;
148         else
149                 f->update = (update_filter_ptr)filter_update;
150
151         /* set filter map and target */
152         f->map = map;
153         f->target = target;
154
155         /* these ensure that the filter is not inserted in more than one list */
156         ASSERT(f->magic != FILTER_MAGIC_ACTIVE);
157         DB(f->magic = FILTER_MAGIC_ACTIVE;)
158
159         /* Add the filter to source filter list */
160         ADDTAIL(&source->targets, &f->link);
161 }