Change group function operation and parameter
[platform/core/connectivity/wifi-direct-manager.git] / src / wifi-direct-manager.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
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 /**
21  * This file implements wifi direct manager functions.
22  *
23  * @file                wifi-direct-manager.c
24  * @author      Gibyoung Kim (lastkgb.kim@samsung.com)
25  * @version     0.7
26  */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <dlfcn.h>
31 #include <sys/utsname.h>
32 #include <time.h>
33 #include <errno.h>
34
35 #include <glib.h>
36 #include <glib-object.h>
37
38 #include <wifi-direct.h>
39 #include <wifi-direct-internal.h>
40
41 #include "wifi-direct-manager.h"
42 #include "wifi-direct-oem.h"
43 #include "wifi-direct-session.h"
44 #include "wifi-direct-group.h"
45 #include "wifi-direct-peer.h"
46 #include "wifi-direct-state.h"
47 #include "wifi-direct-client.h"
48 #include "wifi-direct-event.h"
49 #include "wifi-direct-util.h"
50
51 wfd_manager_s *g_manager;
52
53 wfd_manager_s *wfd_get_manager()
54 {
55         return g_manager;
56 }
57
58 static gboolean _wfd_exit_timeout_cb(void *user_data)
59 {
60         __WDS_LOG_FUNC_ENTER__;
61         wfd_manager_s *manager = (wfd_manager_s*) user_data;
62
63         if (!manager) {
64                 WDS_LOGE("Invalid parameter");
65                 return TRUE;
66         }
67
68         if (manager->client_count > 0) {
69                 WDS_LOGD("Client count [%d]", manager->client_count);
70                 return TRUE;
71         }
72
73         if (manager->state == WIFI_DIRECT_STATE_DEACTIVATED) {
74                 WDS_LOGD("Terminate Wi-Fi Direct Manager");
75                 g_main_quit(manager->main_loop);
76         }
77         manager->exit_timer = 0;
78         WDS_LOGD( "Stop exit timer. State [%d]", manager->state);
79
80         __WDS_LOG_FUNC_EXIT__;
81         return FALSE;
82 }
83
84 static int _wfd_local_init_device(wfd_manager_s *manager)
85 {
86         __WDS_LOG_FUNC_ENTER__;
87         wfd_device_s *local = NULL;
88         int res = 0;
89
90         if (!manager) {
91                 WDS_LOGE("Invalid parameter");
92                 return -1;
93         }
94
95         errno = 0;
96         local = (wfd_device_s*) calloc(1, sizeof(wfd_device_s));
97         if (!local) {
98                 WDS_LOGE("Failed to allocate memory for local device [%s]", strerror(errno));
99                 return -1;
100         }
101
102         res = wfd_util_get_phone_name(local->dev_name);
103         if (res < 0) {
104                 WDS_LOGE("Failed to get phone name of local device. Use default device name");
105                 strncpy(local->dev_name, DEFAULT_DEVICE_NAME, DEV_NAME_LEN);
106                 local->dev_name[DEV_NAME_LEN] = '\0';
107         }
108         WDS_LOGD("Local Device name [%s]", local->dev_name);
109         wfd_util_set_dev_name_notification();
110
111         res = wfd_util_get_local_dev_mac(local->dev_addr);
112         if (res < 0) {
113                 WDS_LOGE("Failed to get local device MAC address");
114         }
115
116         memcpy(local->intf_addr, local->dev_addr, MACADDR_LEN);
117         local->intf_addr[4] ^= 0x80;
118         WDS_LOGD("Local Interface MAC address [" MACSTR "]", MAC2STR(local->intf_addr));
119
120         local->config_methods = WFD_WPS_MODE_PBC | WFD_WPS_MODE_DISPLAY | WFD_WPS_MODE_KEYPAD;
121         local->wps_mode = WFD_WPS_MODE_PBC;
122         // TODO: initialize other local device datas
123         manager->local = local;
124
125         __WDS_LOG_FUNC_EXIT__;
126         return 0;
127 }
128
129 static int _wfd_local_deinit_device(wfd_manager_s *manager)
130 {
131         __WDS_LOG_FUNC_ENTER__;
132
133         if (!manager) {
134                 WDS_LOGE("Invalid parameter");
135                 return -1;
136         }
137
138         wfd_util_unset_dev_name_notification();
139
140         if (manager->local)
141                 free(manager->local);
142
143         __WDS_LOG_FUNC_EXIT__;
144         return 0;
145 }
146
147 int wfd_local_reset_data(wfd_manager_s *manager)
148 {
149         __WDS_LOG_FUNC_ENTER__;
150         wfd_device_s *local = manager->local;
151
152         /* init local device data */
153         local->dev_role = WFD_DEV_ROLE_NONE;
154         local->wps_mode = WFD_WPS_MODE_PBC;
155         memset(local->go_dev_addr, 0x0, MACADDR_LEN);
156         memset(local->ip_addr, 0x0, IPADDR_LEN);
157
158         __WDS_LOG_FUNC_EXIT__;
159         return 0;
160 }
161
162 int wfd_local_get_dev_name(char *dev_name)
163 {
164         __WDS_LOG_FUNC_ENTER__;
165         wfd_device_s *local = g_manager->local;
166
167         if (!dev_name) {
168                 WDS_LOGE("Invalid parameter");
169                 __WDS_LOG_FUNC_EXIT__;
170                 return -1;
171         }
172
173         strncpy(dev_name, local->dev_name, DEV_NAME_LEN);
174         dev_name[DEV_NAME_LEN-1] = '\0';
175         WDS_LOGD("Local device name [%s]", dev_name);
176
177         __WDS_LOG_FUNC_EXIT__;
178         return 0;
179 }
180
181 int wfd_local_set_dev_name(char *dev_name)
182 {
183         __WDS_LOG_FUNC_ENTER__;
184         wfd_device_s *local = g_manager->local;
185
186         if (!dev_name) {
187                 WDS_LOGE("Invalid parameter");
188                 __WDS_LOG_FUNC_EXIT__;
189                 return -1;
190         }
191
192         strncpy(local->dev_name, dev_name, DEV_NAME_LEN);
193         local->dev_name[DEV_NAME_LEN-1] = '\0';
194
195         if (g_manager->state >= WIFI_DIRECT_STATE_ACTIVATED) {
196                 wfd_oem_set_dev_name(g_manager->oem_ops, dev_name);
197
198                 wfd_oem_scan_param_s param;
199                 param.scan_mode = WFD_OEM_SCAN_MODE_ACTIVE;
200                 param.scan_type = WFD_OEM_SCAN_TYPE_FULL;
201                 param.scan_time = 5;
202                 param.refresh = TRUE;
203                 wfd_oem_start_scan(g_manager->oem_ops, &param);
204                 g_manager->scan_mode = WFD_SCAN_MODE_ACTIVE;
205                 WDS_LOGD("Device name changed. Active scan started");
206         }
207
208         __WDS_LOG_FUNC_EXIT__;
209         return 0;
210 }
211
212 int wfd_local_get_dev_mac(unsigned char *dev_mac)
213 {
214         __WDS_LOG_FUNC_ENTER__;
215         wfd_device_s *local = g_manager->local;
216
217         if (!dev_mac) {
218                 WDS_LOGE("Invalid parameter");
219                 __WDS_LOG_FUNC_EXIT__;
220                 return -1;
221         }
222
223         memcpy(dev_mac, local->dev_addr, MACADDR_LEN);
224         WDS_LOGD("Local device MAC address [" MACSTR "]", MAC2STR(dev_mac));
225
226         __WDS_LOG_FUNC_EXIT__;
227         return 0;
228 }
229
230 int wfd_local_get_intf_mac(unsigned char *intf_mac)
231 {
232         __WDS_LOG_FUNC_ENTER__;
233         wfd_device_s *local = g_manager->local;
234
235         if (!intf_mac) {
236                 WDS_LOGE("Invalid parameter");
237                 __WDS_LOG_FUNC_EXIT__;
238                 return -1;
239         }
240
241         memcpy(intf_mac, local->intf_addr, MACADDR_LEN);
242         WDS_LOGD("Local interface MAC address [" MACSTR "]", MAC2STR(intf_mac));
243
244         __WDS_LOG_FUNC_EXIT__;
245         return 0;
246 }
247
248 int wfd_local_get_ip_addr(char *ip_str)
249 {
250         __WDS_LOG_FUNC_ENTER__;
251         wfd_device_s *local = g_manager->local;
252
253         if (!ip_str) {
254                 WDS_LOGE("Invalid parameter");
255                 __WDS_LOG_FUNC_EXIT__;
256                 return -1;
257         }
258
259         snprintf(ip_str, IPSTR_LEN, IPSTR, IP2STR(local->ip_addr));
260         WDS_LOGD("Local IP address [" IPSTR "]", IP2STR(local->ip_addr));
261
262         __WDS_LOG_FUNC_EXIT__;
263         return 0;
264 }
265
266 int wfd_local_get_supported_wps_mode(int *config_methods)
267 {
268         __WDS_LOG_FUNC_ENTER__;
269         wfd_device_s *local = g_manager->local;
270
271         if (!config_methods) {
272                 WDS_LOGE("Invalid parameter");
273                 __WDS_LOG_FUNC_EXIT__;
274                 return -1;
275         }
276
277         *config_methods = local->config_methods;
278         WDS_LOGD("Local config method [0x%x]", *config_methods);
279
280         __WDS_LOG_FUNC_EXIT__;
281         return 0;
282 }
283
284 int wfd_local_get_wps_mode(int *wps_mode)
285 {
286         __WDS_LOG_FUNC_ENTER__;
287         wfd_device_s *local = g_manager->local;
288
289         if (!wps_mode) {
290                 WDS_LOGE("Invalid parameter");
291                 __WDS_LOG_FUNC_EXIT__;
292                 return -1;
293         }
294
295         *wps_mode = local->wps_mode;
296         WDS_LOGD("Local wps mode [0x%x]", *wps_mode);
297
298         __WDS_LOG_FUNC_EXIT__;
299         return 0;
300 }
301
302 int wfd_local_set_wps_mode(int wps_mode)
303 {
304         __WDS_LOG_FUNC_ENTER__;
305         wfd_device_s *local = g_manager->local;
306
307         if (!wps_mode) {
308                 WDS_LOGE("Invalid parameter");
309                 __WDS_LOG_FUNC_EXIT__;
310                 return -1;
311         }
312
313         local->wps_mode = wps_mode;
314         WDS_LOGD("Local wps mode [0x%x]", wps_mode);
315
316         __WDS_LOG_FUNC_EXIT__;
317         return 0;
318 }
319
320 int wfd_manager_get_go_intent(int *go_intent)
321 {
322         __WDS_LOG_FUNC_ENTER__;
323         if (!go_intent) {
324                 WDS_LOGE("Invalid parameter");
325                 __WDS_LOG_FUNC_EXIT__;
326                 return -1;
327         }
328
329         *go_intent = g_manager->go_intent;
330         WDS_LOGD("Local GO intent [%d]", *go_intent);
331
332         __WDS_LOG_FUNC_EXIT__;
333         return 0;
334 }
335
336 int wfd_manager_set_go_intent(int go_intent)
337 {
338         __WDS_LOG_FUNC_ENTER__;
339
340         if (go_intent < 0 || go_intent > 15) {
341                 WDS_LOGE("Invalid parameter");
342                 __WDS_LOG_FUNC_EXIT__;
343                 return -1;
344         }
345
346         g_manager->go_intent = go_intent;
347         if (g_manager->state >= WIFI_DIRECT_STATE_ACTIVATED)
348                 wfd_oem_set_go_intent(g_manager->oem_ops, go_intent);
349
350         __WDS_LOG_FUNC_EXIT__;
351         return 0;
352 }
353
354 int wfd_manager_get_max_station(int *max_station)
355 {
356         __WDS_LOG_FUNC_ENTER__;
357
358         if (!max_station) {
359                 WDS_LOGE("Invalid parameter");
360                 __WDS_LOG_FUNC_EXIT__;
361                 return -1;
362         }
363
364         *max_station = g_manager->max_station;
365         WDS_LOGD("Local max station[%d]", *max_station);
366
367         __WDS_LOG_FUNC_EXIT__;
368         return 0;
369 }
370
371 int wfd_manager_set_max_station(int max_station)
372 {
373         __WDS_LOG_FUNC_ENTER__;
374
375         if (max_station < 1) {
376                 WDS_LOGE("Invalid parameter");
377                 __WDS_LOG_FUNC_EXIT__;
378                 return -1;
379         }
380
381         g_manager->max_station = max_station;
382
383         __WDS_LOG_FUNC_EXIT__;
384         return 0;
385 }
386
387 int wfd_manager_get_autoconnection(int *autoconnection)
388 {
389         __WDS_LOG_FUNC_ENTER__;
390         if (!autoconnection) {
391                 WDS_LOGE("Invalid parameter");
392                 __WDS_LOG_FUNC_EXIT__;
393                 return -1;
394         }
395
396         *autoconnection = g_manager->autoconnection;
397         WDS_LOGD("Local autoconnection [%s]", *autoconnection ? "TRUE":"FALSE");
398
399         __WDS_LOG_FUNC_EXIT__;
400         return 0;
401 }
402
403 int wfd_manager_set_autoconnection(int autoconnection)
404 {
405         __WDS_LOG_FUNC_ENTER__;
406         if (autoconnection < 0) {
407                 WDS_LOGE("Invalid parameter");
408                 __WDS_LOG_FUNC_EXIT__;
409                 return -1;
410         }
411
412         g_manager->autoconnection = autoconnection;
413
414         __WDS_LOG_FUNC_EXIT__;
415         return 0;
416 }
417
418 int wfd_manager_get_req_wps_mode(int *req_wps_mode)
419 {
420         __WDS_LOG_FUNC_ENTER__;
421
422         if (!req_wps_mode) {
423                 WDS_LOGE("Invalid parameter");
424                 __WDS_LOG_FUNC_EXIT__;
425                 return -1;
426         }
427
428         *req_wps_mode = g_manager->req_wps_mode;
429         WDS_LOGD("Requested wps mode [0x%x]", *req_wps_mode);
430
431         __WDS_LOG_FUNC_EXIT__;
432         return 0;
433 }
434
435 int wfd_manager_set_req_wps_mode(int req_wps_mode)
436 {
437         __WDS_LOG_FUNC_ENTER__;
438         wfd_device_s *local = g_manager->local;
439
440         if (req_wps_mode != WIFI_DIRECT_WPS_TYPE_PBC &&
441                         req_wps_mode != WIFI_DIRECT_WPS_TYPE_PIN_DISPLAY &&
442                         req_wps_mode != WIFI_DIRECT_WPS_TYPE_PIN_KEYPAD) {
443                 WDS_LOGE("Invalid parameter");
444                 __WDS_LOG_FUNC_EXIT__;
445                 return -1;
446         }
447
448         g_manager->req_wps_mode = req_wps_mode;
449         WDS_LOGD("Requested wps mode [0x%x]", req_wps_mode);
450         if (req_wps_mode == WFD_WPS_MODE_DISPLAY)
451                 local->wps_mode = WFD_WPS_MODE_KEYPAD;
452         else if (req_wps_mode == WFD_WPS_MODE_KEYPAD)
453                 local->wps_mode = WFD_WPS_MODE_DISPLAY;
454         else
455                 local->wps_mode = req_wps_mode;
456
457         __WDS_LOG_FUNC_EXIT__;
458         return 0;
459 }
460
461 int wfd_manager_local_config_set(wfd_manager_s *manager)
462 {
463         __WDS_LOG_FUNC_ENTER__;
464         wfd_device_s *local = NULL;
465         int res = 0;
466
467         if (!manager) {
468                 WDS_LOGE("Invalid parameter");
469                 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
470         }
471
472         local = manager->local;
473
474         local->wps_mode = WFD_WPS_MODE_PBC;
475         WDS_LOGD("Device name set as %s", local->dev_name);
476         wfd_oem_set_dev_type(manager->oem_ops, local->pri_dev_type, local->sec_dev_type);
477         wfd_oem_set_go_intent(manager->oem_ops, manager->go_intent);
478         wfd_oem_set_dev_name(manager->oem_ops, local->dev_name);
479
480         return WIFI_DIRECT_ERROR_NONE;
481 }
482
483 int wfd_manager_activate(wfd_manager_s *manager)
484 {
485         __WDS_LOG_FUNC_ENTER__;
486         int res = 0;
487
488         if (!manager) {
489                 WDS_LOGE("Invalid parameter");
490                 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
491         }
492
493         if (manager->state > WIFI_DIRECT_STATE_ACTIVATING) {
494                 WDS_LOGE("Already activated");
495                 return 1;
496         }
497
498         wfd_state_set(manager, WIFI_DIRECT_STATE_ACTIVATING);
499
500         res = wfd_oem_activate(manager->oem_ops);
501         if (res < 0) {
502                 WDS_LOGE("Failed to activate");
503                 wfd_state_set(manager, WIFI_DIRECT_STATE_DEACTIVATED);
504                 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
505         }
506         WDS_LOGE("Succeeded to activate");
507
508         wfd_state_set(manager, WIFI_DIRECT_STATE_ACTIVATED);
509         wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_ACTIVATED);
510
511         __WDS_LOG_FUNC_EXIT__;
512         return WIFI_DIRECT_ERROR_NONE;
513 }
514
515 int wfd_manager_deactivate(wfd_manager_s *manager)
516 {
517         __WDS_LOG_FUNC_ENTER__;
518         int res = 0;
519
520         if (!manager) {
521                 WDS_LOGE("Invalid parameter");
522                 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
523         }
524
525         if (manager->state < WIFI_DIRECT_STATE_ACTIVATING) {
526                 WDS_LOGE("Already deactivated");
527                 return WIFI_DIRECT_ERROR_NOT_PERMITTED;
528         }
529
530         wfd_state_set(manager, WIFI_DIRECT_STATE_DEACTIVATING);
531
532         res = wfd_oem_deactivate(manager->oem_ops);
533         if (res < 0) {
534                 WDS_LOGE("Failed to deactivate");
535                 // TODO: check state setting is correct
536                 wfd_state_set(manager, WIFI_DIRECT_STATE_ACTIVATED);
537                 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
538         }
539         WDS_LOGE("Succeeded to deactivate");
540
541         wfd_state_set(manager, WIFI_DIRECT_STATE_DEACTIVATED);
542         wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_DEACTIVATED);
543
544         manager->req_wps_mode = WFD_WPS_MODE_PBC;
545
546         __WDS_LOG_FUNC_EXIT__;
547         return WIFI_DIRECT_ERROR_NONE;
548 }
549
550 int wfd_manager_connect(wfd_manager_s *manager, unsigned char *peer_addr)
551 {
552         __WDS_LOG_FUNC_ENTER__;
553         wfd_session_s *session = NULL;
554         int res = 0;
555
556         if (!manager || !peer_addr) {
557                 WDS_LOGE("Invalid parameter");
558                 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
559         }
560
561         session = (wfd_session_s*) manager->session;
562         if (session && session->type != SESSION_TYPE_INVITE) {
563                 WDS_LOGE("Session already exist or not an invitaion session");
564                 return WIFI_DIRECT_ERROR_NOT_PERMITTED;
565         }
566
567         if (!session) {
568                 session = wfd_create_session(manager, peer_addr,
569                                         manager->req_wps_mode, SESSION_DIRECTION_OUTGOING);
570                 if (!session) {
571                         WDS_LOGE("Failed to create new session");
572                         return WIFI_DIRECT_ERROR_OPERATION_FAILED;
573                 }
574         }
575
576         if (manager->local->dev_role == WFD_DEV_ROLE_GO && session->type != SESSION_TYPE_INVITE) {
577                 session->type = SESSION_TYPE_INVITE;
578                 res = wfd_session_invite(session);
579         } else {
580                 /* joining to group or starting connection with PD */
581                 /* In case of invitation session PD should be started
582                  * peer->dev_role == WFD_DEV_ROLE_GO
583                  * session->direction == SESSION_DIRECTION_INCOMING
584                  * session->invitation == TRUE;
585                  */
586                 res = wfd_session_start(session);
587         }
588         if (res < 0) {
589                 WDS_LOGE("Failed to start session");
590                 wfd_destroy_session(manager);
591                 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
592         }
593         wfd_state_set(manager, WIFI_DIRECT_STATE_CONNECTING);
594
595         __WDS_LOG_FUNC_EXIT__;
596         return WIFI_DIRECT_ERROR_NONE;
597 }
598
599 int wfd_manager_accept_connection(wfd_manager_s *manager, unsigned char *peer_addr)
600 {
601         __WDS_LOG_FUNC_ENTER__;
602         wfd_session_s *session = NULL;
603         wfd_device_s *peer = NULL;
604         int res = 0;
605
606         if (!manager || !peer_addr) {
607                 WDS_LOGE("Invalid parameter");
608                 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
609         }
610
611         session = (wfd_session_s*) manager->session;
612         if (!session) {
613                 WDS_LOGE("Session not found");
614                 return WIFI_DIRECT_ERROR_NOT_PERMITTED;
615         }
616
617         peer = wfd_peer_find_by_dev_addr(manager, peer_addr);
618         if (!peer) {
619                 WDS_LOGE("Peer is NULL");
620                 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
621         }
622
623         // TODO: check peer_addr with session's peer_addr
624
625         if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
626                 /* Peer want to join my group(Peer sent PD) */
627                 WDS_LOGD("My device is GO and peer want to join my group, so WPS will be started");
628                 res = wfd_session_wps(session);
629         } else if (peer->dev_role == WFD_DEV_ROLE_GO) {
630                 /* FIX ME: When Enter PIN or Display event comes up from supplicant
631                  * manager send Connection WPS Req event to client.
632                  * So, application use accept_connection API.
633                  * This is odd situation. We need new client event such as WPS_KEYPAD/WPS_DISPLAY for application.
634                  * We can correct alien code below with new client event */
635                 if (session->direction == SESSION_DIRECTION_OUTGOING) {
636                         WDS_LOGD("Peer device is GO, WPS_Enrollee will be started");
637                         wfd_session_wps(manager->session);
638                 } else {
639                         WDS_LOGD("Peer device is GO, so Prov_Disc will be started");
640                         wfd_session_start(session);
641                 }
642         } else {
643                 /* Prov_disc_req received. GO Negotiation will be started */
644                 WDS_LOGD("My device is Device, so Negotiation will be started");
645                 res = wfd_session_connect(session);
646         }
647         if (res < 0) {
648                 WDS_LOGE("Failed to start session");
649                 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
650         }
651         wfd_state_set(manager, WIFI_DIRECT_STATE_CONNECTING);
652
653         __WDS_LOG_FUNC_EXIT__;
654         return WIFI_DIRECT_ERROR_NONE;
655 }
656
657
658 int wfd_manager_get_peers(wfd_manager_s *manager, wfd_discovery_entry_s **peers_data)
659 {
660         __WDS_LOG_FUNC_ENTER__;
661         GList *temp = NULL;
662         wfd_device_s *peer = NULL;
663         wfd_discovery_entry_s *peers = NULL;
664         int peer_count = 0;
665         int count = 0;
666         int res = 0;
667
668         if (!manager || !peers_data) {
669                 WDS_LOGE("Invalid parameter");
670                 return -1;
671         }
672
673         unsigned long time = 0;
674         struct timeval tval;
675         gettimeofday(&tval, NULL);
676         time = tval.tv_sec;
677         WDS_LOGI("Current time [%ld]", time);
678
679         peer_count = manager->peer_count;
680         if (peer_count < 0)
681                 return -1;
682         else if (peer_count == 0)
683                 return 0;
684
685         errno = 0;
686         peers = (wfd_discovery_entry_s*) calloc(peer_count, sizeof(wfd_discovery_entry_s));
687         if (!peers) {
688                 WDS_LOGF("Failed to allocate memory for peer data. [%s]", strerror(errno));
689                 return -1;
690         }
691
692         temp = g_list_first(manager->peers);
693         while (temp && count < peer_count) {
694                 peer = temp->data;
695                 if (!peer)
696                         goto next;
697                 if (peer->time + 4 < time) {
698                         WDS_LOGD("Device data is too old to report to application [%s]", peer->dev_name);
699                         res = wfd_update_peer(manager, peer);
700                         if (res < 0) {
701                                 WDS_LOGE("This device is disappeared [%s]", peer->dev_name);
702                                 temp = g_list_next(temp);
703                                 manager->peers = g_list_remove(manager->peers, peer);
704                                 manager->peer_count--;
705                                 free(peer);
706                                 peer = NULL;
707                                 continue;
708                         }
709                 }
710
711                 strncpy(peers[count].device_name, peer->dev_name, DEV_NAME_LEN);
712                 peers[count].device_name[DEV_NAME_LEN] = '\0';
713                 memcpy(peers[count].mac_address, peer->dev_addr, MACADDR_LEN);
714                 memcpy(peers[count].intf_address, peer->intf_addr, MACADDR_LEN);
715                 peers[count].channel = peer->channel;
716                 peers[count].services = 0;
717                 peers[count].is_group_owner = peer->dev_role == WFD_DEV_ROLE_GO;
718                 peers[count].is_persistent_go = peer->group_flags & WFD_OEM_GROUP_FLAG_PERSISTENT_GROUP;
719                 peers[count].is_connected = peer->dev_role == WFD_DEV_ROLE_GC;
720                 peers[count].wps_device_pwd_id = 0;
721                 peers[count].wps_cfg_methods = peer->config_methods;
722                 peers[count].category = peer->pri_dev_type;
723                 peers[count].subcategory = peer->sec_dev_type;
724
725                 count++;
726                 WDS_LOGD("%dth peer [%s]", count, peer->dev_name);
727 next:
728                 temp = g_list_next(temp);
729                 peer = NULL;
730         }
731         WDS_LOGD("%d peers converted", count);
732         WDS_LOGD("Final peer count is %d", manager->peer_count);
733
734         *peers_data = peers;
735
736         __WDS_LOG_FUNC_EXIT__;
737         return count;
738 }
739
740 int wfd_manager_get_connected_peers(wfd_manager_s *manager, wfd_connected_peer_info_s **peers_data)
741 {
742         __WDS_LOG_FUNC_ENTER__;
743         wfd_connected_peer_info_s *peers = NULL;
744         wfd_group_s *group = NULL;
745         wfd_device_s *peer = NULL;
746         GList *temp = NULL;
747         int peer_count = 0;
748         int count = 0;
749
750         if (!manager || !peers_data) {
751                 WDS_LOGE("Invalid parameter");
752                 return -1;
753         }
754
755         group = manager->group;
756         if (!group) {
757                 WDS_LOGE("Group not exist");
758                 return -1;
759         }
760
761         peer_count = group->member_count;
762         if (peer_count == 0) {
763                 WDS_LOGD("Member not exist");
764                 return 0;
765         }
766
767         errno = 0;
768         peers = (wfd_connected_peer_info_s*) calloc(peer_count, sizeof(wfd_connected_peer_info_s));
769         if (!peers) {
770                 WDS_LOGE("Failed to allocate memory for connected peer data. [%s]", strerror(errno));
771                 return -1;
772         }
773
774         temp = g_list_first(group->members);
775         while (temp && count < group->member_count) {
776                 peer = temp->data;
777                 {
778                         strncpy(peers[count].device_name, peer->dev_name, DEV_NAME_LEN);
779                         peers[count].device_name[DEV_NAME_LEN] = '\0';
780                         memcpy(peers[count].mac_address, peer->dev_addr, MACADDR_LEN);
781                         memcpy(peers[count].intf_address, peer->intf_addr, MACADDR_LEN);
782                         memcpy(peers[count].ip_address, peer->ip_addr, IPADDR_LEN);
783                         peers[count].category = peer->pri_dev_type;
784                         peers[count].subcategory = peer->sec_dev_type;
785                         peers[count].channel = peer->channel;
786                         peers[count].is_p2p = 1;
787                         peers[count].services = 0;
788                         WDS_LOGD("%dth member converted[%s]", count, peers[count].device_name);
789                         count++;
790                 }
791                 temp = g_list_next(temp);
792                 peer = NULL;
793         }
794         WDS_LOGD("%d members converted", count);
795
796         *peers_data = peers;
797
798         __WDS_LOG_FUNC_EXIT__;
799         return count;
800 }
801
802 wfd_device_s *wfd_manager_find_connected_peer(wfd_manager_s *manager, unsigned char *peer_addr)
803 {
804         __WDS_LOG_FUNC_ENTER__;
805         wfd_device_s *peer = NULL;
806
807         if (!manager || !peer_addr) {
808                 WDS_LOGE("Invalid parameter");
809                 return NULL;
810         }
811
812         peer = wfd_group_find_member_by_addr(manager->group, peer_addr);
813
814         __WDS_LOG_FUNC_EXIT__;
815         return peer;
816 }
817
818 wfd_device_s *wfd_manager_get_current_peer(wfd_manager_s *manager)
819 {
820         __WDS_LOG_FUNC_ENTER__;
821         wfd_session_s *session = NULL;
822
823         if (!manager) {
824                 WDS_LOGE("Invalid parameter");
825                 __WDS_LOG_FUNC_EXIT__;
826                 return NULL;
827         }
828
829         session = manager->session;
830         if (session && session->peer) {
831                 __WDS_LOG_FUNC_EXIT__;
832                 return session->peer;
833         }
834
835         __WDS_LOG_FUNC_EXIT__;
836         return NULL;
837 }
838
839 int wfd_manager_get_goup_ifname(char **ifname)
840 {
841         __WDS_LOG_FUNC_ENTER__;
842         wfd_group_s *group = g_manager->group;
843
844         if (!ifname) {
845                 WDS_LOGE("Invalid parameter");
846                 __WDS_LOG_FUNC_EXIT__;
847                 return -1;
848         }
849
850         if (!group) {
851                 WDS_LOGE("Group not exist");
852                 return -1;
853         }
854
855         *ifname = group->ifname;
856
857         __WDS_LOG_FUNC_EXIT__;
858         return 0;
859 }
860
861 static wfd_manager_s *wfd_manager_init()
862 {
863         __WDS_LOG_FUNC_ENTER__;
864         wfd_manager_s *manager = NULL;
865         int res = 0;
866
867         manager = (wfd_manager_s*) calloc(1, sizeof(wfd_manager_s));
868         if (!manager) {
869                 WDS_LOGE("Failed to allocate memory for wfd_manager structure");
870                 return NULL;
871         }
872
873         manager->go_intent = 7;
874         manager->req_wps_mode = WFD_WPS_MODE_PBC;
875         manager->max_station = 8;
876
877         res = _wfd_local_init_device(manager);
878         if (res < 0) {
879                 WDS_LOGE("Failed to initialize local device");
880                 free(manager);
881                 return NULL;            // really stop manager?
882         }
883         WDS_LOGD("Succeeded to initialize local device");
884
885         manager->exit_timer = g_timeout_add(120000,
886                                                 (GSourceFunc) _wfd_exit_timeout_cb, manager);
887         WDS_LOGD("Exit timer started");
888
889         __WDS_LOG_FUNC_EXIT__;
890         return manager;
891 }
892
893 int wfd_manager_deinit(wfd_manager_s *manager)
894 {
895         __WDS_LOG_FUNC_ENTER__;
896
897         if (!manager) {
898                 WDS_LOGE("Invalid parameter");
899                 __WDS_LOG_FUNC_EXIT__;
900                 return -1;
901         }
902
903         if (manager->exit_timer > 0)
904                 g_source_remove(manager->exit_timer);
905         manager->exit_timer = 0;
906
907         _wfd_local_deinit_device(manager);
908
909         if (manager)
910                 free(manager);
911
912         __WDS_LOG_FUNC_EXIT__;
913         return 0;
914 }
915
916 static void *wfd_plugin_init(wfd_manager_s *manager)
917 {
918         __WDS_LOG_FUNC_ENTER__;
919         void *handle;
920         struct utsname kernel_info;
921         int res;
922
923         if (!manager) {
924                 WDS_LOGE("Invalid parameter");
925                 __WDS_LOG_FUNC_EXIT__;
926                 return NULL;
927         }
928
929         res = uname(&kernel_info);
930         if (res) {
931                 WDS_LOGE("Failed to detect target type");
932                 __WDS_LOG_FUNC_EXIT__;
933                 return NULL;
934         }
935         WDS_LOGD("Node name [%s], HW ID [%s]", kernel_info.nodename, kernel_info.machine);
936
937         errno = 0;
938         handle = dlopen(SUPPL_PLUGIN_PATH, RTLD_NOW);
939         if (!handle) {
940                 WDS_LOGE("Failed to open shared object. [%s]", dlerror());
941                 __WDS_LOG_FUNC_EXIT__;
942                 return NULL;
943         }
944
945         errno = 0;
946         int (*plugin_load)(wfd_oem_ops_s **ops) = NULL;
947         plugin_load = (int (*)(wfd_oem_ops_s **ops)) dlsym(handle, "wfd_plugin_load");
948         if (!plugin_load) {
949                 WDS_LOGE( "Failed to load symbol. Error = [%s]", strerror(errno));
950                 dlclose(handle);
951                 __WDS_LOG_FUNC_EXIT__;
952                 return NULL;
953         }
954
955         wfd_oem_ops_s *temp_ops;
956         (*plugin_load)(&temp_ops);
957         manager->oem_ops = temp_ops;
958
959         res = wfd_oem_init(temp_ops, (wfd_oem_event_cb) wfd_process_event, manager);
960         if (res < 0) {
961                 WDS_LOGE("Failed to initialize OEM");
962                 dlclose(handle);
963                 __WDS_LOG_FUNC_EXIT__;
964                 return NULL;
965         }
966         WDS_LOGD("Succeeded to initialize OEM");
967
968         __WDS_LOG_FUNC_EXIT__;
969         return handle;
970 }
971
972 static int wfd_plugin_deinit(wfd_manager_s *manager)
973 {
974         __WDS_LOG_FUNC_ENTER__;
975
976         if (!manager || !manager->plugin_handle) {
977                 WDS_LOGE("Invalid parameter");
978                 __WDS_LOG_FUNC_EXIT__;
979                 return -1;
980         }
981
982         dlclose(manager->plugin_handle);
983         manager->plugin_handle = NULL;
984
985         __WDS_LOG_FUNC_EXIT__;
986         return 0;
987 }
988
989 int main(int argc, char *argv[])
990 {
991         __WDS_LOG_FUNC_ENTER__;
992         GMainLoop *main_loop = NULL;
993         int res = 0;
994
995         if (!g_thread_supported())
996                 g_thread_init(NULL);
997
998         g_type_init();
999
1000         // TODO: Parsing argument
1001         /* Wi-Fi direct connection for S-Beam can be optimized using argument */
1002
1003         g_manager = wfd_manager_init();
1004         if (!g_manager) {
1005                 WDS_LOGE("Failed to initialize wifi-direct manager");
1006                 __WDS_LOG_FUNC_EXIT__;
1007                 return -1;
1008         }
1009         WDS_LOGD("Succeeded to initialize manager");
1010
1011         g_manager->plugin_handle = wfd_plugin_init(g_manager);
1012         if (!g_manager->plugin_handle) {
1013                 WDS_LOGE("Failed to initialize plugin");
1014                 wfd_manager_deinit(g_manager);
1015                 __WDS_LOG_FUNC_EXIT__;
1016                 return -1;
1017         }
1018         WDS_LOGD("Succeeded to load plugin");
1019
1020         res = wfd_client_handler_init(g_manager);
1021         if (res < 0) {
1022                 WDS_LOGE("Failed to initialize client handler");
1023                 wfd_plugin_deinit(g_manager);
1024                 wfd_manager_deinit(g_manager);
1025                 __WDS_LOG_FUNC_EXIT__;
1026                 return -1;
1027         }
1028         WDS_LOGD("Succeeded to initialize client handler");
1029
1030         main_loop = g_main_loop_new(NULL, FALSE);
1031         if (main_loop == NULL) {
1032                 WDS_LOGE("Failed to create GMainLoop structure");
1033                 __WDS_LOG_FUNC_EXIT__;
1034                 return -1;
1035         }
1036         g_manager->main_loop = main_loop;
1037
1038         g_main_loop_run(main_loop);
1039
1040         wfd_client_handler_deinit(g_manager);
1041         wfd_plugin_deinit(g_manager);
1042         wfd_manager_deinit(g_manager);
1043
1044         __WDS_LOG_FUNC_EXIT__;
1045         return 0;
1046 }