2 * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 #include <wifi-plugin.h>
25 #include <wifi-plugin-util.h>
26 #include <wifi-scan.h>
27 #include <wifi-networkmanager.h>
29 #define NAME "wifi-plugin"
30 #define AUTHOR "Samsung"
33 #define DETECTION_WINDOW_DEFAULT 60 /* 1 minute -> 1 * 60 = 60 seconds */
34 #define ABSENCE_THRESHOLD_DEFAULT 1
36 static int wifi_detection_window = DETECTION_WINDOW_DEFAULT;
37 static bool initial_bursts = true;
39 static gboolean lpm_enabled = FALSE; /**< Low power mode */
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;
47 static int init(const uas_callbacks_t *callbacks)
51 retv_if(NULL == callbacks, UAS_STATUS_FAIL);
53 if (uas_cbs != NULL) {
54 UA_WIFI_DBG("Wi-Fi plugin is already initialized");
56 return UAS_STATUS_ALREADY_DONE;
63 if (__nm_init() != true) {
64 UA_WIFI_ERR("Fail to initialize network manager");
66 return UAS_STATUS_FAIL;
69 if (__initialize_arp_data() != UAS_STATUS_SUCCESS) {
70 UA_WIFI_ERR("Fail to initialize arp data");
72 return UAS_STATUS_FAIL;
76 return UAS_STATUS_SUCCESS;
79 static int deinit(void)
83 g_slist_free_full(dev_list, g_free);
90 return UAS_STATUS_SUCCESS;
93 static int get_state(int *state)
100 return UAS_STATUS_SUCCESS;
103 static int get_capability(uas_capability_e *capability)
107 retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
109 *capability = UAS_SUPPORT_USER;
112 return UAS_STATUS_SUCCESS;
115 static int set_registered_devices(int num_devices, uas_device_info_t *devices)
118 int i, dev_count = 0;
120 retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
123 g_slist_free_full(dev_list, g_free);
127 for (i = 0; i < num_devices; i++) {
128 uas_wifi_info_t* wifi_info;
130 wifi_info = _wifi_plugin_util_get_wifi_info_from_dev_info(&(devices[i]));
137 wifi_info->mobile_flag = dev_count;
138 dev_list = g_slist_prepend(dev_list, wifi_info);
141 detect_count = dev_count;
143 if (uas_cbs->state_changed_cb) {
144 switch (curr_state) {
145 case UAS_STATE_NOT_READY:
147 uas_cbs->state_changed_cb(UAS_STATE_READY);
148 curr_state = UAS_STATE_READY;
151 case UAS_STATE_READY:
153 uas_cbs->state_changed_cb(UAS_STATE_NOT_READY);
154 curr_state = UAS_STATE_NOT_READY;
161 return UAS_STATUS_SUCCESS;
164 void __check_mobilelist()
170 UA_WIFI_ERR("No devices to scan");
174 for (l = dev_list; NULL != l; l = g_slist_next(l)) {
175 uas_wifi_info_t *wifi_info = l->data;
177 if (wifi_info->mobile_flag != detect_count)
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");
188 initial_bursts = false;
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;
200 UA_WIFI_INFO("Already detected, So skip");
205 __check_mobile_list_finish(false);
208 void __reset_wifi_info()
211 detect_count = g_slist_length(dev_list);
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;
219 static gboolean __start_wifi_scan(gpointer user_data)
223 initial_bursts = true;
225 __check_mobilelist();
227 /* Send detection started */
228 if (uas_cbs && uas_cbs->detection_state_cb)
229 uas_cbs->detection_state_cb(1);
235 void __check_device_found(char* sbuf, char* ip_sbuf)
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;
244 if (wifi_info->mobile_flag == detect_count) {
245 wifi_info->presence = WIFI_PRESENCE_STATUS_PRESENCE;
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);
250 if (!(UAS_PRESENCE & wifi_detection_type))
253 if (!uas_cbs || !uas_cbs->device_detected_cb)
256 /* Send PRESENCE callback */
257 dev_info = _wifi_plugin_util_get_dev_info_from_wifi_info(wifi_info);
259 UA_WIFI_ERR("Unable to get dev_info");
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);
272 void __check_mobile_list_finish(bool is_check)
275 uas_device_info_t *dev_info = NULL;
277 if (is_check == true)
280 UA_WIFI_INFO("find next mobile flag %d", detect_count);
286 UA_WIFI_INFO("Already All mobile detected");
288 initial_bursts = true;
291 UA_WIFI_INFO("Detection mode unicast finish");
293 for (l = dev_list; NULL != l; l = g_slist_next(l)) {
294 uas_wifi_info_t *wifi_info = l->data;
299 if (wifi_info->presence) {
300 wifi_info->presence = WIFI_PRESENCE_STATUS_ABSENCE;
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);
308 UA_WIFI_ERR("Unable to get dev_info");
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);
317 wifi_info->presence = WIFI_PRESENCE_STATUS_ABSENCE;
320 /* Send detection stopped */
321 if (uas_cbs && uas_cbs->detection_state_cb)
322 uas_cbs->detection_state_cb(0);
324 /* Reset detection flags */
325 wifi_detection_type = 0;
327 if (is_check == true) {
328 initial_bursts = true;
329 __check_mobilelist();
336 static gboolean __add_device_send(gpointer data)
339 uas_device_info_t *dev_info = NULL;
341 initial_bursts = true;
343 for (l = dev_list; NULL != l; l = g_slist_next(l)) {
344 uas_wifi_info_t *wifi_info = l->data;
346 if (wifi_info->new_device == true) {
347 wifi_info->new_device = false;
349 if (NULL == uas_cbs || NULL == uas_cbs->device_added_cb) {
350 dev_list = g_slist_remove(dev_list, wifi_info);
355 dev_info = _wifi_plugin_util_get_dev_info_from_wifi_info(wifi_info);
358 UA_WIFI_ERR("Unable to get dev_info");
359 dev_list = g_slist_remove(dev_list, wifi_info);
364 uas_cbs->device_added_cb(UAS_STATUS_SUCCESS, dev_info);
365 _wifi_plugin_util_uas_device_info_free(dev_info);
373 static int add_device(uas_device_info_t *device)
377 uas_wifi_info_t *wifi_info;
381 retv_if(NULL == device, UAS_STATUS_FAIL);
382 retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
384 wifi_info = _wifi_plugin_util_get_wifi_info_from_dev_info(device);
385 retv_if(NULL == wifi_info, UAS_STATUS_FAIL);
387 mac_len = strlen(wifi_info->mac_addr);
388 ip_len = strlen(wifi_info->ip_addr);
389 if (!mac_len && !ip_len) {
392 return UAS_STATUS_FAIL;
395 wifi_info->new_device = true;
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));
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);
410 return UAS_STATUS_SUCCESS;
413 static int remove_device(uas_device_info_t *device)
418 retv_if(NULL == device, UAS_STATUS_FAIL);
419 retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
421 for (l = dev_list; NULL != l; l = g_slist_next(l)) {
422 uas_wifi_info_t *wifi_info = l->data;
424 if (!strcasecmp(wifi_info->mobile_id, device->device_id)) {
425 dev_list = g_slist_remove(dev_list, wifi_info);
427 return UAS_STATUS_SUCCESS;
432 return UAS_STATUS_FAIL;
435 static int start_detection(unsigned int detection_type)
439 retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
440 retv_if((wifi_detection_type & detection_type), UAS_STATUS_ALREADY_DONE);
442 /* Check if detection already in progress */
443 if (0 != wifi_detection_type) {
444 wifi_detection_type |= detection_type;
448 wifi_detection_type |= detection_type;
449 /* Check if lpm enabled */
452 return UAS_STATUS_SUCCESS;
455 /* Start detection */
456 __start_wifi_scan(NULL);
459 UA_WIFI_INFO("wifi_detection_type = 0x%8.8X", wifi_detection_type);
461 return UAS_STATUS_SUCCESS;
464 static int stop_detection(unsigned int detection_type)
468 retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
469 retv_if(0 == wifi_detection_type, UAS_STATUS_ALREADY_DONE);
471 wifi_detection_type &= ~detection_type;
472 UA_WIFI_INFO("wifi_detection_type = 0x%8.8X", wifi_detection_type);
474 if (0 != wifi_detection_type)
479 return UAS_STATUS_SUCCESS;
482 static int set_low_power_mode(int mode)
492 return UAS_STATUS_SUCCESS;
495 static int set_detection_window(unsigned int detection_window)
499 retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
501 wifi_detection_window = detection_window;
504 return UAS_STATUS_SUCCESS;
507 static int set_detection_threshold(int presence_threshold, int absence_threshold)
511 UA_WIFI_INFO("presence_threshold = %d, absence_threshold = %d",
512 presence_threshold, absence_threshold);
515 return UAS_STATUS_UNSUPPORTED;
518 static uas_api_t wifi_api = {
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
535 static int module_init(uas_api_t **api)
545 static int module_deinit(void)
553 UAS_MODULE_ADD(UAS_PLUGIN_ID_WIFI, NAME, AUTHOR, VERSION, module_init, module_deinit);