Add API to remove device
[platform/core/connectivity/ua-plugin-wifi-location.git] / src / wifi-location-plugin.c
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * @author: Abhay Agarwal <ay.agarwal@samsung.com>
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <glib.h>
24 #include "wifi-location-plugin.h"
25 #include "wifi-location-plugin-util.h"
26
27 #define NAME    "wifi-location-plugin"
28 #define AUTHOR  "Samsung"
29 #define VERSION "0.1"
30
31 #define DETECTION_WINDOW_DEFAULT        55 /* 55 seconds */
32
33 #define DETECTION_STARTED 1
34 #define DETECTION_STOPPED 0
35
36 static unsigned int wifi_location_detection_window = DETECTION_WINDOW_DEFAULT;
37 static const uas_callbacks_t *uas_cbs = NULL;
38 static GSList *dev_list = NULL;
39 static int wifi_location_detection_type = 0;
40 static guint stop_scan_timer = 0;
41
42 static void __report_absence(gpointer data, gpointer user_data)
43 {
44         FUNC_ENTER;
45
46         /* TODO: Implement this function */
47
48         FUNC_EXIT;
49 }
50
51 static void __reset_devices(gpointer data, gpointer user_data)
52 {
53         /* TODO: Implement this function */
54         return;
55 }
56
57 static int __stop_scan()
58 {
59         FUNC_ENTER;
60         int ret = UAS_STATUS_SUCCESS;
61
62         g_slist_foreach(dev_list, __reset_devices, NULL);
63
64         /* stop scan */
65         ret = _wifi_location_plugin_stop_scan();
66         retv_if_with_log(UAS_STATUS_SUCCESS != ret, ret, "return %d", ret);
67
68         /* Send detection stopped */
69         if (uas_cbs && uas_cbs->detection_state_cb) {
70                 uas_cbs->detection_state_cb(PLUGIN_ID, DETECTION_STOPPED);
71         } else {
72                 UA_WIFI_LOCATION_ERR("uas_cbs not ready");
73         }
74
75         /* Reset detection flags */
76         wifi_location_detection_type = 0;
77
78         FUNC_EXIT;
79         return ret;
80 }
81
82 static gboolean __stop_scan_expired_timer_cb(gpointer user_data)
83 {
84         int ret = UAS_STATUS_SUCCESS;
85
86         stop_scan_timer = 0;
87
88         /* Report absence for undetected devices */
89         g_slist_foreach(dev_list, __report_absence, NULL);
90
91         /* Stop detection */
92         ret = __stop_scan();
93         retv_if_with_log(UAS_STATUS_SUCCESS != ret, FALSE, "return %d", ret);
94
95         return FALSE;
96 }
97
98 static int __start_scan(gpointer user_data, int scan_mode)
99 {
100         FUNC_ENTER;
101         int ret = UAS_STATUS_SUCCESS;
102
103         ret = _wifi_location_plugin_start_scan(scan_mode);
104         retv_if_with_log(UAS_STATUS_SUCCESS != ret, ret, "return %d", ret);
105
106         if (0 < stop_scan_timer)
107                 g_source_remove(stop_scan_timer);
108         stop_scan_timer = g_timeout_add_seconds(wifi_location_detection_window,
109                                         __stop_scan_expired_timer_cb, NULL);
110
111         /* Send detection started */
112         if (uas_cbs && uas_cbs->detection_state_cb) {
113                 uas_cbs->detection_state_cb(PLUGIN_ID, DETECTION_STARTED);
114         } else {
115                 UA_WIFI_LOCATION_ERR("uas_cbs not ready");
116                 ret = UAS_STATUS_FAIL;
117         }
118
119         FUNC_EXIT;
120         return ret;
121 }
122
123 static int init(const uas_callbacks_t *callbacks)
124 {
125         FUNC_ENTER;
126         int ret = UAS_STATUS_SUCCESS;
127
128         if (!callbacks)
129                 return UAS_STATUS_FAIL;
130
131         retv_if(NULL != uas_cbs, UAS_STATUS_ALREADY_DONE);
132
133         /* TODO: Check wifi location system support */
134
135         /* Initialize wifi-location */
136         ret = wifi_location_initialize();
137         retv_if_with_log(WIFI_LOCATION_ERROR_NONE != ret,
138                         UAS_STATUS_FAIL, "return %d", ret);
139
140         uas_cbs = callbacks;
141
142         FUNC_EXIT;
143         return UAS_STATUS_SUCCESS;
144 }
145
146 static int deinit(void)
147 {
148         FUNC_ENTER;
149         int ret = UAS_STATUS_SUCCESS;
150
151         if (dev_list) {
152                 g_slist_free_full(dev_list, g_free);
153                 dev_list = NULL;
154         }
155
156         /* Deinitialize wifi-location */
157         ret = wifi_location_deinitialize();
158         retv_if_with_log(WIFI_LOCATION_ERROR_NONE != ret,
159                         UAS_STATUS_FAIL, "return %d", ret);
160
161         uas_cbs = NULL;
162
163         FUNC_EXIT;
164         return UAS_STATUS_SUCCESS;
165 }
166
167 static int get_state(int *state)
168 {
169         FUNC_ENTER;
170         int ret = UAS_STATUS_SUCCESS;
171
172         retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
173         retv_if(NULL == state, UAS_STATUS_FAIL);
174
175         /* TODO: Get wifi-location state */
176         *state = UAS_STATE_READY;
177
178         FUNC_EXIT;
179         return ret;
180 }
181
182 static int get_capability(uas_capability_e *capability)
183 {
184         FUNC_ENTER;
185
186         retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
187         retv_if(NULL == capability, UAS_STATUS_FAIL);
188
189         *capability = UAS_SUPPORT_USER;
190
191         FUNC_EXIT;
192         return UAS_STATUS_SUCCESS;
193 }
194
195 static int add_device(uas_device_info_t *device)
196 {
197         FUNC_ENTER;
198         uas_wifi_location_info_t *wifi_location_info;
199
200         retv_if(NULL == device, UAS_STATUS_FAIL);
201         retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
202
203         wifi_location_info =
204                 _wifi_location_plugin_util_get_wifi_location_info_from_dev_info(device);
205         retv_if_with_log(NULL == wifi_location_info, UAS_STATUS_FAIL,
206                 "_wifi_location_plugin_util_get_wifi_location_info_from_dev_info");
207
208         g_idle_add(_wifi_location_plugin_add_device, wifi_location_info);
209
210         FUNC_EXIT;
211         return UAS_STATUS_SUCCESS;
212 }
213
214 static int remove_device(uas_device_info_t *device)
215 {
216         FUNC_ENTER;
217         int ret = UAS_STATUS_SUCCESS;
218         GSList *l;
219         uas_wifi_location_info_t *wifi_location_info = NULL;
220
221         retv_if(NULL == device, UAS_STATUS_FAIL);
222         retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
223
224         for (l = dev_list; NULL != l; l = g_slist_next(l)) {
225                 wifi_location_info = l->data;
226
227                 if (!wifi_location_info) {
228                         UA_WIFI_LOCATION_ERR("data in dev list is NULL");
229                         continue;
230                 }
231
232                 if (!strncasecmp(wifi_location_info->device_id, device->device_id,
233                                 UAS_DEVICE_ID_MAX_LEN))
234                         break;
235         }
236         retv_if(NULL == l, UAS_STATUS_ALREADY_DONE);
237
238         dev_list = g_slist_remove(dev_list, wifi_location_info);
239         g_free(wifi_location_info);
240
241         FUNC_EXIT;
242         return ret;
243 }
244
245 static int start_detection(unsigned int detection_type, int scan_mode)
246 {
247         FUNC_ENTER;
248
249         int ret = UAS_STATUS_SUCCESS;
250
251         retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
252         retv_if(detection_type == (wifi_location_detection_type & detection_type),
253                         UAS_STATUS_ALREADY_DONE);
254
255         /* Check if detection already in progress */
256         if (0 != wifi_location_detection_type)
257                 goto done;
258
259         /* Start detection */
260         ret = __start_scan(NULL, scan_mode);
261         retv_if_with_log(UAS_STATUS_SUCCESS != ret, ret, "return %d", ret);
262
263 done:
264         wifi_location_detection_type |= detection_type;
265         UA_WIFI_LOCATION_INFO_C("wifi_location_detection_type = 0x%8.8X", wifi_location_detection_type);
266
267         FUNC_EXIT;
268         return ret;
269 }
270
271 static int stop_detection(unsigned int detection_type)
272 {
273         FUNC_ENTER;
274         int ret = UAS_STATUS_SUCCESS;
275
276         retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
277         retv_if(0 == (wifi_location_detection_type & detection_type),
278                                                 UAS_STATUS_ALREADY_DONE);
279
280         /* Stop detection */
281         ret = __stop_scan();
282         retv_if_with_log(UAS_STATUS_SUCCESS != ret, ret, "return %d", ret);
283
284         wifi_location_detection_type &= ~detection_type;
285         UA_WIFI_LOCATION_INFO_C("wifi_location_detection_type = 0x%8.8X",
286                                                 wifi_location_detection_type);
287         if (0 != wifi_location_detection_type)
288                 goto done;
289
290         /* Remove stop scan timer */
291         if (0 < stop_scan_timer) {
292                 g_source_remove(stop_scan_timer);
293                 stop_scan_timer = 0;
294                 UA_WIFI_LOCATION_INFO("Stop scan timer removed");
295         }
296
297 done:
298         FUNC_EXIT;
299         return ret;
300 }
301
302 static int set_detection_window(unsigned int detection_window)
303 {
304         FUNC_ENTER;
305
306         retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
307
308         wifi_location_detection_window = detection_window;
309
310         FUNC_EXIT;
311         return UAS_STATUS_SUCCESS;
312 }
313
314 static uas_api_t wifi_location_api = {
315         .init = init,
316         .deinit = deinit,
317         .get_state = get_state,
318         .get_capability = get_capability,
319         .set_registered_devices = NULL,
320         .add_device = add_device,
321         .remove_device = remove_device,
322         .start_detection = start_detection,
323         .stop_detection = stop_detection,
324         .set_low_power_mode = NULL,
325         .set_detection_window = set_detection_window,
326         .set_detection_threshold = NULL,
327         .scan_active_devices = NULL,
328         .cancel_active_device_scan = NULL,
329         .add_ibeacon_adv = NULL,
330 };
331
332 static int module_init(uas_api_t **api)
333 {
334         FUNC_ENTER;
335
336         *api = &wifi_location_api;
337
338         FUNC_EXIT;
339         return 0;
340 }
341
342 static int module_deinit(void)
343 {
344         FUNC_ENTER;
345
346         FUNC_EXIT;
347         return 0;
348 }
349
350 UAS_MODULE_ADD(UAS_PLUGIN_ID_WIFI_LOCATION, NAME, AUTHOR, VERSION, module_init, module_deinit);
351
352 void _wifi_location_plugin_handle_device_added(int status,
353                 uas_wifi_location_info_t *wifi_location_info)
354 {
355         FUNC_ENTER;
356         uas_device_info_t *dev_info;
357
358         ret_if(NULL == wifi_location_info);
359
360         dev_info = _wifi_location_plugin_util_get_dev_info_from_wifi_location_info(
361                                                                 wifi_location_info);
362         if (NULL == dev_info) {
363                 /* Device Addition failed */
364                 UA_WIFI_LOCATION_ERR(
365                 "_wifi_location_plugin_util_get_dev_info_from_wifi_location_info failed");
366                 if (uas_cbs && uas_cbs->device_added_cb)
367                         uas_cbs->device_added_cb(PLUGIN_ID, UAS_STATUS_FAIL, NULL);
368                 FUNC_EXIT;
369                 return;
370         }
371
372         if (UAS_STATUS_SUCCESS == status) {
373                 dev_list = g_slist_prepend(dev_list,
374                                 g_memdup(wifi_location_info,
375                                 sizeof(uas_wifi_location_info_t)));
376         }
377         /* Save current time */
378         dev_info->last_seen = _wifi_location_plugin_util_get_curr_time();
379
380         /* Send device Addition callback */
381         if (uas_cbs && uas_cbs->device_added_cb) {
382                 uas_cbs->device_added_cb(PLUGIN_ID, status, dev_info);
383         } else {
384                 UA_WIFI_LOCATION_ERR("uas_cbs not ready");
385         }
386
387         _wifi_location_plugin_util_uas_device_info_free(dev_info);
388         FUNC_EXIT;
389 }