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