blob: d1af9d0cf128260ef639fc8d9aa57e919cfe9e25 [file] [log] [blame]
Kévin Redon69b92d92019-01-24 16:39:20 +01001/**
2 * \file
3 *
4 * \brief Events implementation.
5 *
6 * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Subject to your compliance with these terms, you may use Microchip
13 * software and any derivatives exclusively with Microchip products.
14 * It is your responsibility to comply with third party license terms applicable
15 * to your use of third party software (including open source software) that
16 * may accompany Microchip software.
17 *
18 * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
19 * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
20 * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
21 * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
22 * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
23 * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
24 * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
25 * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
26 * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
27 * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
28 * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
29 *
30 * \asf_license_stop
31 *
32 */
33
34#include <utils_event.h>
35#include <utils_assert.h>
36#include <string.h>
37
38#define EVENT_WORD_BITS (sizeof(event_word_t) * 8)
39
40static struct list_descriptor events;
41static uint8_t subscribed[EVENT_MASK_SIZE];
42
43int32_t event_subscribe(struct event *const event, const event_id_t id, event_cb_t cb)
44{
45 /* get byte and bit number of the given event in the event mask */
46 const uint8_t position = id >> 3;
47 const uint8_t mask = 1 << (id & 0x7);
48
49 ASSERT(event && cb && (id < EVENT_MAX_AMOUNT));
50
51 if (event->mask[position] & mask) {
52 return ERR_NO_CHANGE; /* Already subscribed */
53 }
54
55 if (!is_list_element(&events, event)) {
56 memset(event->mask, 0, EVENT_MASK_SIZE);
57 list_insert_as_head(&events, event);
58 }
59 event->cb = cb;
60 event->mask[position] |= mask;
61
62 subscribed[position] |= mask;
63
64 return ERR_NONE;
65}
66
67int32_t event_unsubscribe(struct event *const event, const event_id_t id)
68{
69 /* get byte and bit number of the given event in the event mask */
70 const uint8_t position = id >> 3;
71 const uint8_t mask = 1 << (id & 0x7);
72 const struct event *current;
73 uint8_t i;
74
75 ASSERT(event && (id < EVENT_MAX_AMOUNT));
76
77 if (!(event->mask[position] & mask)) {
78 return ERR_NO_CHANGE; /* Already unsubscribed */
79 }
80
81 event->mask[position] &= ~mask;
82
83 /* Check if there are more subscribers */
84 for ((current = (const struct event *)list_get_head(&events)); current;
85 current = (const struct event *)list_get_next_element(current)) {
86 if (current->mask[position] & mask) {
87 break;
88 }
89 }
90 if (!current) {
91 subscribed[position] &= ~mask;
92 }
93
94 /* Remove event from the list. Can be unsave, document it! */
95 for (i = 0; i < ARRAY_SIZE(event->mask); i++) {
96 if (event->mask[i]) {
97 return ERR_NONE;
98 }
99 }
100 list_delete_element(&events, event);
101
102 return ERR_NONE;
103}
104
105void event_post(const event_id_t id, const event_data_t data)
106{
107 /* get byte and bit number of the given event in the event mask */
108 const uint8_t position = id >> 3;
109 const uint8_t mask = 1 << (id & 0x7);
110 const struct event *current;
111
112 ASSERT((id < EVENT_MAX_AMOUNT));
113
114 if (!(subscribed[position] & mask)) {
115 return; /* No subscribers */
116 }
117
118 /* Find all subscribers */
119 for ((current = (const struct event *)list_get_head(&events)); current;
120 current = (const struct event *)list_get_next_element(current)) {
121 if (current->mask[position] & mask) {
122 current->cb(id, data);
123 }
124 }
125}