1 /**
2  * \file
3  *
4  * \brief Events implementation.
5  *
6  * Copyright (C) 2015 Atmel Corporation. All rights reserved.
7  *
8  * \asf_license_start
9  *
10  * \page License
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions are met:
14  *
15  * 1. Redistributions of source code must retain the above copyright notice,
16  *    this list of conditions and the following disclaimer.
17  *
18  * 2. Redistributions in binary form must reproduce the above copyright notice,
19  *    this list of conditions and the following disclaimer in the documentation
20  *    and/or other materials provided with the distribution.
21  *
22  * 3. The name of Atmel may not be used to endorse or promote products derived
23  *    from this software without specific prior written permission.
24  *
25  * 4. This software may only be redistributed and used in connection with an
26  *    Atmel microcontroller product.
27  *
28  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSEsD AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  *
40  * \asf_license_stop
41  *
42  */
43 
44 #include <utils_event.h>
45 #include <utils_assert.h>
46 #include <string.h>
47 
48 #define EVENT_WORD_BITS (sizeof(event_word_t) * 8)
49 
50 static struct list_descriptor events;
51 static uint8_t                subscribed[EVENT_MASK_SIZE];
52 
event_subscribe(struct event * const event,const event_id_t id,event_cb_t cb)53 int32_t event_subscribe(struct event *const event, const event_id_t id, event_cb_t cb)
54 {
55 	/* get byte and bit number of the given event in the event mask */
56 	const uint8_t position = id >> 3;
57 	const uint8_t mask     = 1 << (id & 0x7);
58 
59 	ASSERT(event && cb && (id < EVENT_MAX_AMOUNT));
60 
61 	if (event->mask[position] & mask) {
62 		return ERR_NO_CHANGE; /* Already subscribed */
63 	}
64 
65 	if (!is_list_element(&events, event)) {
66 		memset(event->mask, 0, EVENT_MASK_SIZE);
67 		list_insert_as_head(&events, event);
68 	}
69 	event->cb = cb;
70 	event->mask[position] |= mask;
71 
72 	subscribed[position] |= mask;
73 
74 	return ERR_NONE;
75 }
76 
event_unsubscribe(struct event * const event,const event_id_t id)77 int32_t event_unsubscribe(struct event *const event, const event_id_t id)
78 {
79 	/* get byte and bit number of the given event in the event mask */
80 	const uint8_t       position = id >> 3;
81 	const uint8_t       mask     = 1 << (id & 0x7);
82 	const struct event *current;
83 	uint8_t             i;
84 
85 	ASSERT(event && (id < EVENT_MAX_AMOUNT));
86 
87 	if (!(event->mask[position] & mask)) {
88 		return ERR_NO_CHANGE; /* Already unsubscribed */
89 	}
90 
91 	event->mask[position] &= ~mask;
92 
93 	/* Check if there are more subscribers */
94 	for ((current = (const struct event *)list_get_head(&events)); current;
95 	     current = (const struct event *)list_get_next_element(current)) {
96 		if (current->mask[position] & mask) {
97 			break;
98 		}
99 	}
100 	if (!current) {
101 		subscribed[position] &= ~mask;
102 	}
103 
104 	/* Remove event from the list. Can be unsave, document it! */
105 	for (i = 0; i < ARRAY_SIZE(event->mask); i++) {
106 		if (event->mask[i]) {
107 			return ERR_NONE;
108 		}
109 	}
110 	list_delete_element(&events, event);
111 
112 	return ERR_NONE;
113 }
114 
event_post(const event_id_t id,const event_data_t data)115 void event_post(const event_id_t id, const event_data_t data)
116 {
117 	/* get byte and bit number of the given event in the event mask */
118 	const uint8_t       position = id >> 3;
119 	const uint8_t       mask     = 1 << (id & 0x7);
120 	const struct event *current;
121 
122 	ASSERT((id < EVENT_MAX_AMOUNT));
123 
124 	if (!(subscribed[position] & mask)) {
125 		return; /* No subscribers */
126 	}
127 
128 	/* Find all subscribers */
129 	for ((current = (const struct event *)list_get_head(&events)); current;
130 	     current = (const struct event *)list_get_next_element(current)) {
131 		if (current->mask[position] & mask) {
132 			current->cb(id, data);
133 		}
134 	}
135 }
136