1 /*
2 * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3 *
4 */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stdint.h>
9 #include <string.h>
10
11 #include "uvoice_os.h"
12 #include "uvoice_types.h"
13 #include "uvoice_event.h"
14 #include "uvoice_list.h"
15
16 #include "uvoice_message.h"
17
18 // #define UVOICE_EVENT_TASK_ENABLE
19
20 #ifdef MUSICBOX_APP
21 #define EVENT_TASK_STACK_SIZE 2048
22 #else
23 #define EVENT_TASK_STACK_SIZE 8192
24 #endif
25 #define EVENT_TASK_PRIORITY UVOICE_TASK_PRI_LOWEST
26
27 #define EVENT_MESSAGE_QUEUE_MAX 10
28
29 struct uvoice_event_node {
30 uint16_t type_filter;
31 uvoice_list_t list;
32 uvoice_event_cb cb;
33 void *data;
34 };
35
36 static uvoice_list_t uvoice_event_client_list = UVOICE_LIST_INIT(uvoice_event_client_list);
37 static os_task_t uvoice_event_task;
38
39 #ifdef UVOICE_EVENT_TASK_ENABLE
40 static os_message_queue_t uvoice_event_msgqueue;
41 #endif
42
uvoice_event_handle(uvoice_event_t * event)43 static void uvoice_event_handle(uvoice_event_t *event)
44 {
45 struct uvoice_event_node *node = NULL;
46 uvoice_list_for_each_entry(&uvoice_event_client_list, node, struct uvoice_event_node, list)
47 {
48 if (node->type_filter != event->type)
49 continue;
50 node->cb(event, node->data);
51 }
52 }
53
54 #ifdef UVOICE_EVENT_TASK_ENABLE
uvoice_event_loop(void * arg)55 static void uvoice_event_loop(void *arg)
56 {
57 uvoice_event_t event;
58 unsigned int size = 0;
59 int ret;
60
61 while (1) {
62 ret = os_message_queue_recv(uvoice_event_msgqueue, &event, sizeof(event), OS_WAIT_FOREVER);
63 if (ret < 0)
64 continue;
65 if (event.type == 0xffff && event.code == 0xffff && event.value == 0xccccffff) {
66 M_LOGW("uvoice event loop exit");
67 break;
68 }
69 uvoice_event_handle(&event);
70 }
71
72 os_task_exit(uvoice_event_task);
73 }
74 #endif
75
uvoice_event_init(void)76 int uvoice_event_init(void)
77 {
78 #ifdef UVOICE_EVENT_ENABLE
79
80 #ifdef UVOICE_EVENT_TASK_ENABLE
81 uvoice_msgqueue_t *msgqueue;
82 int ret;
83
84 if (uvoice_event_msgqueue) {
85 M_LOGW("uvoice event exist\n");
86 return -1;
87 }
88
89 uvoice_event_msgqueue = os_message_queue_create(EVENT_MESSAGE_QUEUE_MAX, sizeof(uvoice_event_t));
90 if (!uvoice_event_msgqueue) {
91 M_LOGE("create msgqueue failed !\n");
92 return -1;
93 }
94
95 ret = os_task_create(&uvoice_event_task, "uvoice_event_task", uvoice_event_loop, NULL, EVENT_TASK_STACK_SIZE,
96 EVENT_TASK_PRIORITY);
97 if (ret) {
98 M_LOGE("create event task failed %d!\n", ret);
99 os_message_queue_free(uvoice_event_msgqueue);
100 uvoice_event_msgqueue = NULL;
101 return -1;
102 }
103 #endif
104
105 #endif
106
107 return 0;
108 }
109
uvoice_event_deinit(void)110 int uvoice_event_deinit(void)
111 {
112 #ifdef UVOICE_EVENT_ENABLE
113
114 struct uvoice_event_node *node = NULL;
115 uvoice_list_t *temp = NULL;
116
117 #ifdef UVOICE_EVENT_TASK_ENABLE
118
119 uvoice_event_post(0xffff, 0xffff, 0xccccffff);
120 os_msleep(10);
121 if (uvoice_event_msgqueue) {
122 os_message_queue_free(uvoice_event_msgqueue);
123 uvoice_event_msgqueue = NULL;
124 }
125 #endif
126
127 uvoice_list_for_each_entry_safe(&uvoice_event_client_list, temp, node, struct uvoice_event_node, list)
128 {
129 uvoice_list_del(&node->list);
130 snd_free(node);
131 }
132
133 #endif
134
135 return 0;
136 }
137
uvoice_event_post(uint16_t type,uint16_t code,int value)138 int uvoice_event_post(uint16_t type, uint16_t code, int value)
139 {
140 #ifdef UVOICE_EVENT_ENABLE
141
142 uvoice_event_t event = {
143 .type = type,
144 .code = code,
145 .value = value,
146 };
147
148 #ifdef UVOICE_EVENT_TASK_ENABLE
149 int ret;
150
151 if (!uvoice_event_msgqueue) {
152 M_LOGD("no event msgqueue\n");
153 return -1;
154 }
155
156 ret = os_message_queue_send(uvoice_event_msgqueue, &event, sizeof(uvoice_event_t), 0);
157 if (ret < 0) {
158 M_LOGE("send event failed %d!\n", ret);
159 return -1;
160 }
161 #else
162 struct uvoice_event_node *node = NULL;
163 uvoice_list_for_each_entry(&uvoice_event_client_list, node, struct uvoice_event_node, list)
164 {
165 if (node->type_filter != type)
166 continue;
167 node->cb(&event, node->data);
168 }
169 #endif
170
171 return 0;
172
173 #else
174 return os_event_post(type, code, value);
175 #endif
176 }
177
uvoice_event_register(uint16_t type,uvoice_event_cb cb,void * data)178 int uvoice_event_register(uint16_t type, uvoice_event_cb cb, void *data)
179 {
180 #ifdef UVOICE_EVENT_ENABLE
181
182 struct uvoice_event_node *node;
183
184 #ifdef UVOICE_EVENT_TASK_ENABLE
185 if (!uvoice_event_msgqueue) {
186 M_LOGD("no event msgqueue\n");
187 return -1;
188 }
189 #endif
190
191 if (!cb) {
192 M_LOGE("callback function null !\n");
193 return -1;
194 }
195
196 node = snd_zalloc(sizeof(struct uvoice_event_node), AFM_EXTN);
197 if (!node) {
198 M_LOGE("alloc event node failed !\n");
199 return -1;
200 }
201
202 node->cb = cb;
203 node->type_filter = type;
204 node->data = data;
205
206 uvoice_list_add_tail(&node->list, &uvoice_event_client_list);
207 return 0;
208 #else
209 return os_event_register(type, cb, data);
210 #endif
211 }
212
uvoice_event_unregister(uint16_t type,uvoice_event_cb cb,void * data)213 int uvoice_event_unregister(uint16_t type, uvoice_event_cb cb, void *data)
214 {
215 #ifdef UVOICE_EVENT_ENABLE
216
217 struct uvoice_event_node *node = NULL;
218 uvoice_list_t *temp = NULL;
219 int ret = -1;
220
221 uvoice_list_for_each_entry_safe(&uvoice_event_client_list, temp, node, struct uvoice_event_node, list)
222 {
223 if (node->type_filter != type)
224 continue;
225
226 if (node->cb != cb)
227 continue;
228
229 if (node->data != data)
230 continue;
231
232 uvoice_list_del(&node->list);
233 snd_free(node);
234 ret = 0;
235 break;
236 }
237
238 return ret;
239
240 #else
241 return os_event_unregister(type, cb, data);
242 #endif
243 }
244