[Fix] Remove spaces and extra function call
[platform/core/connectivity/ua-plugin-wifi-dummy.git] / src / wifi-plugin.c
1 /*
2  * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <glib.h>
22
23 #include <log.h>
24 #include <wifi-plugin.h>
25 #include <wifi-plugin-util.h>
26 #include <wifi-scan.h>
27 #include <wifi-networkmanager.h>
28
29 #define NAME    "wifi-plugin"
30 #define AUTHOR  "Samsung"
31 #define VERSION "0.1"
32
33 #define DETECTION_WINDOW_DEFAULT 60 /* 1 minute -> 1 * 60 = 60 seconds */
34 #define ABSENCE_THRESHOLD_DEFAULT 1
35
36 static int wifi_detection_window = DETECTION_WINDOW_DEFAULT;
37 static bool initial_bursts = true;
38
39 static gboolean lpm_enabled = FALSE; /**< Low power mode */
40
41 static const uas_callbacks_t *uas_cbs = NULL; /**< Interfaces for ua_manager */
42 static uas_state_e curr_state = UAS_STATE_NOT_READY; /**< Plugin state */
43 static GSList *dev_list = NULL; /**< Device lists */
44 static unsigned int detect_count;
45 static int wifi_detection_type = 0;
46
47 static int init(const uas_callbacks_t *callbacks)
48 {
49         FUNC_ENTER;
50
51         retv_if(NULL == callbacks, UAS_STATUS_FAIL);
52
53         if (uas_cbs != NULL) {
54                 UA_WIFI_DBG("Wi-Fi plugin is already initialized");
55                 FUNC_EXIT;
56                 return UAS_STATUS_ALREADY_DONE;
57         } else {
58                 uas_cbs = callbacks;
59         }
60
61         detect_count = 0;
62
63         if (__nm_init() != true) {
64                 UA_WIFI_ERR("Fail to initialize network manager");
65                 FUNC_EXIT;
66                 return UAS_STATUS_FAIL;
67         }
68
69         if (__initialize_arp_data() != UAS_STATUS_SUCCESS) {
70                 UA_WIFI_ERR("Fail to initialize arp data");
71                 FUNC_EXIT;
72                 return UAS_STATUS_FAIL;
73         }
74
75         FUNC_EXIT;
76         return UAS_STATUS_SUCCESS;
77 }
78
79 static int deinit(void)
80 {
81         FUNC_ENTER;
82         if (dev_list) {
83                 g_slist_free_full(dev_list, g_free);
84                 dev_list = NULL;
85         }
86
87         __nm_deinit();
88         __deinit_arp_data();
89         FUNC_EXIT;
90         return UAS_STATUS_SUCCESS;
91 }
92
93 static int get_state(int *state)
94 {
95         FUNC_ENTER;
96
97         *state = curr_state;
98
99         FUNC_EXIT;
100         return UAS_STATUS_SUCCESS;
101 }
102
103 static int get_capability(uas_capability_e *capability)
104 {
105         FUNC_ENTER;
106
107         retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
108
109         *capability = UAS_SUPPORT_USER;
110
111         FUNC_EXIT;
112         return UAS_STATUS_SUCCESS;
113 }
114
115 static int set_registered_devices(int num_devices, uas_device_info_t *devices)
116 {
117         FUNC_ENTER;
118         int i, dev_count = 0;
119
120         retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
121
122         if (dev_list) {
123                 g_slist_free_full(dev_list, g_free);
124                 dev_list = NULL;
125         }
126
127         for (i = 0; i < num_devices; i++) {
128                 uas_wifi_info_t* wifi_info;
129
130                 wifi_info = _wifi_plugin_util_get_wifi_info_from_dev_info(&(devices[i]));
131
132                 if (!wifi_info)
133                         continue;
134                 else
135                         dev_count++;
136
137                 wifi_info->mobile_flag = dev_count;
138                 dev_list = g_slist_prepend(dev_list, wifi_info);
139         }
140
141         detect_count = dev_count;
142
143         if (uas_cbs->state_changed_cb) {
144                 switch (curr_state) {
145                 case UAS_STATE_NOT_READY:
146                         if (dev_list) {
147                                 uas_cbs->state_changed_cb(UAS_STATE_READY);
148                                 curr_state = UAS_STATE_READY;
149                         }
150                         break;
151                 case UAS_STATE_READY:
152                         if (!dev_list) {
153                                 uas_cbs->state_changed_cb(UAS_STATE_NOT_READY);
154                                 curr_state = UAS_STATE_NOT_READY;
155                         }
156                         break;
157                 }
158         }
159
160         FUNC_EXIT;
161         return UAS_STATUS_SUCCESS;
162 }
163
164 void __check_mobilelist()
165 {
166         int ret;
167         GSList *l;
168
169         if (!dev_list) {
170                 UA_WIFI_ERR("No devices to scan");
171                 return ;
172         }
173
174         for (l = dev_list; NULL != l; l = g_slist_next(l)) {
175                 uas_wifi_info_t *wifi_info = l->data;
176
177                 if (wifi_info->mobile_flag != detect_count)
178                         continue;
179
180                 if (WIFI_PRESENCE_STATUS_ABSENCE == wifi_info->presence) {
181                         UA_WIFI_INFO("Detect this mobild id %s start presence request MAC %s",
182                                 wifi_info->mobile_id, wifi_info->mac_addr);
183                         if (initial_bursts == true) {
184                                 if (UAS_STATUS_SUCCESS != __init_ip_mac_count()) {
185                                         UA_WIFI_ERR("ARP Init fail");
186                                         return;
187                                 } else
188                                         initial_bursts = false;
189                         }
190
191                         ret = __start_wifi_detection(wifi_info->ip_addr, wifi_info->mac_addr);
192                         if (UAS_STATUS_SUCCESS != ret) {
193                                 UA_WIFI_ERR("ARP Init fail");
194                                 wifi_info->presence = WIFI_PRESENCE_STATUS_ABSENCE;
195                                 detect_count--;
196                                 continue;
197                         }
198                         break;
199                 } else {
200                         UA_WIFI_INFO("Already detected, So skip");
201                         detect_count--;
202                 }
203         }
204
205         __check_mobile_list_finish(false);
206 }
207
208 void __reset_wifi_info()
209 {
210         GSList *l;
211         detect_count = g_slist_length(dev_list);
212
213         for (l = dev_list; NULL != l; l = g_slist_next(l)) {
214                 uas_wifi_info_t *wifi_info = l->data;
215                 wifi_info->presence = WIFI_PRESENCE_STATUS_ABSENCE;
216         }
217 }
218
219 static gboolean __start_wifi_scan(gpointer user_data)
220 {
221         FUNC_ENTER;
222
223         initial_bursts = true;
224         __reset_wifi_info();
225         __check_mobilelist();
226
227         /* Send detection started */
228         if (uas_cbs && uas_cbs->detection_state_cb)
229                 uas_cbs->detection_state_cb(1);
230
231         FUNC_EXIT;
232         return TRUE;
233 }
234
235 void __check_device_found(char* sbuf, char* ip_sbuf)
236 {
237         FUNC_ENTER;
238         GSList *l;
239
240         for (l = dev_list; NULL != l; l = g_slist_next(l)) {
241                 uas_wifi_info_t *wifi_info = l->data;
242                 uas_device_info_t *dev_info = NULL;
243
244                 if (wifi_info->mobile_flag == detect_count) {
245                         wifi_info->presence = WIFI_PRESENCE_STATUS_PRESENCE;
246
247                         g_strlcpy(wifi_info->mac_addr, sbuf, MAC_ADDRESS_STRING_SIZE);
248                         g_strlcpy(wifi_info->ip_addr, ip_sbuf, IP_ADDRESS_STRING_SIZE);
249
250                         if (!(UAS_PRESENCE & wifi_detection_type))
251                                 break;
252
253                         if (!uas_cbs || !uas_cbs->device_detected_cb)
254                                 break;
255
256                         /* Send PRESENCE callback */
257                         dev_info = _wifi_plugin_util_get_dev_info_from_wifi_info(wifi_info);
258                         if (!dev_info) {
259                                 UA_WIFI_ERR("Unable to get dev_info");
260                                 break;
261                         }
262
263                         uas_cbs->device_detected_cb(UAS_PRESENCE, dev_info);
264                         UA_WIFI_INFO("Called uas_cbs->device_detected_cb(UAS_PRESENCE)");
265                         _wifi_plugin_util_uas_device_info_free(dev_info);
266                         break;
267                 }
268         }
269         FUNC_EXIT;
270 }
271
272 void __check_mobile_list_finish(bool is_check)
273 {
274         FUNC_ENTER;
275         uas_device_info_t *dev_info = NULL;
276
277         if (is_check == true)
278                 detect_count--;
279
280         UA_WIFI_INFO("find next mobile flag %d", detect_count);
281
282         if (!detect_count) {
283
284                 GSList *l;
285
286                 UA_WIFI_INFO("Already All mobile detected");
287
288                 initial_bursts = true;
289
290
291                 UA_WIFI_INFO("Detection mode unicast finish");
292
293                 for (l = dev_list; NULL != l; l = g_slist_next(l)) {
294                         uas_wifi_info_t *wifi_info = l->data;
295
296                         if (!wifi_info)
297                                 continue;
298
299                         if (wifi_info->presence) {
300                                 wifi_info->presence = WIFI_PRESENCE_STATUS_ABSENCE;
301                                 continue;
302                         }
303
304                         if ((UAS_ABSENCE & wifi_detection_type) &&
305                                         (uas_cbs && uas_cbs->device_detected_cb)) {
306                                 dev_info = _wifi_plugin_util_get_dev_info_from_wifi_info(wifi_info);
307                                 if (!dev_info) {
308                                         UA_WIFI_ERR("Unable to get dev_info");
309                                         break;
310                                 }
311
312                                 uas_cbs->device_detected_cb(UAS_ABSENCE, dev_info);
313                                 UA_WIFI_INFO("Called uas_cbs->device_detected_cb(UAS_ABSENCE)");
314                                 _wifi_plugin_util_uas_device_info_free(dev_info);
315                         }
316
317                         wifi_info->presence = WIFI_PRESENCE_STATUS_ABSENCE;
318                 }
319
320                 /* Send detection stopped */
321                 if (uas_cbs && uas_cbs->detection_state_cb)
322                         uas_cbs->detection_state_cb(0);
323
324                 /* Reset detection flags */
325                 wifi_detection_type = 0;
326         } else {
327                 if (is_check == true) {
328                         initial_bursts = true;
329                         __check_mobilelist();
330                 }
331         }
332
333         FUNC_EXIT;
334 }
335
336 static gboolean __add_device_send(gpointer data)
337 {
338         GSList *l;
339         uas_device_info_t *dev_info = NULL;
340
341         initial_bursts = true;
342
343         for (l = dev_list; NULL != l; l = g_slist_next(l)) {
344                 uas_wifi_info_t *wifi_info = l->data;
345
346                 if (wifi_info->new_device == true) {
347                         wifi_info->new_device = false;
348
349                         if (NULL == uas_cbs || NULL == uas_cbs->device_added_cb) {
350                                 dev_list = g_slist_remove(dev_list, wifi_info);
351                                 free(wifi_info);
352                                 break;
353                         }
354
355                         dev_info = _wifi_plugin_util_get_dev_info_from_wifi_info(wifi_info);
356
357                         if (!dev_info) {
358                                 UA_WIFI_ERR("Unable to get dev_info");
359                                 dev_list = g_slist_remove(dev_list, wifi_info);
360                                 free(wifi_info);
361                                 break;
362                         }
363
364                         uas_cbs->device_added_cb(UAS_STATUS_SUCCESS, dev_info);
365                         _wifi_plugin_util_uas_device_info_free(dev_info);
366                         break;
367                 }
368         }
369
370         return FALSE;
371 }
372
373 static int add_device(uas_device_info_t *device)
374 {
375         FUNC_ENTER;
376
377         uas_wifi_info_t *wifi_info;
378         int mac_len;
379         int ip_len;
380
381         retv_if(NULL == device, UAS_STATUS_FAIL);
382         retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
383
384         wifi_info = _wifi_plugin_util_get_wifi_info_from_dev_info(device);
385         retv_if(NULL == wifi_info, UAS_STATUS_FAIL);
386
387         mac_len = strlen(wifi_info->mac_addr);
388         ip_len = strlen(wifi_info->ip_addr);
389         if (!mac_len && !ip_len) {
390                 free(wifi_info);
391                 FUNC_EXIT;
392                 return UAS_STATUS_FAIL;
393         }
394
395         wifi_info->new_device = true;
396         /* Add to list */
397         dev_list = g_slist_prepend(dev_list,
398                         g_memdup(wifi_info, sizeof(uas_wifi_info_t)));
399         UA_WIFI_DBG("Added device to list, num devices = %d", g_slist_length(dev_list));
400
401         if (mac_len && ip_len &&
402                         (strcasecmp(wifi_info->mac_addr, BROADCAST_MAC_ADDR) != 0)) {
403                 initial_bursts = true;
404                 g_idle_add(__add_device_send, NULL);
405         }
406
407         free(wifi_info);
408
409         FUNC_EXIT;
410         return UAS_STATUS_SUCCESS;
411 }
412
413 static int remove_device(uas_device_info_t *device)
414 {
415         FUNC_ENTER;
416         GSList *l;
417
418         retv_if(NULL == device, UAS_STATUS_FAIL);
419         retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
420
421         for (l = dev_list; NULL != l; l = g_slist_next(l)) {
422                 uas_wifi_info_t *wifi_info = l->data;
423
424                 if (!strcasecmp(wifi_info->mobile_id, device->device_id)) {
425                         dev_list = g_slist_remove(dev_list, wifi_info);
426                         free(wifi_info);
427                         return UAS_STATUS_SUCCESS;
428                 }
429         }
430
431         FUNC_EXIT;
432         return UAS_STATUS_FAIL;
433 }
434
435 static int start_detection(unsigned int detection_type)
436 {
437         FUNC_ENTER;
438
439         retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
440         retv_if((wifi_detection_type & detection_type), UAS_STATUS_ALREADY_DONE);
441
442         /* Check if detection already in progress */
443         if (0 != wifi_detection_type) {
444                 wifi_detection_type |= detection_type;
445                 goto done;
446         }
447
448         wifi_detection_type |= detection_type;
449         /* Check if lpm enabled */
450         if (lpm_enabled) {
451                 FUNC_EXIT;
452                 return UAS_STATUS_SUCCESS;
453         }
454
455         /* Start detection */
456         __start_wifi_scan(NULL);
457
458 done:
459         UA_WIFI_INFO("wifi_detection_type = 0x%8.8X", wifi_detection_type);
460         FUNC_EXIT;
461         return UAS_STATUS_SUCCESS;
462 }
463
464 static int stop_detection(unsigned int detection_type)
465 {
466         FUNC_ENTER;
467
468         retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
469         retv_if(0 == wifi_detection_type, UAS_STATUS_ALREADY_DONE);
470
471         wifi_detection_type &= ~detection_type;
472         UA_WIFI_INFO("wifi_detection_type = 0x%8.8X", wifi_detection_type);
473
474         if (0 != wifi_detection_type)
475                 goto done;
476
477 done:
478         FUNC_EXIT;
479         return UAS_STATUS_SUCCESS;
480 }
481
482 static int set_low_power_mode(int mode)
483 {
484         FUNC_ENTER;
485
486         if (0 == mode)
487                 lpm_enabled = FALSE;
488         else
489                 lpm_enabled = TRUE;
490
491         FUNC_EXIT;
492         return UAS_STATUS_SUCCESS;
493 }
494
495 static int set_detection_window(unsigned int detection_window)
496 {
497         FUNC_ENTER;
498
499         retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
500
501         wifi_detection_window = detection_window;
502
503         FUNC_EXIT;
504         return UAS_STATUS_SUCCESS;
505 }
506
507 static int set_detection_threshold(int presence_threshold, int absence_threshold)
508 {
509         FUNC_ENTER;
510
511         UA_WIFI_INFO("presence_threshold = %d, absence_threshold = %d",
512                         presence_threshold, absence_threshold);
513
514         FUNC_EXIT;
515         return UAS_STATUS_UNSUPPORTED;
516 }
517
518 static uas_api_t wifi_api = {
519         .init = init,
520         .deinit = deinit,
521         .get_state = get_state,
522         .get_capability = get_capability,
523         .set_registered_devices = set_registered_devices,
524         .add_device = add_device,
525         .remove_device = remove_device,
526         .start_detection = start_detection,
527         .stop_detection = stop_detection,
528         .set_low_power_mode = set_low_power_mode,
529         .set_detection_window = set_detection_window,
530         .set_detection_threshold = set_detection_threshold,
531         .scan_active_devices = NULL,
532         .cancel_active_device_scan = NULL
533 };
534
535 static int module_init(uas_api_t **api)
536 {
537         FUNC_ENTER;
538
539         *api = &wifi_api;
540
541         FUNC_EXIT;
542         return 0;
543 }
544
545 static int module_deinit(void)
546 {
547         FUNC_ENTER;
548
549         FUNC_EXIT;
550         return 0;
551 }
552
553 UAS_MODULE_ADD(UAS_PLUGIN_ID_WIFI, NAME, AUTHOR, VERSION, module_init, module_deinit);